- The paper introduces driver-induced subgraphs that project dynamic fuzzing coverage onto whole-program call graphs, enabling structural analysis across 854 drivers and 27 OSS-Fuzz projects.
- The paper finds that multi-driver fuzzing improves coverage over the best single driver by an average of 27.9% in call-graph nodes and 73.5% in CFG edges, while exposing 13 mostly unique bugs.
- The paper identifies three residual-coverage regimes—backbone-dominated gaps, diffuse partial exploration, and localized pockets—supporting adaptive scheduling, redundancy reduction, and targeted driver-input design.
Motivation and problem statement
Configuration-rich software exposes multiple execution modes through command-line options, subcommands, and input formats, so the behavior reachable by a fuzzer depends jointly on mutated inputs and on the invocation mode. Prior work has treated such modes as levers for improving fuzzing effectiveness—option-aware fuzzers, CLI combinatorial exploration, environment fuzzing—but not as objects of structural analysis. As a result, it remains unclear whether different execution modes explore complementary or redundant regions of the same program, how their induced execution footprints are organized, and why substantial parts of a program remain under-explored even when many drivers are combined. This paper addresses that gap with an empirical study rather than a new fuzzing algorithm, framing multi-driver fuzzing as a structural exploration problem.
Structural abstraction and methodology
The central device is a hybrid structural representation: for each executable, a whole-program, context-insensitive function-level call graph (built with SVF's flow-sensitive pointer analysis) serves as a shared backbone, and driver-specific dynamic coverage collected during fuzzing is projected onto that backbone to yield driver-induced subgraphs. A driver is a concrete execution configuration d=⟨id,opts,fmt,Sd​⟩ comprising an identifier, command-line options, expected input format, and seed corpus; drivers are manually specified to ensure each corresponds to a semantically meaningful mode rather than superficial option variation.
The study proceeds in four phases: benchmark selection from OSS-Fuzz C/C++ projects organized into ten domains; backbone construction and driver specification; multi-driver fuzzing with per-driver attribution of coverage and crashes; and offline graph-based analysis. The benchmark suite comprises 27 projects, 43 executables, roughly 259K functions, and 854 driver configurations, spanning media processing (ffmpeg, libtiff), document parsing (xpdf, libxml2, jq), toolchains (binutils, cppcheck), language runtimes (cpython, quickjs, lua), archives (libarchive, upx, xz), and storage systems (hdf5, netcdf, sqlite3).
Tool support consists of an execution-side extension of Honggfuzz (~4 KLoC C/C++) implementing round-robin driver scheduling with equal time slices, shared-memory profile synchronization at switch boundaries, and driver-indexed bitmaps over call-graph nodes and edges; and an analysis-side Python component (~2.8 KLoC) computing the metrics. Validation on one large executable per domain shows coverage differences versus pure single-driver Honggfuzz within −1.9% to +1.2% across eight targets, average switch costs below 1 s, and peak-memory increases of 10–36% relative (largely attributable to retained corpora). The analysis is strictly observational—no feedback enters the fuzzing loop.
Five metric families are computed on the subgraphs: subgraph size (∣Vd​∣, ∣Ed​∣); cohesion via the largest weakly connected component (LCC) ratio and fragmentation via the number of weakly connected components (#WCC); directed modularity Q via Louvain-style community detection; pairwise redundancy via intersection-over-union over covered functions (IoUV​) and call edges (IoUE​); and region-level residual coverage after partitioning the backbone into communities.
RQ1: Multi-driver effectiveness
Under identical total budgets (24-hour runs, five repetitions per configuration), union multi-driver fuzzing improves over the best single-driver baseline by an average of 27.9% in covered call-graph nodes and 73.5% in CFG edges. Gains are frequently asymmetric in favor of edge coverage—for example, file (+31.3% nodes, +203.9% edges), quickjs/qjs (+37.0%, +370.7%), xz (+7.4%, +220.7%), and binutils/objdump (+46.6%, +101.9%)—indicating that driver diversity deepens intra-procedural exploration within already reached regions as well as broadening reach. Extreme cases include lua (+294.0%, +780.5%) and netcdf/ncgen (+275.8%, +190.0%).
The improvement is nonetheless uneven. Marginal gains appear where drivers are structurally redundant (cppcheck +1.0%, qjsc +0.3%, git +2.8%, tiffinfo +1.1%), near-parity occurs for sqlite3 and upx, and two executables regress slightly under multi-driver execution: xpdf/pdfdetach (−1.6%, −3.4%) and libarchive/bsdtar (−1.8%, −32.6%). These regressions arise because fixed-budget division reduces time available to a dominant single driver when overlap is high—an important caveat against assuming multi-driver execution is uniformly beneficial.
Bug discovery reinforces the coverage results: 13 unique bugs and abnormal behaviors were exposed across ncdump, h5repack, readelf, and lua, of which only three were also found by the best single driver. The findings cluster in semantically specialized modes (formatting/extraction flags in ncdump, ordering/transformation modes in h5repack, debug-display modes in readelf, the -E mode hang in lua), showing that aggregate coverage does not grant access to the specific semantic slices in which failures occur.
RQ2: Driver heterogeneity under equal budgets
Normalizing each driver's call-graph node coverage share against the overlap-aware union reveals systematic imbalance. Coefficients of variation range from 0 (sqlite3, perfectly uniform across 48 drivers) to above 2.7 (qjsc). Many executables exhibit pronounced right skew: pdftops spans minimum 0.0067 to maximum 0.9772 across 66 drivers, ffmpeg from 0.0632 to 0.9958, and dominant-driver patterns appear in qjsc and bsdtar where medians sit near zero while maxima approach one. Near-uniform contribution is rare, confined largely to sqlite3 and upx whose drivers traverse a common execution backbone. Equal time allocation therefore does not produce equal structural contribution, which explains both why round-robin multi-driver fuzzing can be effective in some executables and wasteful in others.
RQ3 and RQ4: Subgraph organization and overlap
Driver-induced subgraphs vary substantially in internal organization. LCC ratios span roughly 0.15–1.0, with wide within-executable dispersion in programs such as snort and ffmpeg, while sqlite3 and upx remain tightly cohesive across all drivers. #WCC ranges from 1 to over 20, indicating that some drivers activate multiple disjoint subsystems while others remain confined to a single connected region. Directed modularity ranges from near 0 to above 0.6, again with broad dispersion in ffmpeg, qjsc, and pdftops. Configuration modes thus differ not only in how much structure they reach but in how that structure is connected and clustered.
Pairwise IoU distributions span nearly the full [0,1] range. Executables such as img_stat, addr2line, tiff2bw, and ncdump show median node-level IoU near zero (highly complementary drivers), whereas snort2lua, tiffinfo, h5dump, and upx show median IoUV​ above 0.8 (highly redundant). Most programs occupy an intermediate regime with mixed structure: highly overlapping and orthogonal driver pairs coexist, and pdftops and xmllint span almost the full range. Edge-level overlap follows similar trends but is often more concentrated near 1, meaning drivers may activate overlapping function sets while inducing different interprocedural connectivity. These patterns provide a graph-level explanation for the RQ1 gains and RQ2 imbalances: high-redundancy executables show little multi-driver benefit, while mixed-overlap executables show large gains.
RQ5: Residual under-exploration regimes
After round-robin multi-driver fuzzing, residual region coverage does not form a homogeneous tail but falls into three recurring regimes:
- Backbone-dominated gaps: ffmpeg, ffprobe, git, istat, tsk_recover, cppcheck, ncgen, nccopy, and checkconf retain median region coverage of zero, with large fractions of regions entirely uncovered (e.g., ffmpeg: 83.84% of its 198 regions at RC = 0).
- Partial exploration with substantial residual tails: objdump, readelf, addr2line, xmllint, python, xz, bsdtar, and the xpdf tools achieve nontrivial exploration yet leave diffuse weak-coverage tails.
- Broad exploration with localized pockets: lua, jq, snort2lua, bsdunzip, img_stat, file, and upx leave only narrow, well-connected residual pockets.
Case studies attribute these regimes to different causes. In ffmpeg, uncovered regions span diverse codec-specific handlers (amrwb, AAC, Opus, H.264, ATRAC3 decoders) behind strict format- and state-dependent semantic preconditions; even the largest backbone region reaches only RC = 0.05, indicating a semantic access barrier rather than missing entry points. In xmllint, main document processing is well explored but XPath evaluation, shell/debug inspection, schema-facet validation, Relax NG validation, and canonicalization remain uncovered or weakly explored, reflecting unmet combinations of options, documents, and internal state. In lua, residual pockets concentrate in pattern matching, binary chunk loading, GC traversal of userdata, and VM edge cases—specialized corners of an otherwise thoroughly explored interpreter. Notably, residual profiles diverge even within the same benchmark family (snort vs. snort2lua, bsdtar vs. bsdunzip), suggesting residual difficulty is executable-specific rather than family-wide.
Practical implications
The findings support several design principles for driver-aware fuzzing: measure each driver's marginal structural contribution rather than treating driver sets as flat collections; explicitly account for overlap by grouping or pruning redundant drivers; prioritize drivers that continue extending exploration into cold regions; adapt effort allocation to the residual regime (broad reallocation for backbone-dominated gaps versus targeted triggering for localized pockets); incorporate finer-grained feedback than aggregate coverage; and improve driver–input combinations for persistent residual regions rather than assuming a purely driver-side or seed-side cause.
Limitations and open questions
The authors identify several constraints on interpretation. All structural measurements are projected onto a context-insensitive static call graph that over-approximates feasible caller–callee relationships, so connectivity, modularity, overlap, and residual-region statistics could differ under context-sensitive models. Fuzzing stochasticity means the reported subgraphs characterize behavior under the studied configuration rather than invariant program properties. The RQ5 region decomposition depends on community-detection choices, and the regime categories are abstractions rather than unique decompositions. Drivers cover only primary command-line options—not exhaustive parameter combinations, environment variables, or configuration files—and driver generation itself remains an open research problem. Finally, the causal interpretations (e.g., overlap reinforcing hot regions, complementarity driving gains) rest on converging observational evidence and case studies, not controlled manipulation. The study also leaves open whether persistent residual gaps stem primarily from driver choice, input quality, or their interaction, and how adaptive (non-round-robin) scheduling would alter the observed regimes.
Conclusion
This paper provides a systematic graph-level characterization of how multi-driver fuzzing explores software structure across 27 OSS-Fuzz-derived projects and 854 driver configurations. Its principal results are that multi-driver fuzzing outperforms the best single driver under equal budgets (average +27.9% call-graph nodes, +73.5% CFG edges, plus 13 mostly single-driver-inaccessible defects), that driver contributions and induced subgraphs are systematically heterogeneous in size, cohesion, modularity, and overlap, and that residual under-exploration follows three recurring regimes rather than a uniform tail. The evidence supports treating multi-driver fuzzing as a structural exploration problem in which driver value derives from marginal, non-redundant contribution to the shared call-graph backbone.