MCPcopy Create free account
hub / github.com/buger/jsonparser / FuzzJSONStructureAware

Function FuzzJSONStructureAware

json_fuzz_test.go:1509–1568  ·  view source on GitHub ↗

FuzzJSONStructureAware is the structure-aware fuzzer. It combines: - Grammar-based JSON generation (always emits valid structures). - JSON-aware mutation operators (break structures at known-dangerous boundaries: value boundaries, mid-key, mid-structure, mid-escape). - Adversarial key-path generatio

(f *testing.F)

Source from the content-addressed store, hash-verified

1507// GetBoolean, GetUnsafeString, ArrayEach, ObjectEach, EachKey,
1508// ParseInt, ParseFloat
1509func FuzzJSONStructureAware(f *testing.F) {
1510 // Seed with known-dangerous corpora (the actual bugs we've found).
1511 for _, s := range structureAwareSeeds {
1512 f.Add(s.data, s.path)
1513 }
1514
1515 f.Fuzz(func(t *testing.T, data []byte, pathBytes []byte) {
1516 // Derive deterministic RNG from the fuzz inputs so generation and
1517 // mutation decisions are a pure function of the engine-supplied bytes.
1518 r := newRandFromSeed(data, pathBytes)
1519
1520 // --- Structure-aware generation layer ---
1521 // When the fuzz engine mutates data into non-JSON garbage (or ~30%
1522 // of the time regardless), regenerate valid JSON from the grammar.
1523 // This maintains structural coverage that blind byte mutation cannot
1524 // reach in reasonable time.
1525 work := data
1526 if !looksLikeJSON(data) || r.Intn(10) < 3 {
1527 depth := r.Intn(4) // mostly depth 0–3
1528 if r.Intn(10) == 0 {
1529 depth = 5 + r.Intn(3) // occasionally deep (stress recursion)
1530 }
1531 work = genJSON(r, depth)
1532 }
1533
1534 // --- Deep-nesting injection (closes Dimension 5 DoS blind spot) ---
1535 // The grammar generator's maxGenDepth=5 cannot produce pathological
1536 // nesting. Occasionally replace work with deeply-nested arrays so the
1537 // parser's own stack-safety (not just encoding/json's) gets fuzzed.
1538 // Both closed ([[[...1...]]]) and unclosed ([[[...) shapes are tested;
1539 // the unclosed shape forces full descent before error recovery.
1540 //
1541 // Capped at 1000 levels in the fuzz body: deeper inputs make the
1542 // existing Get-family gates (6+ calls, each O(n)) dominate the
1543 // worker's per-exec budget. The non-fuzz TestDoSPerformance gate
1544 // covers 100k+ level nesting separately.
1545 if r.Intn(40) == 0 {
1546 depth := 50 * (1 << r.Intn(5)) // 50..800
1547 work = genDeepNesting(depth, r.Intn(2) == 0)
1548 }
1549
1550 // --- JSON-aware mutation layer ---
1551 // Apply 0–3 mutations at structural boundaries. Each operator
1552 // targets a specific bug class (truncation, duplication, corruption).
1553 for n := r.Intn(4); n > 0; n-- {
1554 work = applyMutation(r, work)
1555 }
1556
1557 // --- Adversarial key-path layer ---
1558 // Derive the path from pathBytes (split on '/'); occasionally inject
1559 // a hazard component (empty key, OOB index) or regenerate from grammar.
1560 path := splitPathComponents(pathBytes)
1561 if r.Intn(5) == 0 { // 20% chance
1562 path = injectPathHazard(r, path)
1563 }
1564
1565 // --- Gates ---
1566 runStructureAwareGates(t, work, path)

Callers

nothing calls this directly

Calls 8

newRandFromSeedFunction · 0.85
looksLikeJSONFunction · 0.85
genJSONFunction · 0.85
genDeepNestingFunction · 0.85
applyMutationFunction · 0.85
splitPathComponentsFunction · 0.85
injectPathHazardFunction · 0.85
runStructureAwareGatesFunction · 0.85

Tested by

no test coverage detected