Основная цель статических анализаторов — найти ошибки, которые остались незамеченными разработчиком.
А недавно команда PVS-Studio снова столкнулась с интересным примером мощи этой техники.
Работа с инструментами статического анализа кода требует осторожности.
Зачастую код, на который указывает анализатор, оказывается корректным.
В таких случаях следует считать предупреждение ложным срабатыванием.
На днях мы сами попали в такую ловушку.
Вот как это произошло.
Недавно мы улучшено ядро анализатора , и коллега, просматривавший новые положительные результаты, обнаружил среди них ложный.
Он выписал триггер для тимлида, который быстро просмотрел код и создал задачу.
Я взялся за задание.
Таким простым способом образовалась цепочка из трех программистов.
Предупреждение анализатора: В645 Вызов функции strncat может привести к переполнению буфера a.consoleText. Границы не должны содержать размер буфера, а количество символов, которые он может содержать.
Фрагмент кода:
Прежде чем изучать пример, давайте вспомним, что делает функция стрнкат :struct A { char consoleText[512]; }; void foo(A a) { char inputBuffer[1024]; .
strncat(a.consoleText, inputBuffer, sizeof(a.consoleText) – strlen(a.consoleText) - 5); .
}
char *strncat(
char *strDest,
const char *strSource,
size_t count
);
Где:
- 'destination' — строка назначения;
- 'source' — исходная строка;
- «count» — максимальное количество символов, которое можно добавить.
Он вычисляет количество пустого места в буфере.
При этом вроде бы даже есть запас в 4 байта.
И именно из-за этого ощущения, что с кодом всё в порядке, его и написали в качестве примера, где анализатор выдаёт ложное предупреждение.
Давайте разберемся, как обстоят дела на самом деле.
В выражении: sizeof(a.consoleText) – strlen(a.consoleText) – 5
максимальное значение может быть достигнуто при минимальном значении второго операнда: strlen(a.consoleText) = 0
Тогда результатом будет 507 и переполнения не произойдет. О чем же тогда говорит PVS-Studio? Давайте углубимся во внутренние механизмы анализатора и попробуем разобраться.
В статическом анализаторе за вычисление таких выражений отвечает механизм анализа потока данных.
В большинстве случаев, когда выражение состоит из констант времени компиляции, поток данных вернет строгое значение выражения.
В других случаях, например в случае предупреждения, будет генерироваться только диапазон возможных значений выражения.
В этом случае значение операнда стрлен (a.consoleText) неизвестный нам на этапе компиляции.
Давайте посмотрим ассортимент. После нескольких минут отладки получаем из data-flow целых 2 диапазона: [0, 507] U [0xFFFFFFFFFFFFFFFC, 0xFFFFFFFFFFFFFFFF]
На первый взгляд кажется, что второй диапазон лишний.
Однако это не так.
Мы просто забыли, что результатом выражения может быть отрицательное число.
Например, это может произойти, когда стрлен(a.consoleText) = 508 .
В этом случае произойдет переполнение беззнакового числа, а результатом выражения будет максимальное значение типа результата, в данном случае — size_t .
Оказывается, анализатор прав! В этом выражении к полю консольтекст может добавить намного больше символов, чем его размер, что приведет к переполнение буфера и, как следствие, неопределенное поведение .
Причина неожиданного предупреждения в том, что ложного срабатывания здесь нет! Так мы в очередной раз получили подтверждение, что ключевое преимущество статического анализа перед человеком — его внимательность.
Вдумчивое изучение предупреждений анализатора помогает разработчику сэкономить время и нервы при отладке, защищает от ошибок и поспешных выводов.
Если вы хотите поделиться этой статьей с англоязычной аудиторией, воспользуйтесь ссылкой для перевода: Владислав Столяров.
Один день из жизни разработчика PVS-Studio, или Как я отладил диагностику, превзошедшую трех программистов .
Теги: #c++ #C++ #статический анализ кода #статический анализ #статический анализ #ложное срабатывание #статический анализатор #статический анализатор #strncat
-
Бескомпромиссная Замена 60-Ваттной Лампочке
19 Oct, 24 -
Финальный Хакатон Конкурса Budgetapps
19 Oct, 24 -
Жил-Был Компьютерщик Игнат™|||0.1
19 Oct, 24 -
Приносит Ли Медведев Победы?
19 Oct, 24