Skip to main content
gamedev.net
🔒 Locked

strncpy deprecated - Visual C++ 2005 - "Say Goodbye to an old friend"

Started by paulecoyote 27 replies 15k views
Original Post
paulecoyote
paulecoyote
So I was compiling something in Visual C++ 2005 just now and I have a this warning pop up:
warning C4996: 'strncpy' was declared deprecated Message: 'This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.'
So I go to the help and look up what is going on, and it directs me here... MSDN Link ... so basically MS have recommended a change to the core libraries, and gone ahead and implemented it anyway in their latest release. Classic MS move. Anyway is anyone actually using these new functions appended with _s? (eg strncpy_s). It strikes me that using them makes your code platform, or even compiler / library specific. Anyone aware of any progress since then? I realise this has probably been brought up before (not seen recently myself) but I was wondering if anything new recently has happened with that stuff?
Anything posted is personal opinion which does not in anyway reflect or represent my employer. Any code and opinion is expressed “as is” and used at your own risk – it does not constitute a legal relationship of any kind.
doynax
doynax
Can't say I'll miss strncpy, it was pretty useless and horribly misleading to begin with. But the deprecation fopen is just plain annoying, why can't they place errno in thread-local storage or do whatever GCC did?.
I can't quite figure out why it's started to complain about certain std::copy calls either..

I guess we'll just have to disable the warnings for now, using the alternative versions just isn't an option if you want to write portable code.
_the_phantom_
_the_phantom_
*chuckles* I find it intresting that MS gets moaned at for insecure software and yet, when they do something to help fix the problem they still get moaned at [grin] (this is probably part of the motivation for giving away the EE of VS05 as well)

As for the functions, are there any differences between the signatures of strncpy and strncpy_s ? If not then the solution would seem to me to be either (a) #define trickery based on platform or (b) assign the correct one to a function pointer on start up.

If the call signature is different then I guess you'll have to find a way to seperate out the functions or call sites for them into seperate modules and let your build system only build the right one, as you would any platform dependant code.

