mersenneforum.org Official "String copy Statement Considered Harmful" thread
 Register FAQ Search Today's Posts Mark Forums Read

2012-05-30, 20:28   #12
Dubslow

"Bunslow the Bold"
Jun 2011
40<A<43 -89<O<-88

3×29×83 Posts

Quote:
 Originally Posted by chalsall src wouldn't get clobbered; dest simply wouldn't have the full string. Code: int strcpy_s( char *dest, int n, const char *src ) { if (!dest || !src) { return 1; // Stupid human... } if (strlen(src) > n-1) { return 2; // dest too small; Stupid human... } strncpy(dest, src, n); return 0; }
Well by src I really meant "the string pointed to by src" Stupid humans and their imprecision
That code is great, but of course it would be nice were it in the Linux <string.h> instead of having to re-write it each time strncpy is close enough if you know what you're doing, which I hope includes all the posters in this thread.

2012-05-30, 21:36   #13
chalsall
If I May

"Chris Halsall"
Sep 2002

2×5×997 Posts

Quote:
 Originally Posted by Dubslow Well by src I really meant "the string pointed to by src" Stupid humans and their imprecision
But again here you are wrong. "the string pointed to by src" is never touched by any of the strcpy functions. By definition (const char * actually means something).

Quote:
 Originally Posted by Dubslow It seems MSFT deserves credit for something they appear to have done better than on linux.
Again, I disagree.

If the stupid human submits to the strcpy() functions null pointers for either dest or src then the program should crash (with a "segfault"). The program is wrong. If dest is ever smaller than src, then the program should crash if the programmer hasn't taken that possibility into account.

With M$'s version of the function, the program will continue to run, even though what the programmer thought they were instructing was not what actually happened. (As a test, examine some source code you have available to you, and see how many test the return value from strcpy_s()). 2012-05-30, 23:21 #14 Dubslow Basketry That Evening! "Bunslow the Bold" Jun 2011 40<A<43 -89<O<-88 722110 Posts Quote:  Originally Posted by chalsall But again here you are wrong. "the string pointed to by src" is never touched by any of the strcpy functions. By definition (const char * actually means something). I meant the abstract conceptualization of the string, I.e. that dest would silently not be correct. Quote:  Originally Posted by chalsall Again, I disagree. If the stupid human submits to the strcpy() functions null pointers for either dest or src then the program should crash (with a "segfault"). The program is wrong. If dest is ever smaller than src, then the program should crash if the programmer hasn't taken that possibility into account. According to my man page, "anything can happen" if dest is smaller than src. Then it goes on to warn about buffer overflow, as LurV initially pointed out. No crashes, just undefined behavior. (Admittedly that probably means a crash, but it's not guarantees and can't be relied on as an error check.) Quote:  Originally Posted by chalsall With M$'s version of the function, the program will continue to run, even though what the programmer thought they were instructing was not what actually happened. (As a test, examine some source code you have available to you, and see how many test the return value from strcpy_s()).
Then the programmer is just as dumb as in your example, except that this time buffer flow doesn't actually happen as it might with strcpy.

Regarding strncpy, clobbering is still silent, whereas M$does give you the option to check for clobbering, even if most people ignore the return value of strcpy_s. In the latter case, either everything is perfect or dest was not written to; that's better than silent clobbering/silent buffer overflow, and as I said before, M$ gives you the option to un-silent it without having to write those checks yourself.

2012-05-30, 23:51   #15
chalsall
If I May

"Chris Halsall"
Sep 2002

2×5×997 Posts

Quote:
 Originally Posted by Dubslow Regarding strncpy, clobbering is still silent, whereas M$does give you the option to check for clobbering, even if most people ignore the return value of strcpy_s. In the latter case, either everything is perfect or dest was not written to; that's better than silent clobbering/silent buffer overflow, and as I said before, M$ gives you the option to un-silent it without having to write those checks yourself.
Sigh...

You need to understand what the term "clobbering" means to those who understand what they are doing.

*src is never clobbered.

And dest[length-1]=0; guarantees that the string copied into dest is null terminated.

M$does no one any favors by providing functions which hide the programmer's mistakes. 2012-05-31, 00:52 #16 Dubslow Basketry That Evening! "Bunslow the Bold" Jun 2011 40<A<43 -89<O<-88 3×29×83 Posts Quote:  Originally Posted by chalsall Sigh... You need to understand what the term "clobbering" means to those who understand what they are doing. *src is never clobbered. In the most recent post anyways, I never said src is clobbered. I just said general stuff like "clobbering happens" and what not. Quote:  Originally Posted by chalsall And dest[length-1]=0; guarantees that the string copied into dest is null terminated. Yes, but that doesn't guarantee that dest contains all of src, and equally does not guarantee that buffer overflow didn't happen. Quote:  Originally Posted by chalsall M$ does no one any favors by providing functions which hide the programmer's mistakes.
How does the function hide the mistakes anymore than strcpy (or strncpy) does? Any errors in the arguments are silently excepted by the latter, whereas the former returns an error code. Even if you ignore the return code, you're still no worse off than using strcpy | strncpy.

2012-05-31, 01:25   #17
chalsall
If I May

"Chris Halsall"
Sep 2002

2·5·997 Posts

Quote:
 Originally Posted by Dubslow Yes, but that doesn't guarantee that dest contains all of src...
No, it does not guarantee that dest contains all of src. But if dest is smaller than src, then it obviously can't.

Quote:
 Originally Posted by Dubslow ...and equally does not guarantee that buffer overflow didn't happen.

Quote:
 Originally Posted by Dubslow How does the function hide the mistakes anymore than strcpy (or strncpy) does? Any errors in the arguments are silently excepted by the latter, whereas the former returns an error code. Even if you ignore the return code, you're still no worse off than using strcpy | strncpy.
Because the former functions don't crash, while the latter ones often will.

I gave you the wrapper code which does nothing more than stupid-human checking. If the stupid human doesn't then check the return code from the function, then all that function does is hide stupid programmer errors.

2012-05-31, 01:51   #18
Dubslow

"Bunslow the Bold"
Jun 2011
40<A<43 -89<O<-88

3×29×83 Posts

Quote:
 Originally Posted by chalsall YES IT DOES!!! It is even thread (read: reentrancy) safe.
What's 'it'? If we're talking about strncpy, then yes, it prevents buffer overflow (assuming the stupid human got the n right). If were talking about strcpy (which generally I have been), then no, there is nothing about "dest[length-1]=0;" which will prevent overflow; any overflow happens before the function returns, so anything done after the return will not change that fact. Edit: Another way to write this is that null-terminating dest and not overflowing the buffer are independent problems.
Quote:
 Originally Posted by chalsall Because the former functions don't crash, while the latter ones often will.
Not always. Nothing (even crashing) is guaranteed, and therefore it would be bad practice to rely on such crashing as error-catching. It is possible to silently cause problems, while M\$'s function will not do anything if it can't be done properly, and it will tell the programmer that something's wrong.
Quote:
 Originally Posted by chalsall If the stupid human doesn't then check the return code from the function, then all that function does is hide stupid programmer errors.
Yes, but not checking the return code is a mistake in and of itself. And I still maintain that not writing anything at all to dest is better than writing as much as possible with unknown results. And, as I've pointed out before, strncpy hides programmer errors just as well as ignoring strcpy_s's return code. If you check the return code, then you are ahead of where you would have been using strncpy.

Last fiddled with by Dubslow on 2012-05-31 at 01:55

 2012-05-31, 04:01 #19 LaurV Romulan Interpreter     "name field" Jun 2011 Thailand 980110 Posts Could some mod move this discussion about strings into a C/C++ related topic? Now about safety, what the program does AFTER it come back from the function has NOTHING to do with the safety of the function. Code: uint8_t ch=0; press_a_key(&ch); if(ch=='w') format_harddisk(); If the user presses w, and his hdd gets formatted, this does not mean the function press_a_key() is not safe. It could only mean the user is idiot or the programmer is idiot or malicious, or it could mean that the user wanted (intentionally) to format his hdd. A function is not safe if the environment can influence the behaviour of the function in such a way that the result or the side effect of the function is altering that environment in unwanted or unintended ways. For strcpy(), which reads/writes the string until a string-terminator is found, this could lead to destroying some data, (or the function running forever) in case the terminator is not found. All this happens INSIDE of the function. You can kill the function (caution, I did not say "the program") altering its input data. Therefore the function is not "safe". There is no way to do this for strncpy() function. Of course, you can kill the program by altering its input data if the string is too long and if the programmer does not take care of the termination, but this will happen outside of the function. The function is safe. In a multi-user/multi-tasking/threaded/prrocess environment, where everybody can alter the DATA in any moment of time, you should never assume that the string you put there (and correctly null-terminated) is still there and it is still null terminated. There are lots of "viruses" (i.e. processes with low access rights) which look for strings in the part of the memory which they can access, for example, and replace the null-terminations of the strings with their own executable code, filled in fromt with a series of NOP's to ensure the right start address. If another process with higher access rights copy that string in some "unsafe" ways, the executable code of the virus will be copied in an area of the memory which the virus CANNOT access (in normal ways), and it would be eventually executed by that task with higher priority, therefore the virus will become part of a process with higher rights in the system and continue do do its malice (replicate, steal passwords, bla bla bla). This is how many viruses "step up" in the hierarchy of rights and priorities in your system, or how an user with limited rights but who knows what he is doing, can get administrator rights in an xp32 system (yes, I can do that. No joke). Last fiddled with by LaurV on 2012-05-31 at 04:25
2012-05-31, 17:49   #20
chalsall
If I May

"Chris Halsall"
Sep 2002

997010 Posts

Quote:
 Originally Posted by LaurV Now about safety, what the program does AFTER it come back from the function has NOTHING to do with the safety of the function.
Hear hear!!!

Quote:
 Originally Posted by LaurV A function is not safe if the environment can influence the behaviour of the function in such a way that the result or the side effect of the function is altering that environment in unwanted or unintended ways. For strcpy(), which reads/writes the string until a string-terminator is found, this could lead to destroying some data, (or the function running forever) in case the terminator is not found. All this happens INSIDE of the function.
Absolutely agree. This is why strcpy() is considered unsafe, while strncpy() is considered safe.

kjaget then (correctly) pointed out that strncpy() will not null terminate *dest if strlen(src) is larger than n; I pointed out that simply adding the additional instruction dest[n-1]=0; after any use of strncpy() guarantees that dest is null terminated. This additional instruction is almost always pointless (no joke intended), but it's cheap and known to be sane.

Quote:
 Originally Posted by LaurV In a multi-user/multi-tasking/threaded/prrocess environment, where everybody can alter the DATA in any moment of time, you should never assume that the string you put there (and correctly null-terminated) is still there and it is still null terminated.
I understand and agree with what you are saying here. But it should be pointed out that in modern operating systems, such altering of other programs' data and code is generally prevented. Of course, in a multi-threaded program (where each thread can share memory) badly written code can result in one thread writing to a memory area which another thread is reading or writing.

And, of course, there are many environments where no such protection is provided. Embedded systems for example.

Quote:
 Originally Posted by LaurV There are lots of "viruses" (i.e. processes with low access rights) which look for strings in the part of the memory which they can access, for example, and replace the null-terminations of the strings with their own executable code, filled in fromt with a series of NOP's to ensure the right start address. If another process with higher access rights copy that string in some "unsafe" ways, the executable code of the virus will be copied in an area of the memory which the virus CANNOT access (in normal ways), and it would be eventually executed by that task with higher priority, therefore the virus will become part of a process with higher rights in the system and continue do do its malice (replicate, steal passwords, bla bla bla). This is how many viruses "step up" in the hierarchy of rights and priorities in your system, or how an user with limited rights but who knows what he is doing, can get administrator rights in an xp32 system (yes, I can do that. No joke).
Absolutely.

But now a-days it seems the easier vector is to simply tell the stupid human user to "click here" on a web page, since most run effectively as "root"....

 Similar Threads Thread Thread Starter Forum Replies Last Post ewmayer Soap Box 15 2016-08-13 11:01 ewmayer Lounge 39 2015-05-19 01:08 ewmayer Science & Technology 41 2014-04-16 11:54 cheesehead Soap Box 56 2013-06-29 01:42 cheesehead Soap Box 61 2013-06-11 04:30

All times are UTC. The time now is 19:55.

Wed Oct 27 19:55:14 UTC 2021 up 96 days, 14:24, 0 users, load averages: 1.53, 1.44, 1.38