Лабораторная работа: Задание 4
Описание
Характеристики лабораторной работы
Список файлов
- Задание 4
- Aegis - результаты.htm 34,88 Kb
- StaticAnalysis
- FalsePositives
- FalsePositives.vcxproj 3,55 Kb
- FalsePositives.vcxproj.filters 972 b
- false_positives_sample.c 7,12 Kb
- Release
- FalsePositives.exe 10 Kb
- UndetectDefect.exe 7 Kb
- StaticAnalysis.sln 1,43 Kb
- StaticAnalysis.v12.suo 29 Kb
- UndetectDefect
- UndetectDefect.vcxproj 3,55 Kb
- UndetectDefect.vcxproj.filters 972 b
- undetect_defect_sample.c 1,08 Kb
- Task04.pdf 233,25 Kb
- answer
- 421_Vasilenko_false_positives.txt 3,16 Kb
- 421_Vasilenko_false_positives_sample.c 7,12 Kb
- 421_Vasilenko_undetect_defect.txt 2,09 Kb
- 421_Vasilenko_undetect_defect_sample.c 1,08 Kb
- 421_Vasilenko_zcomparison.txt 2,06 Kb
- заметки.txt 757 b
- Прочти меня!!!.txt 136 b
Я использовал Visual Studio 2013
Т.к. код не компилировался из-за того, что компилятор считает функцию fopen - unsafe,
то пришлось добавить в проект _CRT_SECURE_NO_WARNINGS в options -> C/C++ -> Preprocessor -> Preprocessor Definitions
После этого, проанализировав программу, анализатор выдал 4-ре ошибки
C6001Using uninitialized memoryUsing uninitialized memory 'result'.FalsePositivesfalse_positives_s ample.c71
'result' is not initialized54
Assume switch ( 'type' ) resolves to the default case55
'result' is an In/Out argument to 'push' (declared on line 15)71
'result' is used, but may not have been initialized71
C6031Return value ignoredReturn value ignored: 'fscanf'.FalsePositivesfalse_positives_s ample.c315
C6031Return value ignoredReturn value ignored: 'scanf'.FalsePositivesfalse_positives_sa mple.c333
C6031Return value ignoredReturn value ignored: 'scanf'.FalsePositivesfalse_positives_sa mple.c343
Первая ошибка - является более, чем правомерной, т.к. параметр result инициализируется в разных ветвях switch, но из-за отсутствия в нём клаузы default - если нам передали неверное значение в параметре функции (которое имеет тип int, а не enum, и потому мы не можем быть уверены, что нам не передали значение за границами обрабатываемых значений в case), то у нас не выполнится ни один из вариантов в switch и мы передадим неинициализированную переменную в параметр другой функции.
Оставшиеся 3 ошибки являются однотипными. И так же являются достаточно важными, потому что может произойти чтение не всех переменных в sscanf и тогда некоторые останутся не проинициализированными, а такое нужно обрабатывать
Более важно, что нету сообщения о небезопасном считывании, потому что есть возможность сделать buffer overflow
Анализ крайне недостаточный, т.к. не выявил такие важные ошибки, как:
1) стр. 22, 32 - как выход за пределы массива (многократно по обе стороны массива)
2) стр. 84 - неявное преобразование типов в функции isSpace: bool -> int, что нарушает логику, которая есть в missSpaces, что влечёт ошибку в 91 строке
3) стр. 116 - switch без default
4) стр. 265 - отсутствие необходимой обработки конца рекурсивного разбора строки, но эта ошибка является алгоритмической, и поэтому не учитывается в общей статистике
5) стр. 273, 288 - отсутствие проверки передаваемого указателя функции
6) стр. 299 - отсутствие закрытия файла
7) стр. 302 - отсутствие проверки успешного открытия файла
8) стр. 308 - отсутствие проверки успешного аллоцирования памяти
9) стр. 317 - нету указаний на возможный buffer overflow
10) стр. 332, стр. 345 - неправильное считывание используя scanf, т.к. тип, в который записывается значение не совпадает с форматом ввода (%f vs %lf для double)
всего 12 ошибок (4-я не учитывается по упомянутой причине)
Вывод: точность анализа - плохая
найденно лишь 4 из 16 ошибок, точность - 25%, но важно учитывать, что качество упущенных ошибок гораздо более весомое, и необнаруженные ошибки гораздо более критичны (на столько, что 3 однотипных ошибки, найденных анализатором являются вообще говоря ошибками в программе, но не являются ошибками безопасности), а среди упущенных ошибок такие важные, как buffer overflow
Анализатор нашёл лишль одну ошибку:
C6031Return value ignoredReturn value ignored: 'scanf'.UndetectDefectundetect_defect_sa mple.c25
Это ошибка обработки возвращаемого значения, которая в предыдущем примере была расмотренна.
Ошибки найденные посредством ручного Code Review:
1) На троке 38 в цикле for в случае неудачной попытки аллокации памяти, выполняется exit(-1) - что завершает процесс, однако не производится очистка уже аллоцированных ресурсов за предыдущие витки цикла, если ось отслеживает аллоцированную память, то она её очистит при удалени процесса, но в общем случае - это ошибка
2) Строка 47 - "Потеря указателя". Мы теряем указатель на начальную структуру el,
(ведь сами структуры организовываются подобно списку), и присвоив NULL - мы потеряли голову, и уже не сможем её вернуть.
Мы могли бы подумать, что указатель всё ещё остался лежать в p_current, т.к. он копировался на строке 29, однако этот указатель внутри цикла неоднократно присваивался (и только если пользователь 9 раз ввёл не приемлимые данные и сработал каждый раз continue указатель не будет потерян и программа завершится корректно)
3) Строка 52 - "Утечка памяти" - в момент окончания работы функции - была очищена лишь структура, на которую указывал p_current
но не были очищенны другие структуры, которые были аллоцированны на других витках цикла, и не была очищена структура, которая была аллоцированна на строке 21
Дефекты не были обнаружены анализатором по той, причине, что манипуляции с указателями имеют сложные зависимости и отследить их трудно даже в элементарных программах, и не при статическом анализе, а при динамическом, например при использовании valgrind
По этой причине отслеживание таких проблем, как утечка памяти, появление висячих ссылок, потеря указателя на аллоцированные данные - статическим анализатором, делающим code analysis - не отлавливаются
Вывод: точность анализа - плохая
среди 4-х ошибок найдена лишь одна, причём эта одна является единственной, не критичной с точки зрения безопасности, однако анализатор пропустил всё, что касалось утечек памяти
строго говоря точность - 25% (1 из 4-х ошибок)
Вывод о возможностях анализатора Visual Studio 2013:
Анализатор не способен отлавливать серьёзные ошибки, требующие хоть какого-то проявления взаимосвязей.
Он скорее может идти на ряду с такими средствами, как pylint для python - определяя скорее стиль программирования, нежели распознавая логику приложения и находя в ней ошибки.
Средство Aegis имело 3 особенности:
1) Была найдена возможность утечки памяти при вызове функций exit(-1)
"Зафиксирована утечка памяти в конструкции <exit(integer(0))>, выделенной в <<annotation>:0:0> в контексте <main() : <initialization>:0:0-> void * D.2563 = malloc(integer(16)) : source.c:21:9> (RES-01A)"
"Зафиксирована утечка памяти в конструкции <exit(integer(0))>, выделенной в <<annotation>:0:0> в контексте <main() : <initialization>:0:0-> void * D.2567 = malloc(integer(16)) : source.c:36:17> (RES-01A)"
2) Т.к. могла произойти ошибка при аллоцировании памяти, то потом везде aegis пишет, что возможна ошибка использования некорректного указателя, несмотря на наличие обработки ошибки после выделения памяти, так что тут он не прав
"Использование некорректного (INVALID) указателя char * ..."
или
"Использование некорректного (NULL) указателя double * ..."
в зависимости от того, как какому парамтеру мы обращаемся - к double или к char (что тоже странно, потому что не должно бытьразницы между тем, к какому полю структуры мы обращаемся)
3) Ошибка утечки памяти при потере указателя p_start и не очистке циклически выделенной памяти несколько раз - не было зафиксированно, однако именно тут и критична утечка памяти (потому что потеря памяти на exit - не является критичной, ибо ось сама освободит память), так что в общем можно сказать, что Aegis не заметил самого главного
Сравнение:
Aegis - гораздо более качественен, чем анализатор VS2013, однако всё равно является недостаточно качесвтенным, потому что можно вполне починить так, чтобы aegis не выявлял аномалий, однако из-за нарушения логики обращения с указателями и потере указателя p_start - всё равно осталась бы большая утечка памяти, которую никто не выявил, даже Aegis.
чтобы он нам там ни подал и в какой бы то ни было кодировке - там пробелы на самом деле не пробелы а фиг знает что
поэтому я чинил файлы следующим образом:
выделяем и копируем псевдо-пробел
Делаем Замену всех вхождения скопированного символа на настощий пробел введённый вами, и после этого компилятор съест
чтобы он не выдавал ошибки компилируя, нужно сходить в проект и добавить в options -> C/C++ -> Preprocessor -> Preprocessor Definitions
_CRT_SECURE_NO_WARNINGS
У многих всё равно не компилировалось, тогда стоит глянуть:
(В качестве проекта я создавал "Empty Project")
options -> C/C++ -> General -> Warning Level
options -> C/C++ -> Code Generation -> Security Check (например это отслеживало инициализированность переменной при printf)
Файл скачан с сайта StudIzba.com
При копировании или цитировании материалов на других сайтах обязательно используйте ссылку на источник
Начать зарабатывать