Переполняющиеся буфера
Ошибок переполнения не избежала практически ни одна программа чуть более сложная, чем "hello, world!", а все потому, что ошибки переполнения в Си носят фундаментальный характер и язык не предоставляет никаких механизмов для их преодоления.
Контроль границ буфера приходится осуществлять вручную. К тому же, если говорить по существу, в Си вообще нет никаких буферов. Получив указатель на "буфер", функция не может определить его длину. Оператор sizeof возвращает размер указателя (как правило, равный DWORD), но отнюдь не размер блока, на который он указывает. Небольшую лазейку оставляет нестандартная функция _msize, сообщающая размер динамического блока, но она требует указателя на его начало, отказываясь работать с серединой.
Простейшая тестовая программа все это наглядно подтверждает:
// Функция, принимающая указатель
// и пытающаяся определить размер соответствующего ему блока
foo(char *p){printf("sizeof says = %Xh\n_msize says = %Xh\n",sizeof(p),_msize(p));}
main()
{
char buf[0x666]; char *p = malloc(0x999);
// передаем указатель на начало блока
foo(buf);foo(p);
// передаем указатель на середину блока
foo(&buf[6]);foo(p+9);
}