views:

773

answers:

11

I've been asked to maintain a large C++ codebase full of memory leaks. While poking around, I found out that we have a lot of buffer overflows that lead to the leaks (how it got this bad, I don't ever want to know).

I've decided to removing the buffer overflows first, starting with the dangerous functions. What C/C++ functions that are most often used incorrectly and can lead to buffer overflow?

For compiler and/or tools used to help look for buffer overrun, I've created another question that deals with this

+2  A: 

Here's some functions that I found that are dangerous:

  • gets() - It doesn't check the length of the variable and can overwrite memory if the input is bigger than the variable's buffer.
  • scanf() - I'm so glad that Visual Studio told me this function is deprecated. This was an easy fix.
  • strcpy() - If the source's memory space is bigger than the destination's, the data after the destination is overwritten.
MrValdez
+2  A: 

The following link should give you a comprehensive look at security functions in C++ (ones that are post-fixed with '_s' to fix problems like overflows): http://msdn.microsoft.com/en-us/library/8ef0s5kh(VS.80).aspx

EDIT: This link contains the specific functions that have been replaced: http://msdn.microsoft.com/en-us/library/wd3wzwts(VS.80).aspx

EDIT: I should mention these are Microsoft methods, but the link is still useful for identifying functions that were deemed a red flag.

j0rd4n
These are non-portable Windows-specific functions, however.
Alex B
Yes, but they identify functions that are a problem.
j0rd4n
+2  A: 

Unfortunately any array can result in a buffer overflow:

uint32_t foo[3];
foo[3] = WALKED_OFF_END_OF_ARRAY;

In terms of functions, sprintf will happily walk off the end of the buffer. It can be replaced by snprintf.

DGentry
+6  A: 

In general, any function that does not check bounds in the arguments. A list would be

  • gets()
  • scanf()
  • strcpy()
  • strcat()

You should use size limited versions like stncpy, strncat, fgets, etc. Then be careful while giving the size limit; take into consideration the '\0' terminating the string.

Also, arrays are NOT bound checked in C or C++. The following example would cause errors. See off by one error

int foo[3];
foo[3] = WALKED_OFF_END_OF_ARRAY;

edit: Copied answers of @MrValdez , @Denton Gentry

hayalci
I disagree: functions which check bounds in the arguments are still dangerous. If you can overrun with strcpy, you can overrun with strncpy by getting the bound wrong, (e.g. increment the pointer and forget to decrement the bound). To protect yourself, use std::string or equivalent C string lib.
Steve Jessop
A shorter summary might be "the C functions risk overflows. The C++ functions generally do not"
Aaron
When using strnxxx versions, beware that they may produce a string that is not null-terminated
Arkadiy
A: 

Basically, anything which accept a pointer and writes to it, without checking the length. So thing like strcpy(), sprintf() etc.

James Curran
+2  A: 

Memcpy() is another dangerous one.

Any loop accessing an array is a danger point, because there's no stopping going beyond the end of array.

Memory Leaks are caused by allocating memory, and not freeing it. Constructor and destructors should be another strong review point, the latter to make sure any allocated memory is freeded.

Thomas Jones-Low
memcpy isn't that dangerous, since it accepts a length parameter, so as long as the destination buffer is in sync with the length (both of which should be under the developer's control), it doesn't matter if the source buffer is compromised.
James Curran
+2  A: 

Which version of visual studio are you using? In 2008 with all warnings enabled, all the functions you mention (and more) warn you that they are deprecated.

Perhaps you could check that all warnings are turned on and let the compiler do the hard work for you?

As a side note, the excellent writing secure code does a great job explaining the different the pitfalls of some of the older functions.

John Sibly
I've opened another question (http://stackoverflow.com/questions/167199/what-cc-tools-can-check-for-buffer-overflows) that deals with tools for helping me look for functions that can create overflows.
MrValdez
+2  A: 

I have somewhat the same problem on the code base I work on. My advice: be wary of any C functions that look like str*() and mem*(). Also be wary of anything that takes a pointer to a buffer, without a length. Since it seems like you have the chance to use C++ I would in the most egregious cases try to use C++ containers for things: vector, string, map, etc. These make your life a lot easier.

Also, automated problem detection tools are wonderful to have. If you can use valgrind I would recommend it. Also Rational Purify is extremely powerful, though not cheap.

+3  A: 

The question is starting at the wrong end, I'm afraid. It's presuming that buffer overruns happen in other functions. The most common cause is operator++, in my experience, or alternatively a lack of operator!=.

The best solution to find a batch of those is /GS in Visual Studio 2005/8. It won't find all of them, but it's a cheap way to reduce the amount of manual work needed.

MSalters
+3  A: 

Valgrind is your new best friend.

valgrind --tool=memcheck --leak-check=full ./a.out

dicroce
A: 

An additional gotcha in C is the "strncpy()" function. Many people do not realize that it is free to return a string that is not null terminated.

jdkoftinoff