Skip to content

Commit b97e1e3

Browse files
committed
Add bounds check suggested by Copilot
1 parent 8c89e70 commit b97e1e3

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

internal/decoder/decoder.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,14 @@ func (d *Decoder) DecodeUInt128() (hi, lo uint64, err error) {
224224
)
225225
}
226226

227+
if offset+size > uint(len(d.d.buffer)) {
228+
return 0, 0, mmdberrors.NewInvalidDatabaseError(
229+
"the MaxMind DB file's data section contains bad data (offset+size %d exceeds buffer length %d)",
230+
offset+size,
231+
len(d.d.buffer),
232+
)
233+
}
234+
227235
for _, b := range d.d.buffer[offset : offset+size] {
228236
var carry byte
229237
lo, carry = append64(lo, b)
@@ -392,6 +400,13 @@ func (d *Decoder) decodeBytes(typ Type) ([]byte, error) {
392400
if err != nil {
393401
return nil, err
394402
}
403+
if offset+size > uint(len(d.d.buffer)) {
404+
return nil, mmdberrors.NewInvalidDatabaseError(
405+
"the MaxMind DB file's data section contains bad data (offset+size %d exceeds buffer length %d)",
406+
offset+size,
407+
len(d.d.buffer),
408+
)
409+
}
395410
d.setNextOffset(offset + size)
396411
return d.d.buffer[offset : offset+size], nil
397412
}

internal/decoder/decoder_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,3 +366,36 @@ func TestPointersInDecoder(t *testing.T) {
366366
})
367367
}
368368
}
369+
370+
// TestBoundsChecking verifies that buffer access is properly bounds-checked
371+
// to prevent panics on malformed databases.
372+
func TestBoundsChecking(t *testing.T) {
373+
// Create a very small buffer that would cause out-of-bounds access
374+
// if bounds checking is not working
375+
smallBuffer := []byte{0x44, 0x41} // Type string (0x4), size 4, but only 2 bytes total
376+
dd := NewDataDecoder(smallBuffer)
377+
decoder := &Decoder{d: dd, offset: 0}
378+
379+
// This should fail gracefully with an error instead of panicking
380+
_, err := decoder.DecodeString()
381+
require.Error(t, err)
382+
require.Contains(t, err.Error(), "exceeds buffer length")
383+
384+
// Test DecodeBytes bounds checking with a separate buffer
385+
bytesBuffer := []byte{0x84, 0x41} // Type bytes (4 << 5 = 0x80), size 4 (0x04), but only 2 bytes total
386+
dd3 := NewDataDecoder(bytesBuffer)
387+
decoder3 := &Decoder{d: dd3, offset: 0}
388+
389+
_, err = decoder3.DecodeBytes()
390+
require.Error(t, err)
391+
require.Contains(t, err.Error(), "exceeds buffer length")
392+
393+
// Test DecodeUInt128 bounds checking
394+
uint128Buffer := []byte{0x0B, 0x03} // Extended type (0x0), size 11, TypeUint128-7=3, but only 2 bytes total
395+
dd2 := NewDataDecoder(uint128Buffer)
396+
decoder2 := &Decoder{d: dd2, offset: 0}
397+
398+
_, _, err = decoder2.DecodeUInt128()
399+
require.Error(t, err)
400+
require.Contains(t, err.Error(), "exceeds buffer length")
401+
}

0 commit comments

Comments
 (0)