Skip to content

Commit

Permalink
Address panics in parseBinaryFloat, add fuzzer (#41)
Browse files Browse the repository at this point in the history
* address panics, add fuzzer

* check for nil error and nil packet

* gate fuzz testing behind build tags requiring Go 1.18 or higher
  • Loading branch information
TomSellers authored Sep 14, 2023
1 parent 3c992f0 commit 04301b4
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 0 deletions.
50 changes: 50 additions & 0 deletions fuzz_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//go:build go1.18
// +build go1.18

// Fuzzing test(s) are gated behind build tags in order to avoid generating errors
// when running on versions of Go that do not support fuzzing. This was added in
// Go 1.18.

package ber

import (
"os"
"testing"
"time"
)

func FuzzDecodePacket(f *testing.F) {
// Seed the fuzz corpus with the test cases defined in suite_test.go
for _, tc := range testCases {
file := tc.File

dataIn, err := os.ReadFile(file)
if err != nil {
f.Fatalf("failed to load file %s into fuzz corpus: %v", file, err)
continue
}
f.Add(dataIn)
}

// Seed the fuzz corpus with data known to cause panics in the past
f.Add([]byte{0x09, 0x02, 0x85, 0x30})
f.Add([]byte{0x09, 0x01, 0xcf})

// Set a limit on the length decoded in readPacket() since the call to
// make([]byte, length) can allocate up to MaxPacketLengthBytes which is
// currently 2 GB. This can cause memory related crashes when fuzzing in
// parallel or on memory constrained devices.
MaxPacketLengthBytes = 65536
f.Fuzz(func(t *testing.T, data []byte) {
stime := time.Now()
p, err := DecodePacketErr(data)

if e := time.Since(stime); e > (time.Millisecond * 500) {
t.Fatalf("DecodePacketErr took too long: %s", e)
}

if p == nil && err == nil {
t.Fatalf("DecodePacketErr returned a nil packet and no error")
}
})
}
6 changes: 6 additions & 0 deletions real.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,18 @@ func parseBinaryFloat(v []byte) (float64, error) {
case 0x02:
expLen = 3
case 0x03:
if len(v) < 2 {
return 0.0, errors.New("invalid data")
}
expLen = int(v[0])
if expLen > 8 {
return 0.0, errors.New("too big value of exponent")
}
v = v[1:]
}
if expLen > len(v) {
return 0.0, errors.New("too big value of exponent")
}
buf, v = v[:expLen], v[expLen:]
exponent, err := ParseInt64(buf)
if err != nil {
Expand Down

0 comments on commit 04301b4

Please sign in to comment.