1. Тема дня

Разбираем:

text
Fuzzing:
  автоматически генерирует и изменяет входные данные,
  пытаясь вызвать crash, зависание или ошибку памяти.
Property-based testing:
  проверяет общие свойства алгоритма
  на большом количестве автоматически созданных входов.

Главная мысль: unit-тест проверяет придуманный тобой сценарий. Fuzzer пытается найти сценарий, о котором ты не подумал.

2. Зачем это нужно

EC25

UART может передать ответ фрагментами, с URC посередине, пустыми строками, нулевыми байтами, повреждённым CR/LF или слишком длинной строкой. Fuzzer автоматически перебирает тысячи сочетаний.

Конфигурация

Повреждённый blob может иметь корректный magic, но неверный size; старую version; строку без \0; переполнение generation; правильный CRC для логически недопустимых параметров.

CAN/RS-485/Modbus

Fuzzing полезен для неверного DLC, неожиданных function code, обрезанного кадра, неправильного CRC, широковещательного адреса.

Phase detector

Property-based тесты проверяют:

text
- timestamp событий не идёт назад;
- sequence увеличивается только при событии;
- короткий импульс короче debounce не меняет stable phase;
- произвольная маска всегда даёт корректный enum.

3. Теория

Coverage-guided fuzzing

Fuzzer:

text
1. Запускает код на исходном corpus.
2. Изменяет байты.
3. Смотрит, какие ветви кода выполнены.
4. Сохраняет вход, если он открыл новый путь.
5. Продолжает изменять интересные входы.

Sanitizers

Используй:

text
AddressSanitizer:
  выход за heap/stack/global buffer, use-after-free.
UndefinedBehaviorSanitizer:
  signed overflow, некорректные сдвиги, misaligned access.

Флаги:

text
-O1 -g -fno-omit-frame-pointer -fsanitize=fuzzer,address,undefined

Хороший fuzz harness

text
- маленький;
- быстрый;
- детерминированный;
- не использует сеть;
- не запускает потоки;
- не делает sleep;
- полностью сбрасывает состояние перед каждой итерацией.

Fragmentation invariance для AT-парсера

Свойство:

text
feed(all_payload_once) == feed(same_payload_fragmented)

Сравнивать надо не внутренние индексы, а канонический результат: последовательность событий AT_EVENT_OK, QMTOPEN, QMTSTAT, ERROR, LINE_TOO_LONG.

4. Типичные ошибки

  • Начать с чистого случайного шума без valid seeds.
  • Harness сохраняет состояние между итерациями.
  • Использовать реальное время.
  • Не ограничить размер входа.
  • Проверять только “не упало”, без свойств.
  • Игнорировать timeout как “неинтересный”.
  • Не превращать crash в regression test.

5. Практическое задание

Сделай fuzz target для AT-парсера. План:

text
1. Вынести parser в host-compatible компонент.
2. Убрать FreeRTOS/UART зависимости.
3. Реализовать canonical event collector.
4. Добавить два режима feed: whole и fragmented.
5. Собрать через Clang с ASan/UBSan.
6. Создать seed corpus.
7. Запустить 50 000 итераций.

Пример запуска:

text
./build-host/fuzz_at_parser \
  fuzz/corpus/at \
  -runs=50000 \
  -max_len=2048 \
  -timeout=2

6. Что попробовать дальше

  • Fuzz config blob loader/migration.
  • Fuzz Modbus RTU decoder.
  • Fuzz CAN codec round-trip.
  • Fuzz fault manager как stateful sequence: timeout → late OK → reconnect → URC.

Задание

Определите property test для AT response, разделённого на произвольных границах байтов. Какой результат сравнивать и какое состояние сбрасывать?

Критерии самопроверки: Проверка должна описывать наблюдаемый результат parsing, а не buffer indices; включить valid seeds и malformed bounded inputs.

Показать ответ автора

Передать один payload целиком и fragmented в чистые экземпляры parser. Сравнить canonical event sequence и event data; перед каждой итерацией сбрасывать parser state и event collector.

Задание

Fuzzer сообщил timeout без crash. Объясните сохранение и расследование входа, затем преобразование результата в детерминированный regression test.

Критерии самопроверки: Не игнорировать timeout; каждый запуск начинается с clean state, regression проверяет причину, а не только сохранённые bytes.

Показать ответ автора

Сохранить воспроизводящий input и точные harness/build settings. Повторить с ограниченным execution, проверить parser progress или state transitions и добавить тест termination либо нарушенного progress property без real sleeps.