-
January 14th, 2013, 01:31 PM
#1
Windows strcpy overflow question
Hello,
I have the following code:
char buf[5];
strcpy(buf, "12345678");
When I run this from the IDE in Release mode, it works fine, no crashes. However, when I change "12345678" to "123456789" then I get this compilation warning:
warning C4789: destination of memory copy is too small
And also it crashes when i run it.
Can anyone explain why this is inconsistent, or what I am misunderstand?
Regards,
EK
Last edited by ekhule; January 15th, 2013 at 10:18 AM.
-
January 14th, 2013, 01:47 PM
#2
Re: Windows strcpy overflow question
Originally Posted by ekhule
my guess is that it is also copying the null terminator?
The standard behaviour of memcpy involves copying the null terminator.
Originally Posted by ekhule
Can anyone explain why this is inconsistent, or what I am misunderstand?
You are in the realm of undefined behaviour. Don't do this, then you don't have to misunderstand.
-
January 14th, 2013, 02:48 PM
#3
Re: Windows strcpy overflow question
Your definition of buffer
allocates space for 4 characters plus the terminating null character (0). Therefore the maximum length of a string that should be copied to buffer is 4. Standard strcpy (as far as I am aware) copies starting from the memory location pointed by the source pointer to the memory location pointed by the destination pointer. This copy continues character by character until a null character is found in the source. strcpy does not know how much memory has been allocated for the destination and continues copying beyond the end of the allocated destination memory if a null has not been found in the source. Effectively strcpy performs
Code:
while (*d++ = *s++);
In your case all your inputs including "12345" have too many characters to be copied correctly and safely to the destination (buffer - maximum number 4 plus the terminating null). Input of "1234" is OK but "12345" is not.
Code:
char buffer[5];
strcpy(buffer, argv[1]);
char buffer[5];
strcpy(buffer, "12345678");
When copying exceeds the memory allocated it overwrites whatever happens to be in memory following buffer. This could be other data, code etc. This is a prime example of what is called 'buffer overflow' where the contents of a buffer has 'overflowed' into adjacent memory. This is a prime source of security issues allowing unauthorised code to be executed by carefully crafted input.
To make sure that buffer overflow does not occur, the new string safe functions should be used. These are the StringCch functions . If you must use the unsafe strcpy, strcat, gets etc functions then you need to make sure that the memory allocated for the destination is large enough to hold what is going to be copied to it.
In your case you are probably overwriting code so that is why your program is crashing.
-
January 14th, 2013, 04:06 PM
#4
Re: Windows strcpy overflow question
Originally Posted by ekhule
Can anyone explain why this is inconsistent, or what I am misunderstand?
Here is what you're misunderstanding: you're using C++.
When you overwrite memory like this in C++, there is no guarantee how your program will behave. Unlike other computer languages, with C++ (and C) you do not get an automatic "crash" or "message box" or some other error indicator when you do these "tricks" at runtime.
You can do all sorts of illegal (but compilable) things in C++, and all seems to work -- until you try to run that program somewhere else, or you run the program at a different time of day, or you run that program on a customer's machine, or you change a couple of lines of code that are totally benign, but the program then crashes.
Haven't you heard of programs that run perfectly in-house, and then when you go take that program to the customer site, things crash? It's situations just like this that causes those issues.
C++ has something called undefined behaviour, meaning exactly that -- you write code that does something that isn't defined as to what will happen, and guess what? You don't know what will happen.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; January 14th, 2013 at 04:12 PM.
-
January 14th, 2013, 07:13 PM
#5
Re: Windows strcpy overflow question
I can stick a knife in the toaster and there is a chance I won't have to go to hospital...
-
January 15th, 2013, 08:11 AM
#6
Re: Windows strcpy overflow question
Originally Posted by 2kaud
To make sure that buffer overflow does not occur, the new string safe functions should be used. These are the StringCch functions . [...]
Right, however, this is Win32 API. To avoid dependency on Win32, strcpy_s() from the C++ runtime library can be used as an alternative. It's still MS-specific (AFAIK), however.
I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.
This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.
-
January 15th, 2013, 08:30 AM
#7
Re: Windows strcpy overflow question
I'm assuming that you're asking this question to understand legacy C code.
As you are using C++, the equivelent code in your first example would be.
Code:
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
string buffer(argv[1]);
cout << "buffer content= " << buffer << "\n";
cout << "String constructor executed\n";
}
No buffer overruns are possible.
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
January 16th, 2013, 07:00 PM
#8
Re: Windows strcpy overflow question
Originally Posted by Eri523
Right, however, this is Win32 API. To avoid dependency on Win32, strcpy_s() from the C++ runtime library can be used as an alternative. It's still MS-specific (AFAIK), however.
Yes, it's an MS-specific recommendation that never made it to the new C11 standard. The C standard has had strncpy for years. Use that, if you desire fixed length fields... Just be aware that unlike the non-portable strcpy_s, strncpy might not append a null terminator to the end of your string. If you want that guarantee, end your fixed length field one byte earlier and put the terminator there yourself.
Code:
#include <string.h>
int main(void) {
char fubar[6];
strncpy(fubar, "hello world", sizeof (fubar) - 1);
fubar[sizeof (fubar) - 1] = '\0';
printf("fubar contains: %s\n", fubar);
return 0;
}
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|