1. Today’s topic

We examine:

text
Fuzzing:
  automatically generates and mutates input data,
  trying to cause a crash, hang, or memory error.
Property-based testing:
  checks general properties of an algorithm
  across many automatically generated inputs.

The central idea: a unit test checks a scenario you imagined. A fuzzer tries to find a scenario you did not think of.

2. Why this matters

EC25

UART may deliver a response in fragments, with a URC in the middle, empty lines, zero bytes, damaged CR/LF, or an excessively long line. A fuzzer automatically explores thousands of combinations.

Configuration

A corrupt blob may have correct magic but wrong size; an old version; a string without \0; generation overflow; or a valid CRC for logically invalid parameters.

CAN/RS-485/Modbus

Fuzzing is useful for invalid DLC, unexpected function code, truncated frames, incorrect CRC, and a broadcast address.

Phase detector

Property-based tests check:

text
- event timestamp does not go backwards;
- sequence increases only when an event occurs;
- a short pulse shorter than debounce does not change stable phase;
- any mask always yields a valid enum.

3. Theory

Coverage-guided fuzzing

The fuzzer:

text
1. Runs code against the initial corpus.
2. Mutates bytes.
3. Observes which code branches executed.
4. Saves an input if it opens a new path.
5. Continues mutating interesting inputs.

Sanitizers

Use:

text
AddressSanitizer:
  heap/stack/global buffer violations, use-after-free.
UndefinedBehaviorSanitizer:
  signed overflow, invalid shifts, misaligned access.

Flags:

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

A good fuzz harness

text
- small;
- fast;
- deterministic;
- does not use a network;
- does not start threads;
- does not sleep;
- completely resets state before every iteration.

Fragmentation invariance for the AT parser

Property:

text
feed(all_payload_once) == feed(same_payload_fragmented)

Compare the canonical result, not internal indices: the sequence of events AT_EVENT_OK, QMTOPEN, QMTSTAT, ERROR, and LINE_TOO_LONG.

4. Common mistakes

  • Starting with pure random noise and no valid seeds.
  • The harness retains state between iterations.
  • Using real time.
  • Not bounding input size.
  • Checking only “did not crash”, without properties.
  • Ignoring timeouts as “uninteresting”.
  • Not converting a crash into a regression test.

5. Practical assignment

Create a fuzz target for the AT parser. Plan:

text
1. Extract the parser into a host-compatible component.
2. Remove FreeRTOS/UART dependencies.
3. Implement a canonical event collector.
4. Add two feed modes: whole and fragmented.
5. Build with Clang and ASan/UBSan.
6. Create a seed corpus.
7. Run 50 000 iterations.

Example invocation:

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

6. What to try next

  • Fuzz config blob loading/migration.
  • Fuzz a Modbus RTU decoder.
  • Fuzz CAN codec round-trip.
  • Fuzz the fault manager as a stateful sequence: timeout → late OK → reconnect → URC.

Exercise

Define a property test for an AT response split at arbitrary byte boundaries. What output should be compared, and what state must be reset?

Self-check criteria: The assertion must describe observable parsing results rather than buffer indices; include both valid seeds and malformed bounded inputs.

Show the supplied answer

Feed the same payload whole and fragmented into clean parser instances. Compare the canonical event sequence and event data; reset parser state and the event collector before each iteration.

Exercise

A fuzzer reports a timeout without a crash. Explain how to preserve and investigate the input, then convert the finding into a deterministic regression test.

Self-check criteria: Do not dismiss the timeout; ensure each run begins with clean state and that the regression checks the cause, not just the saved bytes.

Show the supplied answer

Keep the reproducing input and exact harness/build settings. Reproduce with bounded execution, inspect parser progress or state transitions, and add a test that asserts termination or the violated progress property without relying on real sleeps.