Edit markers (command line)

From Svacer Wiki
Revision as of 12:05, 19 November 2025 by Gribunin (talk | contribs) (edit-markers change descriptions to more correct description)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Обзор

Функциональность edit-markers позволяет автоматически обрабатывать маркеры при импорте данных с помощью правил, заданных в JSON-файле. Поддерживаются три типа операций:

  • skip — пропуск (удаление) маркеров, соответствующих условию
  • change — изменение полей маркеров
  • deduplicate — объединение дублирующихся маркеров. У маркеров, подходящих под правило, объединяются уникальные трассы и остается только один маркер с наименьшим порядковым номером предупреждения (local_id) в файле результатов анализа. Остальные маркеры удаляются.

Все операции происходят на стороне клиента до загрузки данных на сервер. При импорте результатов Svace, а также sarif (без указания флага --upload) изменяется .svacer-dir. Директория .svace-dir остается неизменной. Снимок остается неизменным при импорте.

Данный функционал работает со снимками, созданными Svacer версии 7-0-0 и новее. Если у вас более старый снимок, то импортируйте и экспортируйте его для возможности работы с edit-markers.

Использование

Импорт результатов Svace

svacer import --edit-markers <файл_правил.json> [другие опции]

Применяет правила редактирования к маркерам при импорте результатов анализа Svace.

Импорт SARIF

svacer sarif2 import --edit-markers <файл_правил.json> [другие опции]

Применяет правила при импорте SARIF-файлов.

Импорт снимка с редактированием

svacer server import --edit-markers <файл_правил.json> [другие опции]

Применяет правила к снимку при импорте. Дополнительно можно сохранить отредактированный снимок:

svacer server import --edit-markers rules.json --save-edited-snapshot edited_snapshot.snap

Формат файла правил

Правила задаются в виде JSON-файла, содержащего массив объектов правил:

[
 {
   "action": "тип_действия",
   "rules": "условие_или_список_полей",
   "change": { /* только для action: "change" */ }
 },
 ...
]

Типы действий

skip — Пропуск маркеров

Удаляет маркеры, соответствующие условию.

...
{
  "action": "skip",
  "rules": "file == 'test.cpp' and line > 100"
}
...

change — Изменение маркеров

Изменяет указанные поля маркеров.

...
{
  "action": "change",
  "rules": "warnclass == 'UNREACHABLE_CODE'",
  "change": {
    "warnclass": "IGNORED",
    "msg": "Код помечен как недостижимый"
  }
}
...

Доступные поля для изменения: warnclass, msg, lang, tool, file, details, line, mtid, function.

deduplicate — Дедупликация

Объединяет маркеры с одинаковыми значениями указанных полей. Один маркер выбирается случайно, все trace от остальных маркеров добавляются к нему.

...
{
 "action": "deduplicate",
 "rules": "file,line,warnclass"
}
...

Поля для группировки (можно указать от 1 до 8): file, line, function, warnclass, lang, tool, mtid, details.

Доступные поля и операторы

Поля маркеров

В условиях можно использовать следующие поля:

  • file — полный путь к файлу (строка)
  • line — номер строки (число)
  • function — имя функции (строка)
  • warnclass — класс предупреждения (строка)
  • lang — язык программирования (строка)
  • tool — инструмент анализа (строка)
  • mtid — ID типа маркера (строка)
  • msg — сообщение маркера (строка)
  • details — детали маркера (строка)

Операторы сравнения

  • ==, != — равно, не равно
  • >, >=, <, <= — сравнение чисел
  • and, or, &&, || — логические операторы
  • not, ! — логическое НЕ
  • in — проверка вхождения в список (например: warnclass in ['ERROR', 'WARNING'])
  • contains — проверка вхождения подстроки

Функции для работы со строками

  • icontains(s, substring) — содержит подстроку (без учета регистра)
  • hasPrefix(s, prefix) — начинается с префикса
  • hasSuffix(s, suffix) — заканчивается суффиксом
  • equalsFold(a, b) — сравнение строк без учета регистра
  • lower(s) — преобразование в нижний регистр
  • upper(s) — преобразование в верхний регистр
  • trim(s) — удаление пробелов в начале и конце строки
  • replace(s, old, new) — замена всех вхождений подстроки
  • regex(s, pattern) — проверка соответствия регулярному выражению
  • nregex(s, pattern) — проверка НЕсоответствия регулярному выражению

Примеры

Часть примеров используют снимок bash. Детекторы в данном снимке выглядят так:

Пропуск файлов

В данном примере будут пропущены все файлы, которые находятся в папке /.build/lib

[
 {
   "action": "skip",
   "rules": "file contains '/.build/lib'"
 }
]

Сравнивая исходный снимок и снимок, где было применено edit-markers можно увидеть 215 пропущенных детекторов. Все они находятся в папке /.build/lib

Если необходимо указать название не зависимо от регистра, то можно использовать функцию icontains:

[ { "action": "skip", "rules": "icontains(file, '/.build/lib')" } ]

