Культура

Превратили PVS-Studio в город

Вы когда-нибудь хотели взглянуть на свой код под новым углом? Например, увидеть, как бы выглядела ваша кодовая база, будь она городом? Звучит как что-то невероятное. Давайте вместе заглянем в город PVS-Studio и посмотрим, какие тайны он в себе хранит :). Начнём с начала Гуляя по просторам интернета, мы наткнулись на инструмент, который может представить код в виде города. Grappl строит визуальную карту вашей кодовой базы, показывая масштаб и иерархию всех файлов и классов. А получившаяся картина захватывает дух, и вы будто летите над собственным проектом. Если вы, как и я, когда-то задавались вопросом, как выглядит собственный код с высоты птичьего полёта, то теперь ответ на этот вопрос можно получить при помощи текстового редактора Visual Studio Code и расширения Grappl. Создатели инструмента предлагают это решение для следующих задач: визуализация архитектуры кодовой базы для улучшения взаимодействия между техническими и нетехническими членами команды (например, менеджерами и аналитиками); автоматическое связывание между собой кода, задач из таск-трекеров (вроде Trello или Jira) и коммитов. Это должно ускорять процесс доставки кода, сокращать время на его обслуживание и помогать рецензентам и тестировщикам. Однако сегодня я предлагаю немного побаловаться и просто поисследовать здания нашего огромного города PVS-Studio. В Grappl каждому типу элементов кода соответствует свой цвет. Для наглядности разберёмся с обозначениями по следующей схеме: Для начала протестируем инструмент на других проектах. Так как мы часто проверяем разные проекты с помощью нашего анализатора, у меня сохранилось несколько репозиториев. Возьмём, к примеру, проект PHP. Про ошибки в этом проекте я писала статью. Взгляните на архитектуру его кодового города: На этой карте мы видим множество файлов, функций и структур, но полностью отсутствуют классы и пространства имён. Всё дело в том, что код написан на C, где этих сущностей просто нет. Если вы уже изучили эту карту, то наверняка, обратили внимание на высокие синие башни. Мне стало интересно, что скрывается в самой левой из них. Оказалось, что это функция lex_scan(zval * , zend_parser_stack_elem * ) из файла Zend/zend_language_scanner.c . Её размер составляет около десяти тысяч строк, что и объясняет, почему здание такое высокое. Ещё один пример — проект Xenia на языке C++. Мы также проверяли его с помощью PVS-Studio, а с результатами анализа можно ознакомиться в этой статье. А вот как выглядит его город: Сам проект небольшой, поэтому парсинг кода не занял много времени, но результат впечатляет. Тут уже можно увидеть большое количество разных пространств имён и классов. Сравните эту карту с PHP. Если проект на C был похож на Вашингтон, то здесь мы видим уже Нью-Йорк. А благодаря разделению их собственного кода от third-party -библиотек, вдали от города мы можем увидеть этот "посёлок городского типа", чей код значительно уступает по объёму основной части. Ну и какой же город этот ваш PVS-Studio? Мы посмотрели на города других проектов, но настоящая магия начинается, когда визуализируешь инструмент, которым пользуешься каждый день. Краткая памятка PVS-Studio — статический анализатор кода, который развивается на рынке уже более 15 лет. Изначально он был создан для поиска проблем при переходе с 32-битных на 64-битные системы и поддерживал языки C и C++. Однако со временем его функциональность значительно расширилась, и сегодня он эффективно выявляет широкий спектр ошибок общего назначения. Узнать больше об этапах развития проекта можно по ссылке. Сейчас PVS-Studio может находить ошибки не только в коде на языках C и C++, но и в C# и Java. Кроме того, анализатор имеет обширный набор диагностических правил, выявляющих потенциальные уязвимости из перечня CWE, критические ошибки согласно ГОСТ Р 71207-2024, а также отклонения от стандартов MISRA и OWASP ASVS. Сегодня я предлагаю посмотреть на визуализацию кода C и C++ анализатора. Поскольку я сама занимаюсь разработкой этой части в инструменте, мне очень интересно узнать, как именно будет выглядеть наш город. Давайте же заглянем под капот и изучим архитектуру PVS-Studio. Перед нами огромный город, и его структура многое говорит о проекте. В глаза бросается чёткое разделение на районы, поэтому предлагаю пройтись по ключевым. Обширный жилой квартал: модули тестирования Не удивляйтесь такому большому размеру нашей тестовой базы — создание качественного продукта требует тщательного тестирования на тысячах примеров, причём это лишь малая часть. Мы также проводим дополнительное тестирование на группе открытых проектов, которые не входят в эту визуализацию. Но если говорить про этот набор тестов, то он включает в себя несколько частей. На схеме отмечены следующие тесты: Rules — функциональные тесты диагностических правил. Это наш главный индикатор: любые изменения в ядре или диагностических правилах сразу отражаются здесь, показывая прогресс или регресс; DocumentationTests — функциональные тесты, проверяющие, что анализатор выдаёт предупреждения на примеры из документации. Если в документации описана ошибка — анализатор обязан её найти; ParseTests — функциональные тесты парсинга кода. Большинство тестов — это комбинация наибольшего числа стандартных заголовочных файлов, которые мы генерируем с помощью утилиты. Цель — проверить, что парсинг кода проходит без ошибок или падений. Мы пополняем их при значительных изменения в стандартной библиотеке; UETests — функциональные тесты, проверяющие работу анализатора с нестандартными контейнерами игрового движка Unreal Engine; StructTests — тесты на точность вычисления размеров и выравниваний структур. Именно поэтому здесь их так много — мы проверяем все возможные сценарии; AnnotationsTests — функциональные тесты работы системы пользовательских аннотаций, которые позволяют размечать типы и функций в формате JSON с целью дать анализатору дополнительную информацию; CodeCheck — функциональные тесты, проверяющие разнообразные конструкции, специфичные для компиляторов. Как вы могли заметить, чтобы надёжно находить ошибки в ваших кодовых базах, PVS-Studio проходит через большое количество тестов, в том числе через самопроверку. Если вы хотите попробовать наш статический анализатор на своём продукте, то получить триал можно по ссылке. Крупный деловой район: ядро анализатора Именно здесь сосредоточена основная работа PVS-Studio. Отмечу, что сейчас мы активно занимаемся масштабной переработкой нашего фреймворка, поэтому в кодовой базе параллельно сосуществуют два ядра. Это позволяет нам последовательно переносить функциональность на новую архитектуру, обеспечивая плавный переход. Новое ядро разрабатывается нами около двух лет, но уже сейчас можно заметить, что оно больше старого. И это при том, что мы всё ещё используем прежние модули, такие как препроцессор и лексер. Но чтобы понять, как далеко мы продвинулись, стоит начать с начала. В сердце нашего города происходит магия статического анализа. Давайте заглянем внутрь старого ядра. Для того, чтобы изучить ядро получше, предлагаю перенестись на "стройплощадку" — в процесс анализа кода. Все начинается с препроцессора. Сначала мы грузим *.i файл, сгенерированный внешним препроцессором, и выполняем его первоначальную подготовку: заменяем табы на пробелы; удаляем BOM; записываем builtin-функции; обрабатываем наши специальные комментарии; сопоставляем исходный и препроцессированный файлы через директивы #line ;отслеживаем расхождения в нумерации строк между файлами. Потом такой код отправляется на "разборки" к лексеру (Lexer). Да, он невелик, но выполняет критически важную работу: разбивает сплошной текст программы на базовые кирпичики — токены (ключевые слова, операторы, идентификаторы и т. д.). После эти токены передаются парсеру (Parser). Его задача — понять структуру кода, собрав из разрозненных кирпичиков целую архитектурную схему — синтаксическое дерево. Именно по этому дереву и будут путешествовать наши диагностические правила. После построения дерева за работу принимается семантический анализатор (Analyzer). В его задачи входит построение системы типов, ведение символьных таблиц и установление семантических связей между элементами кода. Исторически сложилось, что в оригинальной архитектуре семантический анализатор и парсер функционировали независимо друг от друга, что создавало определённые ограничения для развития системы. А вот в релизе PVS-Studio 7.38 было добавлено новое ядро. Оно включает в себя полностью переработанные компоненты: парсер, семантический анализатор и систему типов. И оно получилось в разы больше: В новой архитектуре парсер и семантический анализатор работают в тесной связке, формируя синтаксическое дерево. Более того, в новое ядро уже заложена основа для абстрактного синтаксического дерева (AST), которое ждёт завершения доработок для полного включения в работу. А пока что парсер формирует дерево старого типа с помощью SyntaxTreeBuilder. Неотъемлемой частью анализатора является блок аннотаций — внутренняя и внешняя система аннотирования сущностей. Благодаря ей мы понимаем намного больше о проверяемом коде. Система содержит семантику классов стандартной библиотеки, информацию о поведении функций, их предусловиях и побочных эффектах. Также в этой части находится механизм пользовательских аннотаций в формате JSON. После того, как дерево построено, к нему нужно добавить больше деталей. Для этого используется анализ потока данных (data-flow analysis), который отслеживает значения переменных, спускаясь по коду программы. Он позволяет находить хитрые ошибки: знаковое переполнение, деление на ноль, доступ за пределами выделенного буфера и др. А когда весь код становится понятен анализатору, в работу включаются диагностические правила. Пункт управления: статический анализатор Здесь сосредоточены ключевые компоненты, отвечающие за организацию работы: парсеры командной строки и конфигурационных файлов обрабатывают пользовательские настройки и определяют параметры анализа; система настроек анализа предоставляет гибкие механизмы настройки процесса проверки под конкретные задачи; диспетчер диагностических правил всегда подскажет, какие из них включены и какое предупреждение из списка кандидатов лучше всего вывести пользователю на определённой строке; обходчик дерева кода последовательно проходит построенное дерево и активирует диагностические правила в соответствующих узлах. Именно этот компактный, но критически важный район запускает работу ядра и интеллектуального центра, о котором мы сейчас тоже узнаем. Интеллектуальный центр: диагностические правила А вот и самая густонаселённая зона нашего города, где находится более 700 специалистов по анализу кода. Каждое диагностическое правило — узкопрофильный эксперт, и вместе они составляют идеальную команду для проверки проектов. Здесь можно увидеть не только большое количество диагностических правил, но и файлы, которые содержат все сообщения предупреждений, утилиты, а также объявления функций разных диагностических групп. Можно заметить, что диагностическое правило V826 выделяется на фоне остальных. Это связанно со сложностью анализа для использованных контейнеров: диагностика должна распознать паттерны доступа к данным, вычислить алгоритмическую сложность операций и определить оптимальную замену стандартного контейнера. Заканчиваем путешествие Карта PVS-Studio — это не просто красивая визуализация, а отражение сложной, но продуманной архитектуры, где каждый район играет свою роль в поиске дефектов кода. Стройте город из своего кода и делитесь впечатляющими видами в комментариях :) Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Aleksandra Uvarova. Building the PVS-Studio megapolis.

Фильтры и сортировка