Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion encoding/internal/wkbcommon/point.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ func unmarshalPoints(order byteOrder, data []byte) ([]orb.Point, error) {
num := unmarshalUint32(order, data)
data = data[4:]

if len(data) < int(num*16) {
// Compute the required byte count in 64-bit space. num is a uint32 read
// directly from the input, so num*16 can overflow a uint32 (or a 32-bit
// int) and wrap to a small value, letting an undersized buffer slip past
// this guard and panic in the read loop below.
if uint64(len(data)) < uint64(num)*16 {
return nil, ErrNotWKB
}

Expand Down
17 changes: 17 additions & 0 deletions encoding/wkb/line_string_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,20 @@ func TestMultiLineString(t *testing.T) {
})
}
}

func TestLineString_pointCountOverflow(t *testing.T) {
// A crafted little-endian linestring header claims a point count whose
// byte size (count * 16) overflows a uint32 and wraps to a small value.
// Before the length check was done in 64-bit space this slipped past the
// bounds guard and read past the end of the buffer.
data := []byte{
0x01, // little endian
0x02, 0x00, 0x00, 0x00, // type: linestring
0x01, 0x00, 0x00, 0x10, // point count 0x10000001; *16 wraps to 16 in uint32
}
data = append(data, make([]byte, 16)...) // only one point's worth of data

if _, err := Unmarshal(data); err != ErrNotWKB {
t.Fatalf("expected ErrNotWKB, got %v", err)
}
}