? int qsize;
?
? qsize = atoi(getenv("CONTENT_LENGTH"));
? fread(query, qsize, 1, stdin);
? return query;
? }
В этом коде предполагается, что ввод никогда не будет длиннее 1024 байтов,
поэтому он, как и gets, открыт для атак переполнения буфера.
Более привычные виды переполнения также могут вызвать проблемы. Если
переполнение целого числа происходит без предупреждения, результат может быть
губительным для программы. Рассмотрим такое выделение памяти:
? char *p;
? р = (char *) malloc(x *
у * z);
Если результат перемножения х, у и z вызывает переполнение, вызов malloc
приведет к созданию массива приемлемого размера, но р[х] может ссылаться на
раздел памяти вне выделенной области. Предположим, что целые числа являются
16-битовыми, а каждая из переменных х, у и z равна 41. Тогда x*y*z равно 68 921, то
есть 3385 по модулю 216. Так что вызов
malloc выделит только 3385 байтов, а любая
ссылка по индексу вне этого значения будет выходить за заданные границы.
Еще одной причиной переполнения может стать преобразование типов, и обработки
таких ошибок не всегда возможны корректным об-, разом. Ракета "Ariane 5"
взорвалась во время своего первого запуска в июне 1996 года только из-за того, что
навигационный
пакет был унаследован от "Ariane 4" и не прошел тщательного
тестирования. Новая ракета имела большую скорость, и, соответственно,
навигационным программам приходилось иметь дело с большими числами. Вскоре
после запуска попытка преобразовать 64-битовое число с плавающей точкой в 16-
битовое целое со знаком вызвала переполнение. Ошибка была отловлена, но коду,
обработавшему ее, пришлось прервать работу
подсистемы. Ракета ушла с курса и
взорвалась. Самое обидное, что код, в котором произошел сбой, генерировал
данные, необходимые только до момента запуска; если бы при запуске эта часть
программы была отключена, трагедии бы не произошло.
На более приземленном уровне двоичный ввод иногда выводит из строя программы,
ожидающие текстового ввода, особенно
если предполагается, что этот ввод должен
относиться к 7-битовому набору символов ASCII. Полезно, а для многих ситуаций и
просто необходимо ввести двоичные значения в тестируемую программу,
ожидающую ввода текста, и посмотреть на ее реакцию.
Хорошие тесты и тестовые случаи нередко могут быть использованы для большого
количества программ. Так, каждая программа, читающая файлы
, должна быть
проверена вводом пустого файла. Каждая программа, читающая текст, должна быть
оттестирована двоичным вводом. Каждая программа, читающая строки текста,
должна быть проверена вводом очень длинных строк, пустых строк и файлом без
символов перевода строки вообще. Таким образом, полезно сохранять подобные
общие тесты и всегда иметь их под рукой — тогда
можно будет быстрее и с
меньшими затратами тестировать любую программу. Полезно также раз и навсегда
написать хорошую программу, которая бы создавала тестовые файлы в
соответствии с запросами.