Commit 45fb14a6 authored by Kirill Smelkov's avatar Kirill Smelkov

decoder: Fix integer overflow in BYTEARRAY8 handling

Rerunning fuzzing afresh found the following crash because uint64 len > max(int64)
was cast to int resulting in negative number:

    "\x960000000\xbd"

    panic: bytes.Buffer.Grow: negative count

    goroutine 1 [running]:
    bytes.(*Buffer).Grow(0xc000012140?, 0xc00010abf8?)
            /home/kirr/src/tools/go/go1.22/src/bytes/buffer.go:166 +0xb4
    github.com/kisielk/og-rek.(*Decoder).bufLoadBytesData(0xc000072000, 0xbd30303030303030)
            /home/kirr/src/neo/src/github.com/kisielk/og-rek/ogorek.go:788 +0xd5
    github.com/kisielk/og-rek.(*Decoder).bufLoadBinData8(0xc000072000)
            /home/kirr/src/neo/src/github.com/kisielk/og-rek/ogorek.go:776 +0x105
    github.com/kisielk/og-rek.(*Decoder).loadBytearray8(0xc000072000)
            /home/kirr/src/neo/src/github.com/kisielk/og-rek/ogorek.go:1270 +0x34
    github.com/kisielk/og-rek.(*Decoder).Decode(0xc000072000)
            /home/kirr/src/neo/src/github.com/kisielk/og-rek/ogorek.go:311 +0x1a2c
    github.com/kisielk/og-rek.Fuzz({0x7fd052187000, 0x9, 0x9})
            /home/kirr/src/neo/src/github.com/kisielk/og-rek/fuzz.go:15 +0xf6
    go-fuzz-dep.Main({0xc00010af38, 0x1, 0x5bc338?})
            go-fuzz-dep/main.go:36 +0x14c
    main.main()
            github.com/kisielk/og-rek/go.fuzz.main/main.go:15 +0x35
    exit status 2

-> Fix it by first comparing uint64 len without casting and further casting to
int only after we cap the len to be in safe range.
parent 72a53b61
...@@ -781,11 +781,12 @@ func (d *Decoder) bufLoadBinData8() error { ...@@ -781,11 +781,12 @@ func (d *Decoder) bufLoadBinData8() error {
func (d *Decoder) bufLoadBytesData(l uint64) error { func (d *Decoder) bufLoadBytesData(l uint64) error {
d.buf.Reset() d.buf.Reset()
// don't allow malicious `BINSTRING <bigsize> nodata` to make us out of memory // don't allow malicious `BINSTRING <bigsize> nodata` to make us out of memory
prealloc := int(l) prealloc := l
if maxgrow := 0x10000; prealloc > maxgrow { const maxgrow = 0x10000
if prealloc > maxgrow {
prealloc = maxgrow prealloc = maxgrow
} }
d.buf.Grow(prealloc) d.buf.Grow(int(prealloc))
if l > math.MaxInt64 { if l > math.MaxInt64 {
return fmt.Errorf("size([]data) > maxint64") return fmt.Errorf("size([]data) > maxint64")
} }
......
...@@ -839,9 +839,10 @@ func TestFuzzCrashers(t *testing.T) { ...@@ -839,9 +839,10 @@ func TestFuzzCrashers(t *testing.T) {
"(c\n\nc\n\n\x85Rd", "(c\n\nc\n\n\x85Rd",
"}(U\x040000u", "}(U\x040000u",
"(\x88d", "(\x88d",
"(]QNd.", // PersID([]) -> dict "(]QNd.", // PersID([]) -> dict
"}]QNs.", // PersID([]) -> setitem "}]QNs.", // PersID([]) -> setitem
"}(]QNI1\nNu.", // PersID([]) ... -> setitems "}(]QNI1\nNu.", // PersID([]) ... -> setitems
"\x960000000\xef", // BYTEARRAY8
} }
for _, c := range crashers { for _, c := range crashers {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment