Стати́ческий ана́лиз ко́да (англ. 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 (в автомобильной индустрии), и широко применяется при разработке критически важных систем.

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

править

Примером простейшего статического анализа являются генерируемые большинством компиляторов (например, 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].

Применение

править

В последнее время статический анализ всё больше используется в верификации свойств ПО, используемого в компьютерных системах высокой надёжности, особенно критичных для жизни (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].

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

править

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

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

  • 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

править

Python

править

Ruby

править

Rust

править

Другие

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

См. также

править

Примечания

править
  1. Software Quality Objectives for Source Code. Proceedings Embedded Real Time Software and Systems 2010 Conference, ERTS2, Toulouse, France: Patrick Briand et al. PDF Архивная копия от 12 марта 2012 на Wayback Machine (архивировано)
  2. Да, PVS-Studio умеет выявлять утечки памяти Архивная копия от 15 мая 2018 на Wayback Machine / Блог компании PVS-Studio
  3. Improving Software Security with Precise Static and Runtime Analysis, Benjamin Livshits, section 7.3 "Static Techniques for Security, " Stanford doctoral thesis, 2006. http://research.microsoft.com/en-us/um/people/livshits/papers/pdf/thesis.pdf Архивная копия от 5 июня 2011 на Wayback Machine
  4. FDA. Infusion Pump Software Safety Research at FDA. Food and Drug Administration (8 сентября 2010). Дата обращения: 9 сентября 2010. Архивировано 1 сентября 2010 года.
  5. Computer based safety systems — technical guidance for assessing software aspects of digital computer based protection systems, http://www.hse.gov.uk/nuclear/operational/tech_asst_guides/tast046.pdf Архивная копия от 9 октября 2012 на Wayback Machine
  6. Position Paper CAST-9. Considerations for Evaluating Safety Engineering Approaches to Software Assurance Архивная копия от 6 октября 2013 на Wayback Machine // FAA, Certification Authorities Software Team (CAST), January, 2002: «Verification. A combination of both static and dynamic analyses should be specified by the applicant/developer and applied to the software.»
  7. Bill Graham. Static Analysis, Safety-Critical Railway Software, and EN 50128. Дата обращения: 2 сентября 2016. Архивировано 25 августа 2016 года.
  8. VDC Research. Automated Defect Prevention for Embedded Software Quality. VDC Research (1 февраля 2012). Дата обращения: 10 апреля 2012. Архивировано 7 апреля 2012 года.
  9. John Barnes, «High Integrity Software: The SPARK Approach to Safety and Security», Addison-Wesley, 2003
  10. Daniel Jackson. Software Abstractions: Logic, Language, and Analysis. — MIT Press, 2012. — ISBN 978-0-262-51862-3.
  11. ТОП бесплатных инструментов для статического анализа кода. cisoclub.ru (11 февраля 2021). Дата обращения: 19 ноября 2021. Архивировано 19 сентября 2021 года.
  12. Clang Static Analyzer. clang-analyzer.llvm.org. Дата обращения: 14 мая 2016. Архивировано 8 октября 2011 года.
  13. Coverity Static Application Security Testing (SAST). Дата обращения: 15 мая 2025. Архивировано 14 мая 2025 года.
  14. SpotBugs. Дата обращения: 15 мая 2025. Архивировано 16 мая 2025 года.
  15. Bandit documentation. Дата обращения: 15 мая 2025.
  16. SonarQube - Static Code Analysis. Дата обращения: 15 мая 2025. Архивировано 16 мая 2025 года.

Ссылки

править

📚 Artikel Terkait di Wikipedia

Безопасность доступа к памяти

current running one).» Anders Moller and Michael I. Schwartzbach. Static Program Analysis. — Department of Computer Science, Aarhus University, 2015. — Май

Динамический анализ кода

Динамический анализ кода (англ. Dynamic program analysis) — анализ программного обеспечения, производящийся при помощи выполнения программ на реальном

PVS-Studio

Владимир Кошелев (ИСП РАН), 2016 5W+1H Static Analysis Report Quality Measure / Tools and Methods of Program Analysis: 4th International Conference, TMPA

Метод Рунге — Кутты

интегрирования task.NextStep(dt); } Console.ReadLine(); } } class Program { static void Main(string[] args) { TMyRK.Test(); } } } В программе на С# используется

Кузо, Радия

Static Analysis of Programs by Construction or Approximation of Fixpoints», POPL, 1977. Patrick Cousot, Radhia Cousot, «Systematic Design of Program Analysis

Удаление мёртвого кода

Алгоритм «Dead» был впервые опубликован в статье «Static Single Assignment Form and the Program Dependence Graph» в журнале ACM TOPLAS в 1991 году.

SimScale

Simulation Project: Static Structural Analysis of a Gripper Arm . Архивировано 30 августа 2017 года. SimScale Simulation Project: Contact analysis of a consumer

Иппотерапия

Dipla K, Liga M, Kellis E. Effect of a hippotherapy intervention program on static balance and strength in adolescents with intellectual disabilities