Статический анализ кода
Стати́ческий ана́лиз ко́да (англ. static code analysis) — анализ программного обеспечения, производимый (в отличие от динамического анализа) без реального выполнения исследуемых программ. В большинстве случаев анализ производится над какой-либо версией исходного кода, хотя иногда анализу подвергается какой-нибудь вид объектного кода, например P-код или код на MSIL. Термин обычно применяют к анализу, производимому специальным программным обеспечением (ПО), тогда как ручной анализ называют «program understanding», «program comprehension» (пониманием или постижением программы).
В зависимости от используемого инструмента глубина анализа может варьироваться от определения поведения отдельных операторов до анализа, включающего весь имеющийся исходный код. Способы использования полученной в ходе анализа информации также различны — от выявления мест, возможно содержащих ошибки (утилиты типа Lint), до формальных методов, позволяющих математически доказать какие-либо свойства программы (например, соответствие поведения спецификации).
Некоторые люди считают программные метрики и обратное проектирование формами статического анализа. Получение метрик (англ. software quality objectives) и статический анализ часто совмещаются, особенно при создании встраиваемых систем.[1]
Принципы статического анализа
Большинство компиляторов (например, GNU C Compiler) выводят на экран «предупреждения» (англ. warnings) — сообщения о том, что код, будучи синтаксически правильным, скорее всего, содержит ошибку. Например:
int x;
int y = x+2; // Переменная x не инициализирована!
Это простейший статический анализ. У компилятора есть много других немаловажных характеристик — в первую очередь скорость работы и качество машинного кода, поэтому компиляторы проверяют код лишь на очевидные ошибки. Статические анализаторы предназначены для более детального исследования кода.
Типы ошибок, обнаруживаемых статическими анализаторами
- Неопределённое поведение — неинициализированные переменные, обращение к NULL-указателям. О простейших случаях сигнализируют и компиляторы.
- Нарушение алгоритма пользования библиотекой. Например, для каждого
fopen
нуженfclose
. И если файловая переменная теряется раньше, чем файл закрывается, анализатор может сообщить об ошибке. - Типичные сценарии, приводящие к недокументированному поведению. Стандартная библиотека языка Си известна большим количеством неудачных технических решений. Некоторые функции, например,
gets
, в принципе небезопасны.sprintf
иstrcpy
безопасны лишь при определённых условиях. - Переполнение буфера — когда компьютерная программа записывает данные за пределами выделенного в памяти буфера.
void doSomething(const char* x)
{
char s[40];
sprintf(s, "[%s]", x); // sprintf в локальный буфер, возможно переполнение
....
}
- Типичные сценарии, мешающие кроссплатформенности.
Object *p = getObject();
int pNum = reinterpret_cast<int>(p); // на x86-32 верно, на x64 часть указателя будет потеряна; нужен intptr_t
- Ошибки в повторяющемся коде. Многие программы исполняют несколько раз одно и то же с разными аргументами. Обычно повторяющиеся фрагменты не пишут с нуля, а размножают и исправляют.
dest.x = src.x + dx;
dest.y = src.y + dx; // Ошибка, надо dy!
- Ошибки форматных строк — в функциях наподобие
printf
могут быть ошибки с несоответствием форматной строки реальному типу параметров.
std::wstring s;
printf ("s is %s", s);
- Неизменный параметр, передаваемый в функцию — признак изменившихся требований к программе. Когда-то параметр был задействован, но сейчас он уже не нужен. В таком случае программист может вообще избавиться от этого параметра — и от связанной с ним логики.
void doSomething(int n, bool flag) // flag всегда равен true
{
if (flag)
{
// какая-то логика
} else
{
// код есть, но не задействован
}
}
doSomething(n, true);
...
doSomething(10, true);
...
doSomething(x.size(), true);
- Утечки памяти и других ресурсов. Ради справедливости следует отметить, что в целом статические анализаторы проигрывают в сфере поиска утечек динамическим анализаторам кода.[2]
Traverser *t = new Traverser(Name);
if (!t->Valid())
{
return FALSE; // Случайно написали return до delete.
delete t;
}
- Прочие ошибки — многие функции из стандартных библиотек не имеют побочного эффекта, и вызов их как процедур не имеет смысла.
std::string s;
...
s.empty(); // код ничего не делает; вероятно, вы хотели s.clear()?
Применение
В последнее время статический анализ всё больше используется в верификации свойств ПО, используемого в компьютерных системах высокой надёжности, особенно критичных для жизни (safety-critical). Также применяется для поиска кода, потенциально содержащего уязвимости (иногда это применение называется Static Application Security Testing, SAST).[3]
Статический анализ постоянно применяется для критического ПО в следующих областях:
- ПО для медицинских устройств.[4]
- ПО для атомных станций и систем защиты реактора (Reactor Protection Systems)[5]
- ПО для авиации (в комбинации с динамическим анализом)[6]
- ПО на автомобильном или железнодорожном транспорте[7]
По данным VDC на 2012 год, примерно 28 % разработчиков встраиваемого ПО применяют средства статического анализа, а 39 % собираются начать их использование в течение 2 лет.[8]
Формальные методы
Инструменты статического анализа
Инструменты по анализируемым языкам, некоторый из которых выделяет CISO CLUB[9]:
C/C++:
- BLAST
- Clang Static Analyzer (встроен в Clang)[10]
- Coverity
- PC-Lint
- lint и lock_lint, входящие в состав Sun Studio
- Cppcheck (Cppcheck on sf)
- Parasoft C/C++Test
- Solar appScreener
- SourceAnalyzer (также Fortran и x86 asm)
- PVS-Studio
- LDRA Testbed
- Polyspace
- QA-C
- Cantata++
- Visual Code Grepper
C#:
- CodeCrawler
- Visual Code Grepper
- Code Warrior
Java:
- fbinfer
- FindBugs (FindBugs on sf)
- JsHint
- PVS-Studio
- Parasoft JTest
- RIPS
- Solar appScreener
- YASCA
- Code Warrior
JavaScript:
.NET:
- .NET Compiler Platform (Roslyn) — фреймворк компилятора для C# и VB.NET, предоставляющий интерфейс для анализатора.
- FxCop
- Microsoft FxCop
- NDepend
- PVS-Studio
- ReSharper
- StyleCop
- YASCA
PHP:
- Graudit
- RIPS
- Solar appScreener
- YASCA
- Visual Code Grepper
- Code Warrior
Ruby:
- Brakeman
- Code Warrior
Другие:
- T-SQL Analyzer — инструмент, который может просматривать программные модули в базах данных под управлением Microsoft SQL Server 2005 или 2008 и обнаруживать потенциальные проблемы, связанные с низким качеством кода.
- АК-ВС 2 от ЗАО "НПО "Эшелон" (Поиск НДВ, выявление опасных шаблонов по CWE[13])
- SonarQube — платформа анализа и управления качеством кода с поддержкой различных языков программирования через систему плагинов.
- AppChecker — коммерческий статический анализатор кода от "НПО "ЭШЕЛОН", предназначенный для автоматизированного поиска дефектов в исходном коде приложений, разработанных на С#, C/C++, Java, PHP.
- Svace — инструмент статического анализа, разработанный в ИСП РАН. Поддерживает языки программирования C/C++, Java, C#.[14]
См. также
Примечания
- Software Quality Objectives for Source Code. Proceedings Embedded Real Time Software and Systems 2010 Conference, ERTS2, Toulouse, France: Patrick Briand, Martin Brochet, Thierry Cambois, Emmanuel Coutenceau, Olivier Guetta, Daniel Mainberte, Frederic Mondot, Patrick Munier, Loic Noury, Philippe Spozio, Frederic Retailleau http://www.erts2010.org/Site/0ANDGY78/Fichier/PAPIERS%20ERTS%202010/ERTS2010_0035_final.pdf Архивная копия от 12 марта 2012 на Wayback Machine
- Да, PVS-Studio умеет выявлять утечки памяти / Блог компании PVS Studio
- 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
- FDA Infusion Pump Software Safety Research at FDA . Food and Drug Administration (8 сентября 2010). Дата обращения: 9 сентября 2010.
- 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
- Position Paper CAST-9. Considerations for Evaluating Safety Engineering Approaches to Software Assurance // 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.»
- Bill Graham. Static Analysis, Safety-Critical Railway Software, and EN 50128 . Дата обращения: 2 сентября 2016.
- VDC Research Automated Defect Prevention for Embedded Software Quality . VDC Research (1 февраля 2012). Дата обращения: 10 апреля 2012.
- ТОП бесплатных инструментов для статического анализа кода (рус.) ?. cisoclub.ru (11 февраля 2021). Дата обращения: 19 ноября 2021.
- Clang Static Analyzer . clang-analyzer.llvm.org. Дата обращения: 14 мая 2016.
- Anand Balachandran Pillai. Software Architecture with Python. — Packt Publishing Ltd, 2017. — С. 63-64.
- Adam Goucher, Tim Riley. Beautiful Testing: Leading Professionals Reveal How They Improve Software. — O'Reilly Media, Inc., 2009. — P. 126.
- Аудит программного кода по требованиям безопасности — Информационная безопасность, аудит, программный код, безопасность, Алексей Марков, Валентин Цирлов, CISSP, security code …, ЗАО "НПО "Эшелон"
- Статический анализатор Svace. Промышленный поиск критических ошибок в безопасном цикле разработки программ
Ссылки
- О безошибочных программах // «Открытые системы», № 07, 2004
- Первые шаги к решению проблемы верификации программ // «Открытые системы», № 08, 2006
- Статический анализ безопасности кода // Программная инженерия и информационная безопасность. 2013 № 1, стр 50 (npo-echelon.ru)
- http://www.drdobbs.com/testing/deploying-static-analysis/240003801
- Коллекция ошибок, обнаруженных в Open Source проектах с помощью статического анализа кода // PVS-Studio (viva64.com)