Skip to content
Merged
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
16 changes: 16 additions & 0 deletions triedb/pathdb/history_trienode.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ package pathdb
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"iter"
"maps"
"math"
"slices"
"sort"
"time"
Expand Down Expand Up @@ -386,12 +388,26 @@ func decodeSingle(keySection []byte, onValue func([]byte, int, int) error) ([]st
}
// Resolve the entry from key section
nShared, nn := binary.Uvarint(keySection[keyOff:]) // key length shared (varint)
if nn <= 0 {
return nil, fmt.Errorf("corrupted varint encoding for nShared at offset %d", keyOff)
}
keyOff += nn
nUnshared, nn := binary.Uvarint(keySection[keyOff:]) // key length not shared (varint)
if nn <= 0 {
return nil, fmt.Errorf("corrupted varint encoding for nUnshared at offset %d", keyOff)
}
keyOff += nn
nValue, nn := binary.Uvarint(keySection[keyOff:]) // value length (varint)
if nn <= 0 {
return nil, fmt.Errorf("corrupted varint encoding for nValue at offset %d", keyOff)
}
keyOff += nn

// Validate that the values can fit in an int to prevent overflow on 32-bit systems
if nShared > uint64(math.MaxUint32) || nUnshared > uint64(math.MaxUint32) || nValue > uint64(math.MaxUint32) {
return nil, errors.New("key size too large")
}

// Resolve unshared key
if keyOff+int(nUnshared) > len(keySection) {
return nil, fmt.Errorf("key length too long, unshared key length: %d, off: %d, section size: %d", nUnshared, keyOff, len(keySection))
Expand Down
5 changes: 4 additions & 1 deletion triedb/pathdb/history_trienode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,10 @@ func TestDecodeSingleCorruptedData(t *testing.T) {
// Test with corrupted varint in key section
corrupted := make([]byte, len(keySection))
copy(corrupted, keySection)
corrupted[5] = 0xFF // Corrupt varint
// Fill first 10 bytes with 0xFF to create a varint overflow (>64 bits)
for i := range 10 {
corrupted[i] = 0xFF
}
_, err = decodeSingle(corrupted, nil)
if err == nil {
t.Fatal("Expected error for corrupted varint")
Expand Down