--------------------------------------------------------------------------- Property: all fuzz harnesses from fuzz.go never panic on arbitrary bytes --------------------------------------------------------------------------- This is the OSS-Fuzz invariant — the harness must accept any byte sequence
(t *testing.T)
| 936 | // reqproof:proptest FuzzParseString, FuzzEachKey, FuzzDelete, FuzzSet, FuzzObjectEach, FuzzParseFloat, FuzzParseInt, FuzzParseBool, FuzzTokenStart, FuzzGetString, FuzzGetFloat, FuzzGetInt, FuzzGetBoolean, FuzzGetUnsafeString |
| 937 | // Verifies: SYS-REQ-035 [property] |
| 938 | func TestPropertyFuzzHarnessesNoCrash(t *testing.T) { |
| 939 | r := newRNG(jsonSeed + 14) |
| 940 | const iterations = 5000 |
| 941 | // Each harness is a function that takes []byte and returns int (0/1). |
| 942 | // We require: (1) no panic, (2) deterministic return for identical input. |
| 943 | harnesses := []struct { |
| 944 | name string |
| 945 | fn func([]byte) int |
| 946 | }{ |
| 947 | {"FuzzParseString", FuzzParseString}, |
| 948 | {"FuzzEachKey", FuzzEachKey}, |
| 949 | {"FuzzDelete", FuzzDelete}, |
| 950 | {"FuzzSet", FuzzSet}, |
| 951 | {"FuzzObjectEach", FuzzObjectEach}, |
| 952 | {"FuzzParseFloat", FuzzParseFloat}, |
| 953 | {"FuzzParseInt", FuzzParseInt}, |
| 954 | {"FuzzParseBool", FuzzParseBool}, |
| 955 | {"FuzzTokenStart", FuzzTokenStart}, |
| 956 | {"FuzzGetString", FuzzGetString}, |
| 957 | {"FuzzGetFloat", FuzzGetFloat}, |
| 958 | {"FuzzGetInt", FuzzGetInt}, |
| 959 | {"FuzzGetBoolean", FuzzGetBoolean}, |
| 960 | {"FuzzGetUnsafeString", FuzzGetUnsafeString}, |
| 961 | } |
| 962 | // Mix of valid JSON and arbitrary bytes. |
| 963 | inputs := make([][]byte, 0, iterations) |
| 964 | for i := 0; i < iterations/2; i++ { |
| 965 | inputs = append(inputs, randomJSONBytes(r, 2)) |
| 966 | } |
| 967 | for i := 0; i < iterations/2; i++ { |
| 968 | inputs = append(inputs, randomBytes(r, 128)) |
| 969 | } |
| 970 | // Curated edge cases. |
| 971 | inputs = append(inputs, nil, []byte{}, []byte("\x00"), []byte("\xff"), |
| 972 | []byte("{"), []byte("}"), []byte("["), []byte("]"), |
| 973 | []byte(`{"test":`), []byte(`{{{`), |
| 974 | bytes.Repeat([]byte{0x80}, 256), |
| 975 | ) |
| 976 | |
| 977 | for _, h := range harnesses { |
| 978 | for i, raw := range inputs { |
| 979 | if !recoverNoPanic(func() { _ = h.fn(raw) }) { |
| 980 | t.Fatalf("%s panicked on input #%d %q", h.name, i, raw) |
| 981 | } |
| 982 | a := safeCall(h.fn, raw) |
| 983 | b := safeCall(h.fn, raw) |
| 984 | if a != b { |
| 985 | t.Fatalf("%s non-deterministic on input #%d %q: %d vs %d", h.name, i, raw, a, b) |
| 986 | } |
| 987 | } |
| 988 | } |
| 989 | } |
| 990 | |
| 991 | // safeCall invokes a fuzz harness, recovering from any panic and returning |
| 992 | // the harness result or -1 on panic. |
nothing calls this directly
no test coverage detected