mersenneforum.org  

Go Back   mersenneforum.org > Extra Stuff > Programming

Reply
 
Thread Tools
Old 2012-05-30, 20:28   #12
Dubslow
Basketry That Evening!
 
Dubslow's Avatar
 
"Bunslow the Bold"
Jun 2011
40<A<43 -89<O<-88

3×29×83 Posts
Default

Quote:
Originally Posted by chalsall View Post
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.
Dubslow is offline   Reply With Quote
Old 2012-05-30, 21:36   #13
chalsall
If I May
 
chalsall's Avatar
 
"Chris Halsall"
Sep 2002
Barbados

2×5×997 Posts
Default

Quote:
Originally Posted by Dubslow View Post
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 View Post
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()).
chalsall is online now   Reply With Quote
Old 2012-05-30, 23:21   #14
Dubslow
Basketry That Evening!
 
Dubslow's Avatar
 
"Bunslow the Bold"
Jun 2011
40<A<43 -89<O<-88

722110 Posts
Default

Quote:
Originally Posted by chalsall View Post
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 View Post
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 View Post
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.
Dubslow is offline   Reply With Quote
Old 2012-05-30, 23:51   #15
chalsall
If I May
 
chalsall's Avatar
 
"Chris Halsall"
Sep 2002
Barbados

2×5×997 Posts
Default

Quote:
Originally Posted by Dubslow View Post
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.
chalsall is online now   Reply With Quote
Old 2012-05-31, 00:52   #16
Dubslow
Basketry That Evening!
 
Dubslow's Avatar
 
"Bunslow the Bold"
Jun 2011
40<A<43 -89<O<-88

3×29×83 Posts
Default

Quote:
Originally Posted by chalsall View Post
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 View Post
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 View Post
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.
Dubslow is offline   Reply With Quote
Old 2012-05-31, 01:25   #17
chalsall
If I May
 
chalsall's Avatar
 
"Chris Halsall"
Sep 2002
Barbados

2·5·997 Posts
Default

Quote:
Originally Posted by Dubslow View Post
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 View Post
...and equally does not guarantee that buffer overflow didn't happen.
YES IT DOES!!! It is even thread (read: reentrancy) safe.

Quote:
Originally Posted by Dubslow View Post
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.
chalsall is online now   Reply With Quote
Old 2012-05-31, 01:51   #18
Dubslow
Basketry That Evening!
 
Dubslow's Avatar
 
"Bunslow the Bold"
Jun 2011
40<A<43 -89<O<-88

3×29×83 Posts
Default

Quote:
Originally Posted by chalsall View Post
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 View Post
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 View Post
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
Dubslow is offline   Reply With Quote
Old 2012-05-31, 04:01   #19
LaurV
Romulan Interpreter
 
LaurV's Avatar
 
"name field"
Jun 2011
Thailand

980110 Posts
Default

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
LaurV is offline   Reply With Quote
Old 2012-05-31, 17:49   #20
chalsall
If I May
 
chalsall's Avatar
 
"Chris Halsall"
Sep 2002
Barbados

997010 Posts
Default

Quote:
Originally Posted by LaurV View Post
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 View Post
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 View Post
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 View Post
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"....
chalsall is online now   Reply With Quote
Reply

Thread Tools


Similar Threads
Thread Thread Starter Forum Replies Last Post
Official "new lows in Olympics TV coverage" thread ewmayer Soap Box 15 2016-08-13 11:01
Official "Faits erronés dans de belles-lettres" thread ewmayer Lounge 39 2015-05-19 01:08
Official "all-Greek-to-me Fiction Literature and Cinema" Thread ewmayer Science & Technology 41 2014-04-16 11:54
Official "Lasciate ogne speranza" whinge-thread cheesehead Soap Box 56 2013-06-29 01:42
Official "Ernst is a deceiving bully and George is a meanie" thread 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

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.

This forum has received and complied with 0 (zero) government requests for information.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation.
A copy of the license is included in the FAQ.