I recently ran into a very sneaky bug, in which I forget to dereference a pointer to a string (char array) and thus sometimes overwrote one byte on the stack.
Bad:
char ** str;
(*str) = malloc(10);
...
str[2] = 'a'; //overwrites 3 bytes from the location in which str is stored
Corrected:
char ** str;
(*str) = malloc(10);
...
(*str)[2] = 'a';
GCC produced no warnings, and this error would've resulted in a very serious and real exploit as the value it sometimes overwrote held the size of a buffer. I only caught this bug because I got luckly and it caused an obvious failure.
Other than relying on luck and/or never using C for anything, what defensive coding techniques and tricks do you use to catch wierd C bugs?
I'm thinking about moving to valgrind's MemCheck, has anyone used it? I suspect it wouldn't have caught this bug. Anyone know?
Are there tools for catching pointer dereferencing or arithmetic bugs? Is that even possible?
UPDATE
Here is the requested example code, it does not throw any warnings.
#include <stdlib.h>
void test(unsigned char** byteArray){
(*byteArray) = (unsigned char*)malloc(5);
byteArray[4] = 0x0;
}
int main(void){
unsigned char* str;
test(&str);
return 0;
}
Compiling causes no errors:
gcc -Wall testBug.c -o testBug
Running causes a seg fault:
./testBug
Segmentation fault
This is the version of GCC I'm using:
gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.1-4ubuntu9' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu9)