Вебинар: ГОСТ Р 71207–2024 — Статический анализ программного обеспечения. Процессы - 13.09
Другие названия: сопоставления с шаблоном, pattern-based analysis.
Это обнаружение в коде паттернов ошибок, которые укладываются в определённый шаблон. Простой пример — присваивание переменной самой себе:
acx->window_size = acx->window_size;
Хотя подобные ошибки очевидны, а диагностики для их выявления обычно просты, это не обесценивает работу статического анализа по их выявлению. Так, приведённый выше пример не является синтетическим, а обнаружен с помощью анализатора PVS-Studio в коде Linux Kernel:
int wl12xx_acx_config_hangover(struct wl1271 *wl)
{
....
acx->recover_time = cpu_to_le32(conf->recover_time);
acx->hangover_period = conf->hangover_period;
acx->dynamic_mode = conf->dynamic_mode;
acx->early_termination_mode = conf->early_termination_mode;
acx->max_period = conf->max_period;
acx->min_period = conf->min_period;
acx->increase_delta = conf->increase_delta;
acx->decrease_delta = conf->decrease_delta;
acx->quiet_time = conf->quiet_time;
acx->increase_time = conf->increase_time;
acx->window_size = acx->window_size; // <=
....
}
Как видите, ошибка связана с невнимательностью программиста при написании однотипного кода. При обзоре кода подобные ошибки также сложно замечать, так как человек быстро теряет сосредоточенность. Здесь на помощь приходят инструменты статического анализа кода, которые не устают.
Такие простые ошибки вовсе не редки, как может показаться, и встречаются в коде даже известных проектов. Вы можете познакомиться с некоторыми другими примерами в нашей коллекции ошибок.
Как уже было сказано, сигнатурный анализ сравнительно прост. Однако в чистом виде он редко применяется, так как требуется дополнительная информация, например, о типах, чтобы сократить число ложных срабатываний.
Другими словами, некоторые ошибки можно искать даже регулярными выражениями, но качество такого анализа будет низким в силу большого числа ложноотрицательных и ложноположительных срабатываний. Поэтому часть ошибок не будет найдена, и при этом будут лишние предупреждения о проблемах там, где их нет.
Рассмотрим это на примере поиска повторяющихся условий в if-else-if конструкциях:
if (A < B) { .... }
else if (B > A) { .... }
Второе условие всегда ложно, так как на самом деле дублирует первое. Это классический паттерн опечатки (примеры в реальных приложениях).
Если искать повторяющиеся условия регулярными выражениями, это станет крайне непростым делом, так как придётся рассматривать множество вариантов, как может проявить себя этот паттерн ошибки:
if (A < B) ....
else if (A < B) ....
if (A & B == 0) ....
else if (0 == B & A) ....
if (A < B) ....
else if (x == y) .... // промежуточные проверки
else if (A < B) ....
В результате будет выявляться малая часть опечаток подобной разновидности.
На самом деле всё ещё сложнее. Статический анализатор должен учитывать дополнительную информацию. Например, что операторы не перегружены, или что в условии происходит изменение переменных:
if ((A = get()) < B) ....
else if ((A = get()) < B) .... // предупреждение выдавать не надо
Так что регулярные выражения не подходят для многих, даже на первый взгляд простых, случаев. Поэтому, хотя регулярные выражения используется для некоторых задач статичного анализа, их сфера применения крайне мала.
Возьмём, например, анализатор кода PVS-Studio (ядро для анализа C и C++ кода). В нём регулярные выражения как-то используются только в пяти из около 700 диагностик, реализованных на момент написания этой заметки.
Сигнатурный анализ в PVS-Studio и других современных анализаторах строится на основе поиска паттернов и закономерностей при обходе синтаксического дерева. При этом для улучшения качества анализа учитывается информация о потоках управления, потоках данных и так далее.
ГОСТ Р 71207-2024 — Статический анализ программного обеспечения. В разделе терминов дано следующее определение сигнатурного анализа:
Статический анализ, определяющий наличие свойства программы при помощи поиска строк в исходном коде программы по некоторому образцу, в том числе заданному с помощью формального языка поиска, например при помощи регулярных выражений.
Дополнительные ссылки:
0