Также после применения edit-markers в информации о снимке указывается, какие правила были применены

Изменение класса предупреждений

При необходимости возможно изменение полей маркера. В данном примере изменим warnclass маркеров у которых в названии есть UNREACHABLE_CODE и находящиеся после 1000 строки, но детектор UNREACHABLE_CODE изменять не будем.

[
 {
   "action": "change",
   "rules": "warnclass contains 'UNREACHABLE_CODE' and line > 1000",
   "change": {
     "warnclass": "UNREACHABLE",
     "msg": "Изменено правилами edit markers"
   }
 }
]

Указанные маркеры изменили свой детектор и описание.

Серьезность, Надежность и CWE привязаны к названию warnclass (детектора), поэтому, если указать несуществующий warnclass, то данные поля пропадут.

Удаление дубликатов

Если необходимо объединить несколько детекторов в один по одинаковым полям, то возможно сделать следующее действие (в качестве полей rules можно указать 8 возможных значений, см. описание deduplicate). Например, в снимке содержится множество одинаковых детекторов в одном файле на одной строке.

Применив следующее правило все маркеры, которые находятся в одном файле, с одним детектором и на одной строке объединятся в один: выберется один с наименьшим порядковым номером предупреждения в файле результатов анализа (local_id) и у него будет объединенные уникальные трассы всех остальных маркеров.

[
 {
   "action": "deduplicate",
   "rules": "file,warnclass,line"
 }
]

В данном примере у всех маркеров UNUSED_FIELD на строке 11 в файле AddInstruction.cs была трасса состоящая из трёх ролей: detected, info, Current function name. Роль detected полностью совпадала во всех маркерах, она была включена один раз, а все остальные роли добавились в объединенный маркер. Оставшиеся дублирующие маркеры были удалены.

Комплексный пример

В данном примере пропускаются все маркеры, у которых инструмент равен CSA, а маркеры, которые имеют детекторы 'BAD_COPY_PASTE', 'DEREF_AFTER_NULL', 'UNUSED_VALUE' или имеют в описании подстроку unsafe в любом регистре, меняют детектор и описание.

[
 {
   "action": "skip",
   "rules": "tool == 'CSA'"
 },
 {
   "action": "change",
   "rules": "warnclass in ['BAD_COPY_PASTE', 'DEREF_AFTER_NULL', 'UNUSED_VALUE'] or icontains(msg, 'unsafe')",
   "change": {
     "warnclass": "HIGH_PRIORITY",
     "msg": "Высокоприоритетное предупреждение"
   }
 }
]

При сравнении с исходным снимком можно заметить, что 91 предупреждение, у которых инструмент был CSA, удалены из измененного снимка.

Также были изменены маркеры, в соответствии с правилами.

Изменение приоритета для определенных классов

Изменение детекторов:

[ 
 {
   "action": "change",
   "rules": "warnclass in ['UNREACHABLE_CODE.TERMINATION', 'UNREACHABLE_CODE.RET', 'UNREACHABLE_CODE.ENUM']",
   "change": {
     "warnclass": "UNREACHABLE_CODE"
   }
 }
]

Обработка сгенерированных файлов

Пропускаем все маркеры в сгенерированных файлах:

[ 
 {
   "action": "skip",
   "rules": "file contains 'generated' or hasPrefix(file, 'vendor/')"
 }
]

Дедупликация с последующей фильтрацией

Сначала объединяем дубликаты, потом удаляем ненужные:

[
 {
   "action": "deduplicate",
   "rules": "file,line,warnclass,function"
 },
 {
   "action": "skip",
   "rules": "icontains(file, 'third_party') or icontains(file, 'external')"
 }
]

Работа с регулярными выражениями

В данном примере будут пропущены маркеры, путь к файлу которых НЕ соответствует регулярному выражению. В результате в снимке останутся только маркеры из файлов с расширениями .c, .cpp, .h или .hpp, находящихся в директории /.build/builtins. В данном случае мы дважды экранируем: сначала слэш, а потом точку.

[
 {
   "action": "skip",
   "rules": "nregex(file, \"^/\\\\.build/builtins/.*\\\\.(c|cpp|h|hpp)$\")"
 }
]

В результате у нас остаются только подходящие маркеры:

Дополнительные опции

Сохранение отредактированного снимка

При импорте снимка можно сохранить результат применения правил:

 svacer server import --edit-markers rules.json --save-edited-snapshot result.snap ...

Обязательно должно быть расширение .snap для сохранения.

Важные замечания

  1. Порядок правил — правила применяются последовательно в порядке их описания в файле
  2. Валидация — при загрузке правил проверяется корректность JSON и соответствие полей
  3. Формат файла — файл правил должен иметь расширение .json
  4. Логирование — результат применения правил выводится в лог (количество обработанных и удаленных маркеров)
  5. Поле line в change — должно быть строкой с неотрицательным числом
  6. Поле warnclass в change — может принимать только русские и английские буквы, цифры, а также специальные символы, которые находятся на цифровой панели клавиатуры (и печатаются через Shift)