@doynax
There is a 'safe' version of std::copy and other functions as well iirc, you'll want to check Washu's journal as that has a nice entry on the safe std. lib stuff [smile]
doynax
doynax
Quote:
Original post by phantom
*chuckles* I find it intresting that MS gets moaned at for insecure software and yet, when they do something to help fix the problem they still get moaned at [grin] (this is probably part of the motivation for giving away the EE of VS05 as well)
Yes, but we like complaining about problems in other people's code, not fixing our own projects ;)
Besides, you should expect to get bashed for any 'breaking' changes.
So don't go around deprecating the standard library until ANSI says so..
Quote:
Original post by phantom
As for the functions, are there any differences between the signatures of strncpy and strncpy_s ? If not then the solution would seem to me to be either (a) #define trickery based on platform or (b) assign the correct one to a function pointer on start up.
Yes, but they perform different functions (strncpy doesn't always null terminate the string). Otherwise what would be the point of writing a new one?
Quote:
Original post by phantom
There is a 'safe' version of std::copy and other functions as well iirc, you'll want to check Washu's journal as that has a nice entry on the safe std. lib stuff [smile]
I'm aware of the safe standard library, and Microsofts has had it for ages. But it's still a major pain for those of us wanting to write portable code..

I guess I'll just globally define _CRT_SECURE_NO_DEPRECATE. So it really isn't that hard to fix, just annoying.
_the_phantom_
_the_phantom_
Well, the change isnt really 'breaking', your code still compiles, but unless you tell them you know what you are doing its going to warn you about it.

Its just MS trying to enforce safe coding on their platform and considering the amount of flakk they get when stuff breaks due to poor coding who can blame them?
paulecoyote
paulecoyote
Quote:
Original post by phantom
*chuckles* I find it intresting that MS gets moaned at for insecure software and yet, when they do something to help fix the problem they still get moaned at [grin] (this is probably part of the motivation for giving away the EE of VS05 as well)


Yeah. I'm not moaning, more of concerned. Stuff still compiles and everything, just new warnings. I don't want to start coding down this route and not have their prestandard rejected or something. The article says something about a similar unix initative that didn't go "quite far enough". I guess the standards body are moving too slowly for MS that just wants to get stuff done and out the door, so they are taking the risk. So do we follow MS and bet that these new functions will become part of the standard?

Quote:
Original post by phantom

As for the functions, are there any differences between the signatures of strncpy and strncpy_s ?


Yep there are, strncpy_s takes 4 params, stncpy takes 3. MSDN has details.

I'll have to check out Washu's journal, I confess not really looked for a few weeks at it.

What I'm working on at the moment is Win32 anyway, and I've not got any plans for it to be anywhere else. But there are other projects I am working on that it might be nice to work on cross platforms, like my Ogre sound extension stuff for example.

It's nice they only warn you and tell you how to turn the rules off, rather then just making breaking changes. MS is much nicer about such things these days!
Anything posted is personal opinion which does not in anyway reflect or represent my employer. Any code and opinion is expressed “as is” and used at your own risk – it does not constitute a legal relationship of any kind.
SpreeTree
SpreeTree
Quote:
Original post by paulecoyote
Yep there are, strncpy_s takes 4 params, stncpy takes 3. MSDN has details.


You could still use some macro trickery (though it might go from trickery to downright code abuse) to get around the warning.

I personally use strncpy a lot in my current project (it needs looking at, but I will prob stick with it), so I would probably go down this route.

Spree

gosper
gosper
Probably because strncpy doesn't NULL terminate the destination buffer. You have to do that manually. That could leed to a buffer overflow or a memory leek somewhere down the line. _snprintf is a better alternative.
doynax
doynax
Quote:
Original post by gosper
Probably because strncpy doesn't NULL terminate the destination buffer. You have to do that manually. That could leed to a buffer overflow or a memory leek somewhere down the line. _snprintf is a better alternative.
But Microsofts implementation of _snprintf doesn't terminate the string either..

I suggest writing safe wrappers for these functions (watch out for strncat too) yourself, perhaps even invoking the safe versions directly on platforms that has them.
gosper
gosper
I just did a quick test on the _snprintf function using visual studio 2003 and it is in fact NULL terminating the buffer.
doynax
doynax
Quote:
Original post by gosper
I just did a quick test on the _snprintf function using visual studio 2003 and it is in fact NULL terminating the buffer.
I should've said that it doesn't always terminate the buffer.
Quote:
MSDN
The _snprintf function formats and stores count or fewer characters and values (including a terminating null character that is always appended unless count is zero or the formatted string length is greater than or equal to count characters) in buffer.
Thus a "full" buffer won't be terminated, much like the behaviour of strncpy.

C99's snprintf function is required to terminate the string however.
gosper
gosper
Wow that is really messed. Microsoft is way stupid for that one. If count is less than the amount being copied into the destination buffer it should crop out the excess but ALWAYS null terminate. Perhaps they can learn a thing or two from GNU.

PS. Microsoft is lucky I don't have any of their source code. ;)
iMalc
iMalc
Quote:
PS. Microsoft is lucky I don't have any of their source code. ;)
But you wouldn't want Microsoft's source code. When I serached for goto in our project, I was surprised to find that there were quite a few. I was less surprised however, when I found that they were just about all in code portions copied directly from MS code samples. Including a goto which simply went to the next line, thus having no effect whatsoever.

I mostly use CComBSTRs and AtlStrings with what I regularly work on, so I don't have to touch strncpy with a barge pole.

I think they go a bit overboard though, with things like qsort_s with it's nmemb AND size parameters. It probably only makes things worse as having two numeric parameters only increases the chance that they get put round the wrong way.
ZQJ
ZQJ
Quote:
Original post by gosper
Perhaps they can learn a thing or two from GNU.


As far as I know the GNU version of strncpy also doesn't NULL terminate strings longer than the destination buffer. However, these new functions look suspiciously similar to BSDs strlcpy, strlcat etc., so why they didn't just copy that I'll never know. I saw a post by somebody asking why GNU libc didn't support the strl... variants and the reply was to the effect that most C string handling routines just shouldn't be used - make sure the buffer is big enough first then use strcpy/cat or memcpy. On the other hand I read in a book once that fixed-size stack buffers are better because then the limitations of the implementation are predictable unlike memory allocation failures which aren't, so take your pick.
msn12b
msn12b
Quote:
Original post by gosper
Wow that is really messed. Microsoft is way stupid for that one. If count is less than the amount being copied into the destination buffer it should crop out the excess but ALWAYS null terminate. Perhaps they can learn a thing or two from GNU.

PS. Microsoft is lucky I don't have any of their source code. ;)


And you need to understand why this behavior exists.

strncpy is defined by the C standard to not guarantee null termination when the maximum number of characters to copy is less than the length of the source string.

Here's a more in depth explanation from Raymond Chen, one of the more experienced Microsoft developers.

MSN
msn12b
msn12b
Quote:
Original post by iMalc
I think they go a bit overboard though, with things like qsort_s with it's nmemb AND size parameters. It probably only makes things worse as having two numeric parameters only increases the chance that they get put round the wrong way.


Many (if not all) of the *_s functions have templated overloads sans _s that pass the additional parameters to the *_s version automatically.

MSN
mattnewport
mattnewport
Quote:
Original post by doynax
Besides, you should expect to get bashed for any 'breaking' changes.
So don't go around deprecating the standard library until ANSI says so..

It's not a breaking change unless you happen to be compiling with warnings-as-errors. As you say, it's easy to disable the warning globally so it's not a big deal.

I imagine MS put the warning in by default so that the many programmers out there who aren't even aware that these functions are unsafe (as evidenced by the huge number of security holes found in the wild) might at least look at the warnings for long enough to learn something about writing secure code.

Standards committees are notoriously slow moving and I don't think it's unreasonable for Microsoft to want to do something to address common security problems ahead of the release of the next version of the C++ standard which is at least 4 years away.
doynax
doynax
Quote:
Original post by mattnewport
Quote:
Original post by doynax
Besides, you should expect to get bashed for any 'breaking' changes.
So don't go around deprecating the standard library until ANSI says so..

It's not a breaking change unless you happen to be compiling with warnings-as-errors. As you say, it's easy to disable the warning globally so it's not a big deal.
Hence 'breaking' rather than breaking.
But really, anything that forces programmers (I don't consider ignoring the warnings an option) into spending effort to fix old code when upgrading the compiler is a breaking change in my book.
Quote:
Original post by mattnewport
I imagine MS put the warning in by default so that the many programmers out there who aren't even aware that these functions are unsafe (as evidenced by the huge number of security holes found in the wild) might at least look at the warnings for long enough to learn something about writing secure code.
I imagine this will scare new programmers away from the standard library, scare them into using Microsoft proprietary libraries or simply make them ignore their warnings.
Quote:
Original post by mattnewport
Standards committees are notoriously slow moving and I don't think it's unreasonable for Microsoft to want to do something to address common security problems ahead of the release of the next version of the C++ standard which is at least 4 years away.
I appreciate the effort, I just think it's a bit extreme..
I also whish they would've copied an existing "safe" implementation of the standard library instead of writing their own. Or at least that GCC could drop their ideals for a while and copy Microsoft's implementation..
nuvem
nuvem
Quote:
Original post by doynax
Quote:
Original post by mattnewport
It's not a breaking change unless you happen to be compiling with warnings-as-errors. As you say, it's easy to disable the warning globally so it's not a big deal.
Hence 'breaking' rather than breaking.
But really, anything that forces programmers (I don't consider ignoring the warnings an option) into spending effort to fix old code when upgrading the compiler is a breaking change in my book.
Except in this case, you don't have to change it if you don't want to (just ignore the errors), and you probably want to spend the effort anyway; if you don't, you're running the risk of leaving your code vulnerable to buffer overrun attacks, which you might later need to patch, much to your embarrassment.

Quite simply, MS decided that they couldn't wait for the standards committee to get around to it. They then had two options, either reimplement the standard functions, or implement proprietary versions. At least with the route they chose, you know the problem is there, and you can either choose to modify your code or ignore the warnings, as opposed to no choice at all, and potentially broken programs for an unknown reason.

I imagine when it's finally standardized, they'll simply add a few defines to have the _s versions call the standard ones.

Quote:
I appreciate the effort, I just think it's a bit extreme..
I also whish they would've copied an existing "safe" implementation of the standard library instead of writing their own. Or at least that GCC could drop their ideals for a while and copy Microsoft's implementation..
Extreme or not, something had to be done. Too many programs are still vulnerable to a well known cause of security issues.

ZQJ
ZQJ
I think the most important thing is that nobody should be using fixed-size buffers any more for things like that because if a string is large enough to take up a significant amount of space on modern computers it should probably be handled some other way (std::rope for instance).

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.