Skip to content

Commit 04301b4

Browse files
authored
Address panics in parseBinaryFloat, add fuzzer (#41)
* address panics, add fuzzer * check for nil error and nil packet * gate fuzz testing behind build tags requiring Go 1.18 or higher
1 parent 3c992f0 commit 04301b4

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

fuzz_test.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//go:build go1.18
2+
// +build go1.18
3+
4+
// Fuzzing test(s) are gated behind build tags in order to avoid generating errors
5+
// when running on versions of Go that do not support fuzzing. This was added in
6+
// Go 1.18.
7+
8+
package ber
9+
10+
import (
11+
"os"
12+
"testing"
13+
"time"
14+
)
15+
16+
func FuzzDecodePacket(f *testing.F) {
17+
// Seed the fuzz corpus with the test cases defined in suite_test.go
18+
for _, tc := range testCases {
19+
file := tc.File
20+
21+
dataIn, err := os.ReadFile(file)
22+
if err != nil {
23+
f.Fatalf("failed to load file %s into fuzz corpus: %v", file, err)
24+
continue
25+
}
26+
f.Add(dataIn)
27+
}
28+
29+
// Seed the fuzz corpus with data known to cause panics in the past
30+
f.Add([]byte{0x09, 0x02, 0x85, 0x30})
31+
f.Add([]byte{0x09, 0x01, 0xcf})
32+
33+
// Set a limit on the length decoded in readPacket() since the call to
34+
// make([]byte, length) can allocate up to MaxPacketLengthBytes which is
35+
// currently 2 GB. This can cause memory related crashes when fuzzing in
36+
// parallel or on memory constrained devices.
37+
MaxPacketLengthBytes = 65536
38+
f.Fuzz(func(t *testing.T, data []byte) {
39+
stime := time.Now()
40+
p, err := DecodePacketErr(data)
41+
42+
if e := time.Since(stime); e > (time.Millisecond * 500) {
43+
t.Fatalf("DecodePacketErr took too long: %s", e)
44+
}
45+
46+
if p == nil && err == nil {
47+
t.Fatalf("DecodePacketErr returned a nil packet and no error")
48+
}
49+
})
50+
}

real.go

+6
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,18 @@ func parseBinaryFloat(v []byte) (float64, error) {
8989
case 0x02:
9090
expLen = 3
9191
case 0x03:
92+
if len(v) < 2 {
93+
return 0.0, errors.New("invalid data")
94+
}
9295
expLen = int(v[0])
9396
if expLen > 8 {
9497
return 0.0, errors.New("too big value of exponent")
9598
}
9699
v = v[1:]
97100
}
101+
if expLen > len(v) {
102+
return 0.0, errors.New("too big value of exponent")
103+
}
98104
buf, v = v[:expLen], v[expLen:]
99105
exponent, err := ParseInt64(buf)
100106
if err != nil {

0 commit comments

Comments
 (0)