Repository navigation
Expand file tree
/
Copy pathfuzz_test.go
More file actions
106 lines (85 loc) · 2.73 KB
/
Copy pathfuzz_test.go
File metadata and controls
106 lines (85 loc) · 2.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package http2
import (
"bufio"
"bytes"
"testing"
)
// The parsers below all take bytes straight off the wire from an unauthenticated
// peer, which makes them the parts worth fuzzing. Each target asserts the same
// contract: whatever the input, the parser either returns an error or a usable
// result, and never panics or runs away.
func FuzzHuffmanDecode(f *testing.F) {
f.Add(encodedBytes)
f.Add(littleEncodedBytes)
f.Add([]byte{})
f.Add([]byte{0xff, 0xff, 0xff, 0xff})
f.Fuzz(func(t *testing.T, src []byte) {
dst, err := HuffmanDecode(nil, src)
if err != nil {
return
}
// A successful decode has to round trip: re-encoding what came out
// must decode back to the same bytes.
again, err := HuffmanDecode(nil, HuffmanEncode(nil, dst))
if err != nil {
t.Fatalf("re-decoding a successful decode failed: %v", err)
}
if !bytes.Equal(dst, again) {
t.Fatalf("round trip changed the value: %q != %q", dst, again)
}
})
}
func FuzzHPACKNext(f *testing.F) {
// A handful of well-formed blocks: indexed field, literal with incremental
// indexing, and a literal with a huffman-coded value.
f.Add([]byte{0x82})
f.Add([]byte{0x40, 0x01, 'a', 0x01, 'b'})
f.Add([]byte{0x00, 0x01, 'a', 0x81, 0x3f})
f.Add([]byte{0xff, 0xff, 0xff, 0xff, 0xff})
f.Add([]byte{})
f.Fuzz(func(t *testing.T, block []byte) {
hp := &HPACK{}
hp.Reset()
hf := &HeaderField{}
b := block
// Bound the loop by the input: every successful field must consume at
// least one byte, so a parser that returns nil error without advancing
// is a bug worth catching rather than an infinite loop in the fuzzer.
for i := 0; len(b) > 0; i++ {
if i > len(block) {
t.Fatalf("decoded %d fields from %d bytes without consuming input", i, len(block))
}
before := len(b)
var err error
b, err = hp.Next(hf, b)
if err != nil {
return
}
if len(b) >= before {
t.Fatalf("field %d consumed no input (%d -> %d bytes)", i, before, len(b))
}
}
})
}
func FuzzFrameHeaderRead(f *testing.F) {
f.Add([]byte{0, 0, 0, byte(FrameSettings), 0, 0, 0, 0, 0})
f.Add([]byte{0, 0, 8, byte(FramePing), 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8})
f.Add([]byte{0, 0, 4, byte(FrameWindowUpdate), 0, 0, 0, 0, 1, 0, 0, 0, 1})
f.Add([]byte{})
f.Fuzz(func(t *testing.T, raw []byte) {
br := bufio.NewReader(bytes.NewReader(raw))
fr, err := ReadFrameFrom(br)
if err != nil {
return
}
defer ReleaseFrameHeader(fr)
// A frame that parsed must report a length no larger than the input it
// came from, otherwise it is claiming payload it never read.
if fr.Len() > len(raw) {
t.Fatalf("frame reports %d payload bytes from a %d byte input", fr.Len(), len(raw))
}
if fr.Body() == nil {
t.Fatal("frame parsed without a body")
}
})
}