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.
-fsanitize=fuzzer support or a standalone libFuzzer library.--no-huge and
--in-memory.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.
The fuzz harnesses #include the production .c files directly so that all static
functions are visible without any wrapper hooks in the library source. The linker flag
--allow-multiple-definition resolves the resulting duplicate non-static symbols
between the harness and libmtl.
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 through
rx_ancillary_session_handle_pkt, using a lightweight DPDK/EAL bootstrap.st40_ancillary_helpers_fuzz – targets the pure helper functions in
st_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.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
The acceptance_tests suite drives every fuzz target with long-running libFuzzer passes and
streams the combined libFuzzer/MTL output into
tests/acceptance/logs/latest/pytest.log. Execute:
pytest tests/acceptance/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.
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.