Image

Listens: напевает Доктора Александрова - Stop Narcotix

Category:

В пятницу, среди новых программ в портах OpenBSD, увидел pscan. Эта одна из программ, которая проводит статический анализ кода. Вы «натравливаете» её на файлы с исходным кодом на Си, а она вам выдаёт в каких файлах и в каких функциях вы использовали небезопасные функции. В основном она ищет конечно же функции, которые подвержены или же часто допускают переполнение буфера (buffer overflow).

Маленькое отступление:
Должен заметить, что программ подобного рода существует достаточно. К примеру, я уже упаковал и скоро отправлю в Сизиф flawfinder. Также в Сизифе есть splint. В интернете можно найти и другие программы подобного назначения. Вот только со всеми ними наблюдается нехорошая тенденция: почти все они написаны лет по пять назад и авторы уже не поддерживают свои программы. К примеру, pscan написан в 2000 году, splint не обновлялся с 2003, а flawfinder c 2004-ого. Почему наблюдается подобная тенденция, мне, к сожалению, неизвестно.

Возвращаясь к pscan: я сразу же решил взглянуть на эту программу. Скачал маленький тарбольчик, распаковал и начал первичный осмотр. В файле pscan.c я сходу же обнаружил три недочета:

1) Два раза подключался один и тот же заголовочный файл errno.h:


...
 25 #include <string.h>
 26 #include <errno.h>
 27 #include <errno.h>
 28 #include <assert.h>
...



В этом нет ничего вообщем-то страшного, это никак не повлияет на работу программы, но это явно лишнее.

2) При ошибке открытия файла сообщение об ошибке будет выведено дважды. Смотрите сами:

...
252     /* Open the source file for reading */
253     if ((yyin = fopen(filename, "r")) == NULL) {
254       fprintf(stderr, "pscan: Error opening %s: %s.\n", filename,
255           strerror(errno));
256       printf("%s\n", strerror(errno));
257       exit(1);
258     }
...


Функция strerror(3), для тех кто не знает, принимает код ошибки и возвращает строку с её описанием. Так вот здесь эта строка будет выводиться дважды, причем второй раз не в stderr, а в stdout. Вообщем, строка номер 256 здесь явно лишняя. Кстати, не очень понял почему автор везде использует связку fprintf(3) + strerror(errno) вместо perror(3), возможно, это просто дело вкуса, а может и нет.

3) При обработке файла для хранения номера строки используется переменная типа int:

...
119   int line;
...
132   /*
133    *  Loop over the input file
134    */
135   line = 0;
136   while (fgets(buffer, sizeof(buffer), fp)) {
137     line++;
...


Типа int здесь явно мало, т.к. максимальное значение, которое сможет принять эта переменная будет 32768. Более разумно было бы использовать для хранения номера строки тип long или даже unsigned long. Кстати, в своё время на эту же проблему в OpenFM мне указал Imagelos_t. Также, в книге «Язык Си» Керниган и Ритчи затрагивали эту тему.

Сейчас, двумя днями позже, когда я пишу этот пост, я подумал, что не видел ещё файлов с исходниками, с размером более 32 768 строк. Возможно, что таких не существует и потому найденная мной проблема неактуальна.

После того как я нашел эти мелочи, я подумал, что было бы неблагодарностью к другим разработчикам не помочь им в улучшении кода и open source программ и потому я изготовил патчик, который отправил автору сей программы и её мэйнтейнеру в OpenBSD.

Автор пока молчит, а мэйнтейнер сказал, что «this patch looks good, but IMPOV it would be better, if the author of the program would fix it.» (переведу, для тех кто плохо знает английский: «этот патч выглядит неплохо, но помойму было бы лучше, если бы его принял автор программы.»)

Послесловие.
Сразу после того как я это обнаружил, я конечно же захотел написать пост, но потом заметил, что немного боюсь. Боюсь критики со стороны тех, кто считает, что эти мелочи несущественны, от тех, кто думает, что я трачу время зря и овчина выделки не стОит. Потом я подумал, что обо мне могут подумать, к примеру, теперь уже мои бывшие коллеги, инженеры контроля качества: мол этот ламер возомнил себя крутым хакером и думает, что он что-то понимает. Но потом я вспомнил как меня хвалил Imagegenixoid, подумал, что пост может кому-то быть интересен так, как он интересен мне. В итоге, я решил его написать.

Сейчас уже полночь, я хочу спать, у меня температура 37.2, но я решил, сделать это не откладывая.

Да и, собственно, почему меня должно волновать мнение о том, что я пишу в своём дневнике???!! Мне это интересно! Я

знаю, что я буду с удовльствие читать о своих исследованиях, когда мне будет лет 50 и когда я буду писать свои мемуары ;) Так что этот пост в некотором смысле ещё и прорыв. Прорыв через свои страхи, через неуверенность. Я буду писать о том, что мне интересно!