ST40/ST30/ST20/ST22 RX Fuzzing#
This repository now provides libFuzzer harnesses that exercise the runtime ST40 RX ancillary packet path, the ancillary helper utilities, the ST30 RX audio frame path, and the ST20/ST22 RX video frame pipelines. The harnesses are built only when the dedicated Meson option is enabled because they pull in DPDK and need an EAL environment.
Build Requirements#
Clang/LLVM with
-fsanitize=fuzzersupport or a standalonelibFuzzerlibrary.DPDK must already be available, as required by the main library build.
Linux is recommended; the harnesses rely on EAL flags such as
--no-hugeand--in-memory.
Enabling The Harnesses#
You can turn the fuzzers on either directly through Meson or via the top-level
build.sh helper:
meson setup build -Denable_fuzzing=true
./build.sh release enable_fuzzing
# or export MTL_BUILD_ENABLE_FUZZING=true before invoking build.sh
Add -Denable_asan=true (or MTL_BUILD_ENABLE_ASAN=true) if you also want
AddressSanitizer instrumentation. Existing build directories can be reconfigured with
meson configure build -Denable_fuzzing=true.
Meson injects the MTL_ENABLE_FUZZING_ST40, MTL_ENABLE_FUZZING_ST30,
MTL_ENABLE_FUZZING_ST20, and MTL_ENABLE_FUZZING_ST22 defines so the RX
implementation exposes the minimal helper hooks required by the fuzzers.
Building#
After configuration simply run the standard build:
ninja -C build
The following fuzz targets will be produced inside build/tests/fuzz/:
st40_rx_rtp_fuzz– feeds arbitrary RTP payloads throughrx_ancillary_session_handle_pkt, using a lightweight DPDK/EAL bootstrap.st40_ancillary_helpers_fuzz– targets the pure helper functions inst_ancillary.c(st40_set_udw,st40_get_udw, parity helpers, checksum, etc.).st30_rx_frame_fuzz– injects fuzzed RFC3550 audio RTP packets into the frame-level ST30 RX path, allocating a tiny in-memory framebuffer to exercise the sequencing and framing logic.st20_rx_frame_fuzz– drives the frame-level ST20 video RX path, including slot management, RTP parsing, bitmap tracking, and framebuffer assembly for RFC4175-formatted video payloads.st22_rx_frame_fuzz– targets the ST22 codestream RX path, validating packetized codestream parsing, JPVS/COLR box handling, and codestream reassembly logic.
Running#
Each target is a standalone libFuzzer executable. A minimal invocation looks like:
./build/tests/fuzz/st40_rx_rtp_fuzz -runs=1000 corpus_dir
The harness configures EAL internally (--no-huge --in-memory --no-shconf -c1 -n1),
so no additional environment setup is required beyond access to /dev/hugepages not
being mandatory.
A similar invocation drives the ST30 frame harness:
./build/tests/fuzz/st30_rx_frame_fuzz -max_total_time=60 corpus_audio
And the new ST20/ST22 video harnesses can be exercised with:
./build/tests/fuzz/st20_rx_frame_fuzz -max_total_time=60 corpus_video
./build/tests/fuzz/st22_rx_frame_fuzz -max_total_time=60 corpus_codestream
For long fuzzing sessions point the binary at a writable corpus directory. The helper fuzzer works the same way:
./build/tests/fuzz/st40_ancillary_helpers_fuzz -max_total_time=60 corpus_helpers
Pytest integration#
The validation suite drives every fuzz target with long-running libFuzzer passes and
streams the combined libFuzzer/MTL output into
tests/validation/logs/latest/pytest.log. Execute:
pytest tests/validation/fuzzing/test_fuzzing.py -k fuzz
Each test carries @pytest.mark.nightly and runs -runs=500000 iterations by default
(override via MTL_FUZZ_TEST_RUNS). That keeps quick developer test shards short while
allowing the nightly job to exercise a deeper corpus.
Logging during fuzzing#
All harnesses automatically raise the MTL and DPDK log level to DEBUG and install a
custom printer that forwards every log line to stderr. When invoked through pytest (or
manually), you will see MTL:-prefixed lines for interesting events—payload-type / SSRC
mismatches, redundant packets, enqueue failures, etc.—inside the test logs without any
extra configuration.
Notes#
The RX harness drains the session ring immediately after notifying the callback so mbufs are always released, which keeps memory usage stable even under ASan.
Inputs must be at least the size of an RFC8331 ancillary header (62 bytes) to ensure the handler never reads beyond the provided mbuf.
All harnesses cap their input size to fit inside a standard DPDK mbuf (2 KiB) to avoid oversized allocations during fuzzing.
The ST30 harness requires inputs large enough to contain an RFC3550 audio header (12 bytes). Packets larger than 2 KiB are truncated so they still fit within a single mbuf.
The ST20 harness expects RFC4175-style video payloads (12-byte RTP header plus video-specific extensions). Packets shorter than the combined header size are ignored.
The ST22 harness operates on RFC9134 codestream packets. Inputs must include at least the base JP2K header; larger payloads exercise the box parsing and codestream completion/marker logic.