From 97f43e33b46de5d03bfdefee63d4ce6c1fb1edf8 Mon Sep 17 00:00:00 2001 From: Alexey Sharov Date: Tue, 11 Aug 2026 13:17:49 +0700 Subject: [PATCH 1/3] db/seg/patricia: make FuzzLongestMatch input deterministic Map iteration order decided which keys got concatenated into the match data, so the same fuzz input produced a different test string on every run. LibAFL reports edges_stability 59% for this target as a result, and a crash saved to the corpus would not replay. --- db/seg/patricia/patricia_fuzz_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/db/seg/patricia/patricia_fuzz_test.go b/db/seg/patricia/patricia_fuzz_test.go index 6e66ab72e46..8337e12b6e0 100644 --- a/db/seg/patricia/patricia_fuzz_test.go +++ b/db/seg/patricia/patricia_fuzz_test.go @@ -61,6 +61,9 @@ func FuzzLongestMatch(f *testing.F) { if len(keys) == 0 { return } + // keys indexes the generated match data below, so map iteration order + // would make the same fuzz input build a different test string each run. + slices.Sort(keys) var data []byte for i := 0; i < 4*(len(test)/4); i += 4 { keyIdx := int(binary.BigEndian.Uint32(test[i : i+4])) From 01ec175832dc3cb65d78986d510dbfc95dc464f2 Mon Sep 17 00:00:00 2001 From: Alexey Sharov Date: Tue, 11 Aug 2026 14:49:37 +0700 Subject: [PATCH 2/3] db/seg: fix uint8 overflow in FuzzCompress chunk size pos[i]*10 is uint8 arithmetic and wraps for pos[i] >= 26, so the conversion to int happened after the value had already been truncated. The harness only ever produced wrapped chunk sizes. --- db/seg/compress_fuzz_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/seg/compress_fuzz_test.go b/db/seg/compress_fuzz_test.go index f4f2192085f..5e17d47e8bb 100644 --- a/db/seg/compress_fuzz_test.go +++ b/db/seg/compress_fuzz_test.go @@ -40,7 +40,7 @@ func FuzzCompress(f *testing.F) { if pos[i] == 0 { continue } - next := min(j+int(pos[i]*10), len(x)-1) + next := min(j+int(pos[i])*10, len(x)-1) bbb := x[j:next] a = append(a, bbb) j = next From ac53a22a7e3d3af7fd05e356781bfeb41fa91a8b Mon Sep 17 00:00:00 2001 From: Alexey Sharov Date: Tue, 11 Aug 2026 18:40:46 +0700 Subject: [PATCH 3/3] db/seg: fix uint8 overflow in FuzzDecompressMatch chunk size Same defect as FuzzCompress: pos[i]*10 is uint8 arithmetic and wraps for pos[i] >= 26, so the conversion to int happened after truncation. --- db/seg/decompress_fuzz_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/seg/decompress_fuzz_test.go b/db/seg/decompress_fuzz_test.go index 21871c3b91b..067998e820b 100644 --- a/db/seg/decompress_fuzz_test.go +++ b/db/seg/decompress_fuzz_test.go @@ -41,7 +41,7 @@ func FuzzDecompressMatch(f *testing.F) { if pos[i] == 0 { continue } - next := min(j+int(pos[i]*10), len(x)-1) + next := min(j+int(pos[i])*10, len(x)-1) bbb := x[j:next] a = append(a, bbb) j = next