With buffer overflow attacks in the news almost every day, matters have come to a head. It is time for
everyone to program defensively, whether they're in C or in any other language with similar behavior in
strcpy and
strcat like functions, or functions calling these C library functions.
First of all, convert
all strcpy and
strcat (or like) calls to
strncpy and
strncat. You
really ought to know what the maximum length is (including the terminating null) of any array you're writing into! This is a major reason that Object-Oriented programming can be so nice, if used correctly — it already carries around the length of a string as part of its internal data, and can do the length checking for you.
Second, you need to make sure that the target is
always a proper string
after the write, that is, with a terminating NULL byte.
strncpy and
strncat do
not, by themselves, write a NULL byte if they hit the limit. You can handle this in one of three ways, where the buffer in question is
STRINGLEN+1 bytes long:
- Have the discipline to write '\0' to array[STRINGLEN] (or some earlier position) after each write (strncpy or strncat).
- Have the discipline to use macros or local functions for copying and concatenating strings, which inside use strncpy/strncat and writes the NULL for you.
- Have the discipline to use STRINGLEN in the strncpy or strncat call, and write the terminating NULL at the last position up at the top of the program. There might be another NULL earlier in the string, but the one at the end is there as a safety stop, and should never be touched. Perhaps you can use a macro to declare the string and initialize it with NULL bytes at [0] and [STRINGLEN]?
Any way you choose to do this requires some discipline to not do the lazy thing and just "this one time can't hurt" call
strcpy or
strcat. Until C library suppliers get their act together and
remove strcpy and
strcat from the library, you should consider making your own dummy stubs in a library that comes ahead of the standard libraries. They would simply print a message to STDERR that informs you that you called
strcpy or
strcat, and then die. At least, this would compel you to fix that oversight!
Now comes the tricky part:
strncat checks only the length of the incoming string (being added to the target string), and
not the current length of the target string (the one being added to)! Therefore, it is still possible to overflow the target string.
You need to figure out the maximum length to copy (for concatenation) from the target string's current and maximum length, and (ideally) the current length of the source string (being concatenated to the target). The idea is that you don't want to overfill your target string, past its safety stop. Again, a macro or function might help with this.
Be aware that if your
strcpy or
strcat should overflow the target buffer string, the damage has been done: something valuable may already have been overwritten with malicious code! Inserting that NULL terminating byte at the very end of the buffer isn't going to undo the damage. It will merely turn this string into a proper (NULL terminated) string fitting within its array — it won't restore the content beyond it. Therefore it is important to avoid writing past the end of the buffer in the first place!
Finally, there is the question about what to do (if anything) about a
source string that lacks a terminating NULL byte. It is conceivable that in such a situation that too much data can be copied, including possibly sensitive material beyond the proper end of the string. If you have been careful about your string lengths and using
strncpy and
strncat, you
probably won't run into a corrupted input string that has lost its terminating NULL byte for some reason (but never say never!).