Недавно я столкнулся с очень хитрой ошибкой, в которой я забыл разыменовать указатель на строку (массив символов) и, таким образом, иногда перезаписывал один байт в стеке.
Плохо:
char ** str;
(*str) = malloc(10);
...
str[2] = 'a'; //overwrites 3 bytes from the location in which str is stored
Исправлено:
char ** str;
(*str) = malloc(10);
...
(*str)[2] = 'a';
GCC не выдавал предупреждений, и эта ошибка привела бы к очень серьезному и реальному эксплойту, поскольку значение, которое оно иногда перезаписывало, содержало размер буфера. Я поймал эту ошибку только потому, что мне повезло, и это вызвало очевидный сбой.
Кроме того, чтобы полагаться на удачу и / или никогда не использовать C для чего-либо, какие защитные приемы и приемы кодирования вы используете, чтобы ловить странные ошибки C?
Я думаю о переходе на Valgrind's MemCheck , кто-нибудь использовал это? Я подозреваю, что это не поймало бы эту ошибку. Кто-нибудь знает?
Существуют ли инструменты для обнаружения разыменования указателей или арифметических ошибок? Это вообще возможно?
UPDATE
Вот запрашиваемый пример кода, он не выдает никаких предупреждений.
#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;
}
Компиляция не вызывает ошибок:
gcc -Wall testBug.c -o testBug
Работа вызывает ошибку сегмента:
./testBug
Segmentation fault
Это версия GCC, которую я использую:
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)