C4996 (function unsafe) warning for strcpy but not for memcpy
Asked Answered
T

7

4

I am writing code in VS2010 and I happen to see after compilation compiler gives me C4996 warning ("This function or variable may be unsafe") for strcpy and sprintf calls.

However, I couldn't get similar warnings for memcpy (and may be there are few more similar 'unsafe' function calls in the code)

int _tmain(int argc, _TCHAR* argv[])
{
    char buf1[100], buf2[100];
    strcpy (buf1, buf2); // Warning C4996 displayed here asking to use strcpy_s instead
    memcpy (buf1, buf2, 100); // No warning here asking to use memcpy_s
    memcpy_s(buf1, 100, buf2, 100);
    return 0;
}

Why is this so? How can I turn on C4996 warning for all possible unsafe calls in my code?

Takin answered 6/5, 2014 at 5:56 Comment(2)
Post some code please.Hades
strcpy and memcpy are C constructs, not C++. C++ uses std::string and std::vector for strings and memory buffers. You've added the wrong tag.Temperature
U
21

In general, to compile C code you need a conforming C compiler. Visual Studio is a non-conforming C++ compiler.

You get the warning because Visual Studio is bad. See this.

C4996 appears whenever you use a function that Microsoft regards as obsolete. Apparently, Microsoft has decided that they should dictate the future of the C language, rather than the ISO C working group. Thus you get false warnings for perfectly fine code. The compiler is the problem.

There is nothing wrong with the strcpy() function, that's a myth. This function has existed for some 30-40 years and every little bit of it is properly documented. So what the function does and what it does not should not come as a surprise, even to beginner C programmers.

What strcpy does and does not:

  • It copies a null-terminated string into another memory location.
  • It does not take any responsibility for error handling.
  • It does not fix bugs in the caller application.
  • It does not take any responsibility for educating C programmers.

Because of the last remark above, you must know the following before calling strcpy:

  • If you pass a string of unknown length to strcpy, without checking its length in advance, you have a bug in the caller application.
  • If you pass some chunk of data which does not end with \0, you have a bug in the caller application.
  • If you pass two pointers to strcpy(), which point at memory locations that overlap, you invoke undefined behavior. Meaning you have a bug in the caller application.

For example, in the code you posted, you never initialized the arrays, so your program will likely crash and burn. That bug isn't in the slightest related to the strcpy() function and will not be solved by swapping out strcpy() for something else.

Universally answered 6/5, 2014 at 8:49 Comment(1)
For the sake of nitpicking, it is actually conforming behaviour to produce more diagnostics than required, and GCC & Clang also do this all the time. Quoting C11 §5.1.1.3 note: "Of course, an implementation is free to produce any number of diagnostics as long as a valid program is still correctly translated."Oria
H
6

strcpy is unsafe if the terminating NUL is missing, as it may copy more characters than fit in the destination area. With memcpy, the number of bytes copied is fixed.

The memcpy_s function actually makes it easier for programmers to do it wrong -- you pass two lengths, and it uses the smaller of both, and all you get is an error code that can be silently ignored with no effort. Calling memcpy requires filling out the size parameter, which should make programmers think about what to pass.

Hexagon answered 6/5, 2014 at 6:2 Comment(1)
Any C function is unsafe if you pass garbage parameters to it.Universally
N
2

Include in header "stdafx.h" definition

#define _CRT_SECURE_NO_WARNINGS

As for the difference of strcpy and memcpy then the last function has third parameter that explicitly specifies how many characters must be copied. The first function has no information how many characters will be copied from the source string to the destination string so in general case there is a possibility that the memory allocated for the destination string will be overwritten.

Numb answered 6/5, 2014 at 6:4 Comment(0)
T
1

You get these warning because not passing the length of string and relying on \0 termination are unsafe as they may cause buffer overrun. In memcpy you pass length so no overrun issue.

You can use something like

#ifdef _MSC_VER
#  pragma warning(push)
#  pragma warning(disable:4996)
#endif
strcpy... ;  // Code that causes unsafe warning
#ifdef _MSC_VER
#  pragma warning(pop)
#endif

If you don't worry about portability, you can use alternatives like strcpy_s etc

Twentyfourmo answered 6/5, 2014 at 6:0 Comment(0)
T
0

The reason why you get a warning on sprintf and strcpy, and not on memcpy, is because memcpy has a length parameter that limits how much memory you copy. For strcpy and memcpy, the input has to be terminated with a \0. If not, it will continue out of bounds. You can limit this by using the snprintf and strncpy functions. Those do limit implicitly how much can be copied.

Note that microsoft has deprecated snprintf, so you should use the replacement function _snprintf instead. However, this is a MSVC specific function.

I would advise to do away with char * buffers all together and switch to C++, using stl container, such as std::string. These will save you a lot of debugging headaches and keep your code portable.

Temperature answered 6/5, 2014 at 6:9 Comment(2)
I would love to replace existing C code with STL calls. But would there be any performance penalty? (E.g. using vector assignments instead of memcpy etc.)Takin
Does that even matter? Generally speaking most code is not on a critical path and then readability/maintainability is often way more important than those few nanoseconds you gain. Next to that, no, for many usecases there is no or only a negligible performance difference when using the std library.Curst
P
-1

Because strcpy and sprintf really are unsafe functions, it depends on the content of the string to not overflow. Instead you should use strncpy and snprintf to make sure it does not overwrite the memory.

While memcpy is not this case, it has the length so it does not overwrite memory as long as the length is correct.

Papillose answered 6/5, 2014 at 6:2 Comment(2)
Eh, my comment had some weird errors. Since I can't edit it, I'll delete it and repost it below:Universally
-1 This is nonsense. First of all, there is nothing wrong with strcpy. Second, strncpy was never intended as a safe version of strcpy. strncpy, unlike strcpy, is a dangerous function! It was only ever intended for a weird, obsolete string format used on old Unix machines. Do not use it.Universally
S
-1

The warning meens that the function is deprecated and you should not use it without understanding the consequences: http://msdn.microsoft.com/en-US/en-en/library/ttcz0bys.aspx You can't add other functions to the deprecate list of Microsoft.

The reason for the deprecation are "unsafe", but that's different from your assumption "C4496 shows you all unsafe functions".

Savoie answered 6/5, 2014 at 6:2 Comment(1)
While the MSDN pages may officially call it deprecation, it's very unlikely these functions will ever be actually removed as they're part of the standard.Curst

© 2022 - 2024 — McMap. All rights reserved.