- Modern C++:Efficient and Scalable Application Development
- Richard Grimes Marius Bancila
- 492字
- 2021-06-10 18:27:57
Preventing Buffer Overruns
The C runtime library for manipulating strings is notorious for allowing buffer overruns. For example, the strcpy function copies one string to another, and you get access to this through the <cstring> header, which is included by the <iostream> header. You may be tempted to write something like this:
char pHello[5]; // enough space for 5 characters
strcpy(pHello, "hello");
The problem is that strcpy will copy all the character up to, and including the terminating NULL character and so you will be copying six characters into an array with space for only five. You could be taking a string from the user input (say, from a text box on a web page) and think that the array you have allocated is big enough, but a malicious user could provide an excessively long string deliberately bigger than the buffer so that it overwrites other parts of your program. Such buffer overruns have caused a lot of programs to be subjected to hackers taking control of servers, so much so that the C string functions have all been replaced by safer versions. Indeed, if you are tempted to type the preceding code, you'll find that strcpy is available, but the Visual C++ compiler will issue an error:
error C4996: 'strcpy': This function or variable may be unsafe.
Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
If you have existing code that uses strcpy, and you need to make that code compile, you can define the symbol before <cstring>:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
An initial attempt to prevent this issue is to call strncpy, which will copy a specific number of characters:
char pHello[5]; // enough space for 5 characters
strncpy(pHello, "hello", 5);
The function will copy up to five characters and then stop. The problem is that the string to copy has five characters and so the result will be no NULL termination. The safer version of this function has a parameter that you can use to say how big the destination buffer is:
size_t size = sizeof(pHello)/sizeof(pHello[0]);
strncpy_s(pHello, size, "hello", 5);
At runtime this will still cause a problem. You have told the function that the buffer is five characters in size and it will determine that this is not big enough to hold the six characters that you have asked it to copy. Rather than allowing the program to silently continue and the buffer overrun to cause problems, the safer string functions will call a function called the constraint handler and the default version will shut down the program on the rationale that a buffer overrun means that the program is compromised.
The C runtime library strings functions were originally written to return the result of the function, the safer versions now return an error value. The strncpy_s function can also be told to truncate the copy rather than call the constraint handler:
strncpy_s(pHello, size, "hello", _TRUNCATE);
The C++ string class protects you from such issues.