Skip to content

Commit

Permalink
Fuzz test UncompressBlock and fix OOB write
Browse files Browse the repository at this point in the history
Includes a corpus that was bootstrapped from the unit tests, then
go-fuzz with -tags=noasm.
  • Loading branch information
greatroar committed Nov 16, 2020
1 parent fce381d commit 02ed8a4
Show file tree
Hide file tree
Showing 111 changed files with 130 additions and 7 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,6 @@ Temporary Items
# End of https://www.gitignore.io/api/macos

cmd/*/*exe
.idea
.idea

fuzz/*.zip
13 changes: 13 additions & 0 deletions fuzz/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module github.com/pierrec/lz4/v4/fuzz

go 1.14

require (
github.com/dvyukov/go-fuzz v0.0.0-20201115201419-0701ec3cea76
github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect
github.com/pierrec/lz4/v4 v4.0.0-00010101000000-000000000000
github.com/stephens2424/writerset v1.0.2 // indirect
golang.org/x/tools v0.0.0-20201116002733-ac45abd4c88c // indirect
)

replace github.com/pierrec/lz4/v4 => ../
36 changes: 36 additions & 0 deletions fuzz/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dvyukov/go-fuzz v0.0.0-20201115201419-0701ec3cea76 h1:2FjmcNOeX/oqxyYhY0+4u62aZCygG9GrnU8ci/qu9QU=
github.com/dvyukov/go-fuzz v0.0.0-20201115201419-0701ec3cea76/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robertkrimen/godocdown v0.0.0-20130622164427-0bfa04905481/go.mod h1:C9WhFzY47SzYBIvzFqSvHIR6ROgDo4TtdTuRaOMjF/s=
github.com/stephens2424/writerset v1.0.2 h1:znRLgU6g8RS5euYRcy004XeE4W+Tu44kALzy7ghPif8=
github.com/stephens2424/writerset v1.0.2/go.mod h1:aS2JhsMn6eA7e82oNmW4rfsgAOp9COBTTl8mzkwADnc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201116002733-ac45abd4c88c h1:quJUizHRFn7XriXTIOCLKSr76x2cMbNGfvfy9ubOO0g=
golang.org/x/tools v0.0.0-20201116002733-ac45abd4c88c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Binary file removed fuzz/lz4-fuzz.zip
Binary file not shown.
29 changes: 29 additions & 0 deletions fuzz/lz4.go
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,32 @@ func Fuzz(data []byte) int {
}
return 1
}

// Fuzzer for UncompressBlock: tries to decompress into a block the same size
// as the input.
//
// go-fuzz-build && go-fuzz -func=FuzzUncompressBlock -workdir=uncompress
func FuzzUncompressBlock(data []byte) int {
decomp := make([]byte, len(data)+16-len(data)%8)
for i := range decomp {
decomp[i] = byte(i)
}
decomp = decomp[:len(data)]

n, err := lz4.UncompressBlock(data, decomp)
if n > len(decomp) {
panic("uncompressed length greater than buffer")
}

decomp = decomp[:cap(decomp)]
for i := len(data); i < len(decomp); i++ {
if decomp[i] != byte(i) {
panic("UncompressBlock wrote out of bounds")
}
}

if err != nil {
return 0
}
return 1
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
B�;"!�/�
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
�>+=/MR��
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pa1same as non-reflect &v.field776356839400250464677810668945312
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
����������������������������������
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
������������������������������������������������������������������
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
������������������������������������������������������������������������
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
����������
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pa17763568394002504646778106689453125rsn
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
����
Empty file.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
������������������
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added fuzz/uncompress/corpus/empty_input
Binary file not shown.
Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions fuzz/uncompress/corpus/literal_only_long
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
���AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Binary file added fuzz/uncompress/corpus/literal_only_long_1
Binary file not shown.
1 change: 1 addition & 0 deletions fuzz/uncompress/corpus/literal_only_short
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Phello
Binary file added fuzz/uncompress/corpus/long_match
Binary file not shown.
Binary file added fuzz/uncompress/corpus/repeat_match_len
Binary file not shown.
Binary file added fuzz/uncompress/corpus/repeat_match_len_2_seq
Binary file not shown.
Binary file added fuzz/uncompress/corpus/repeat_match_log_len_2_seq
Binary file not shown.
4 changes: 4 additions & 0 deletions internal/lz4block/decode_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
package lz4block

func decodeBlock(dst, src []byte) (ret int) {
// Restrict capacities so we don't read or write out of bounds.
dst = dst[:len(dst):len(dst)]
src = src[:len(src):len(src)]

const hasError = -2
defer func() {
if recover() != nil {
Expand Down
39 changes: 33 additions & 6 deletions internal/lz4block/decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ func TestBlockDecode(t *testing.T) {
concat(emitSeq("a", 1, 15), emitSeq("B", 1, 15), emitSeq("end", 0, 0)),
[]byte(strings.Repeat("a", 16) + strings.Repeat("B", 16) + "end"),
},
{
"fuzz-3e4ce8cc0da392ca5a353b6ffef6d08f400ac5f9",
[]byte("0000\x01\x00"),
[]byte("0000000"),
},
}

for _, test := range tests {
Expand All @@ -135,24 +140,46 @@ func TestBlockDecode(t *testing.T) {
func TestDecodeBlockInvalid(t *testing.T) {
t.Parallel()

dst := make([]byte, 100)

for _, test := range []struct {
name string
src string
size int // Output size to try.
}{
{
"empty_input",
"",
100,
},
{
"final_lit_too_short",
"\x20a", // litlen = 2 but only a single-byte literal
100,
},
{
"write_beyond_len_dst",
"\x1b0\x01\x00000000000000",
len("\x1b0\x01\x00000000000000"),
},
} {
r := decodeBlock(dst, []byte(test.src))
if r >= 0 {
t.Errorf("no error for %s", test.name)
}
t.Run(test.name, func(t *testing.T) {
dst := make([]byte, test.size+8)
for i := range dst {
dst[i] = byte(i)
}
dst = dst[:test.size]

r := decodeBlock(dst, []byte(test.src))
if r >= 0 {
t.Errorf("no error for %s", test.name)
}

dst = dst[:cap(dst)]
for i := test.size; i < len(dst); i++ {
if dst[i] != byte(i) {
t.Error("decodeBlock wrote out of bounds")
break
}
}
})
}
}

0 comments on commit 02ed8a4

Please sign in to comment.