Лучшие вопросы
Таймлайн
Чат
Перспективы

Статический анализ кода

Из Википедии, свободной энциклопедии

Remove ads

Стати́ческий ана́лиз ко́да (англ. static code analysis) — анализ исходного кода программного обеспечения, производимый без реального выполнения исследуемых программ (в отличие от динамического анализа). В большинстве случаев анализ производится над исходным кодом, хотя иногда анализу подвергается объектный код, например P-код или код на MSIL. Термин обычно применяют к анализу, производимому специальным программным обеспечением (ПО), тогда как ручной анализ называют «program understanding» или «program comprehension» (пониманием программы).

В зависимости от используемого инструмента глубина анализа может варьироваться от определения поведения отдельных операторов до анализа всего имеющегося кода. Способы использования полученной в ходе анализа информации также различны — от выявления мест, возможно содержащих ошибки (утилиты типа Lint), до формальных методов, позволяющих математически доказать какие-либо свойства программы (например, соответствие поведения спецификации).

В некоторых источниках программные метрики и обратное проектирование рассматриваются как формы статического анализа. Получение метрик (англ. software quality objectives) и статический анализ часто совмещаются, особенно при создании встраиваемых систем[1].

Современные средства анализа, такие как Coverity, SonarQube, PVS-Studio, Clang Static Analyzer и Infer от Meta, используют методы анализа потока данных, контроля потока управления, а также абстрактной интерпретации для выявления ошибок, неочевидных при компиляции. Многие инструменты интегрируются в CI/CD-конвейеры и автоматизированные процессы разработки программного обеспечения для раннего выявления уязвимостей и дефектов.

Статический анализ играет важную роль в обеспечении безопасной разработки, соответствующей таким стандартам, как OWASP и MISRA C (в автомобильной индустрии), и широко применяется при разработке критически важных систем.

Remove ads

Принципы статического анализа

Суммиров вкратце
Перспектива

Примером простейшего статического анализа являются генерируемые большинством компиляторов (например, GCC) «предупреждения» (англ. warnings) — диагностические сообщения о потенциальной ошибочности синтаксически правильного кода. Например, для следующего кода на C может быть получено сообщение о неинициализированной переменной:

int x;
int y = x + 2;  // Переменная x не инициализирована!

В связи с высокими требованиями к скорости компиляции и качеству машинного кода, компиляторы проверяют код лишь на простейшие ошибки. Статические анализаторы предназначены для более детального исследования кода, включая межпроцедурный анализ, определение утечек памяти, проблем конкурентности и возможных уязвимостей.

Типы ошибок, обнаруживаемых статическими анализаторами

Статические анализаторы выявляют широкий спектр ошибок, которые могут привести к сбоям, уязвимостям и проблемам сопровождения программного обеспечения:

  • Неопределённое поведение — например, использование неинициализированных переменных, обращение к нулевым указателям. Простые случаи могут быть обнаружены ещё на этапе компиляции.
  • Нарушения контракта использования библиотек. Например, в языках с управлением файлами каждый вызов открытия файла должен сопровождаться вызовом его закрытия. Если файловая переменная теряется до закрытия, это может быть отмечено как ошибка.
  • Недокументированное поведение, возникающее при использовании конструкций, выходящих за рамки спецификации языка.
  • Переполнение буфера, особенно при использовании небезопасных функций (например, strcpy, sprintf) или при ошибках работы с массивами и указателями.
  • Ошибки кроссплатформенности. Например, приведение указателей к типу int может работать на 32-битных архитектурах, но потерять значимые данные на 64-битных:
Object *p = getObject();
int pNum = reinterpret_cast<int>(p);  // часть указателя теряется на x64
  • Копипаст-ошибки в повторяющемся коде — например, неправильное копирование строк с небольшими изменениями:
dest.x = src.x + dx;
dest.y = src.y + dx;  // ошибка: дублируется dx, а не dy
  • Ошибки форматных строк, особенно в языках со статической типизацией. Например:
std::wstring s;
printf("s is %s and d is %d", s);
  • Неиспользуемые или неизменные параметры, которые могут указывать на ошибки проектирования или устаревшую логику:
void doSomething(bool flag)   // flag всегда равен true
{
   if (flag)
       // какая-то логика
   else
       // код не используется
}
doSomething(true);
  • Утечки памяти и ресурсов. Несмотря на то, что динамические анализаторы лучше подходят для выявления таких проблем, статические инструменты также могут обнаруживать ошибки:
Traverser *t = new Traverser(Name);
if (!t->Valid())
{
  return FALSE; // выход без delete
  delete t;
}
  • Вызовы функций без побочных эффектов без использования возвращаемого значения:
std::string s;
s.empty();  // вызов ничего не делает; возможно, имелось в виду s.clear()
  • Прочие ошибки, зависящие от конкретного контекста и языка программирования.

Инструменты, такие как PVS-Studio, Coverity и Clang Static Analyzer, предоставляют различные уровни проверки, включая межпроцедурный анализ, анализ сложных выражений, контроль утечек памяти и другие формальные методы[2].

Remove ads

Применение

В последнее время статический анализ всё больше используется в верификации свойств ПО, используемого в компьютерных системах высокой надёжности, особенно критичных для жизни (safety-critical[англ.]). Также применяется для поиска кода, потенциально содержащего уязвимости (иногда это применение называется Static Application Security Testing, SAST)[3].

Статический анализ постоянно применяется для критического ПО в следующих областях:

  1. ПО для медицинских устройств[4];
  2. ПО для атомных станций и систем защиты реактора (Reactor Protection Systems)[5];
  3. ПО для авиации (в комбинации с динамическим анализом)[6];
  4. ПО на автомобильном или железнодорожном транспорте[7].

По данным VDC на 2012 год, примерно 28 % разработчиков встраиваемого ПО применяют средства статического анализа, а 39 % собираются начать их использование в течение 2 лет[8].

Remove ads

Формальные методы

Суммиров вкратце
Перспектива

Формальные методы — это строго определённые математические подходы, применяемые для доказательства корректности программного обеспечения на основе его спецификаций. В рамках статического анализа кода формальные методы позволяют не только находить ошибки, но и доказывать свойства программ, включая отсутствие определённых классов ошибок, таких как переполнение буфера, гонки данных или утечки памяти.

Примеры применения формальных методов:

  • Frama-C — платформа для анализа программ на языке C, использующая аннотации и абстрактную интерпретацию для доказательства корректности.
  • SPARK — формальный диалект языка Ada, предназначенный для разработки критичных к безопасности систем. Используется, например, в авионике и управлении железнодорожными системами[9].
  • Coq — интерактивная среда доказательств, применяемая для формальной верификации алгоритмов и программ. Используется в проектах типа CompCert, Bedrock и Verasco.
  • Why3 — платформа для формальной спецификации и верификации программ, интегрирующая различные автоматические доказатели (Z3, Alt-Ergo и др.).
  • Dafny — язык программирования с поддержкой формальной верификации. Компилятор может автоматически доказывать корректность кода относительно спецификации.

Формальные методы находят применение при разработке систем, критичных к безопасности, таких как авионика, медицинские устройства, автомобильные контроллеры и банковские системы. Несмотря на высокую стоимость внедрения, они позволяют существенно снизить риски, связанные с программными ошибками[10].

Инструменты статического анализа

Существует множество инструментов статического анализа, охватывающих различные языки программирования. Ниже приведён перечень наиболее известных из них, основанный в том числе на публикации CISO CLUB[11] и других источниках.

C/C++

C#

Java

JavaScript

.NET

PHP

  • PHPStan
  • Psalm
  • RIPS
  • YASCA
  • Visual Code Grepper
  • SonarQube

Python

  • Pylint
  • Pyflakes
  • Flake8
  • Pyright
  • mypy
  • Bandit[15]
  • McCabe
  • Solar appScreener

Ruby

  • Brakeman

Rust

  • clippy

Другие

  • SonarQube — многоплатформенный инструмент для анализа качества кода[16]
  • T-SQL Analyzer — анализатор SQL-скриптов и хранимых процедур для Microsoft SQL Server.
Remove ads

См. также

Примечания

Ссылки

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads