Skip to content

Commit d2a5dba

Browse files
authored
triedb/pathdb: fix 32-bit integer overflow in history trienode decoder (#33098)
failed in 32bit: ``` --- FAIL: TestDecodeSingleCorruptedData (0.00s) panic: runtime error: slice bounds out of range [:-1501805520] [recovered, repanicked] goroutine 38872 [running]: testing.tRunner.func1.2({0x838db20, 0xa355620}) /opt/actions-runner/_work/_tool/go/1.25.3/x64/src/testing/testing.go:1872 +0x29b testing.tRunner.func1() /opt/actions-runner/_work/_tool/go/1.25.3/x64/src/testing/testing.go:1875 +0x414 panic({0x838db20, 0xa355620}) /opt/actions-runner/_work/_tool/go/1.25.3/x64/src/runtime/panic.go:783 +0x103 github.com/ethereum/go-ethereum/triedb/pathdb.decodeSingle({0x9e57500, 0x1432, 0x1432}, 0x0) /opt/actions-runner/_work/go-ethereum/go-ethereum/triedb/pathdb/history_trienode.go:399 +0x18d6 github.com/ethereum/go-ethereum/triedb/pathdb.TestDecodeSingleCorruptedData(0xa2db9e8) /opt/actions-runner/_work/go-ethereum/go-ethereum/triedb/pathdb/history_trienode_test.go:698 +0x180 testing.tRunner(0xa2db9e8, 0x83c86e8) /opt/actions-runner/_work/_tool/go/1.25.3/x64/src/testing/testing.go:1934 +0x114 created by testing.(*T).Run in goroutine 1 /opt/actions-runner/_work/_tool/go/1.25.3/x64/src/testing/testing.go:1997 +0x4b4 FAIL github.com/ethereum/go-ethereum/triedb/pathdb 41.453s ? github.com/ethereum/go-ethereum/version [no test files] FAIL ``` Found in https://github.com/ethereum/go-ethereum/actions/runs/18912701345/job/53990136071?pr=33052
1 parent 982235f commit d2a5dba

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

triedb/pathdb/history_trienode.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ package pathdb
1919
import (
2020
"bytes"
2121
"encoding/binary"
22+
"errors"
2223
"fmt"
2324
"iter"
2425
"maps"
26+
"math"
2527
"slices"
2628
"sort"
2729
"time"
@@ -386,12 +388,26 @@ func decodeSingle(keySection []byte, onValue func([]byte, int, int) error) ([]st
386388
}
387389
// Resolve the entry from key section
388390
nShared, nn := binary.Uvarint(keySection[keyOff:]) // key length shared (varint)
391+
if nn <= 0 {
392+
return nil, fmt.Errorf("corrupted varint encoding for nShared at offset %d", keyOff)
393+
}
389394
keyOff += nn
390395
nUnshared, nn := binary.Uvarint(keySection[keyOff:]) // key length not shared (varint)
396+
if nn <= 0 {
397+
return nil, fmt.Errorf("corrupted varint encoding for nUnshared at offset %d", keyOff)
398+
}
391399
keyOff += nn
392400
nValue, nn := binary.Uvarint(keySection[keyOff:]) // value length (varint)
401+
if nn <= 0 {
402+
return nil, fmt.Errorf("corrupted varint encoding for nValue at offset %d", keyOff)
403+
}
393404
keyOff += nn
394405

406+
// Validate that the values can fit in an int to prevent overflow on 32-bit systems
407+
if nShared > uint64(math.MaxUint32) || nUnshared > uint64(math.MaxUint32) || nValue > uint64(math.MaxUint32) {
408+
return nil, errors.New("key size too large")
409+
}
410+
395411
// Resolve unshared key
396412
if keyOff+int(nUnshared) > len(keySection) {
397413
return nil, fmt.Errorf("key length too long, unshared key length: %d, off: %d, section size: %d", nUnshared, keyOff, len(keySection))

triedb/pathdb/history_trienode_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,10 @@ func TestDecodeSingleCorruptedData(t *testing.T) {
694694
// Test with corrupted varint in key section
695695
corrupted := make([]byte, len(keySection))
696696
copy(corrupted, keySection)
697-
corrupted[5] = 0xFF // Corrupt varint
697+
// Fill first 10 bytes with 0xFF to create a varint overflow (>64 bits)
698+
for i := range 10 {
699+
corrupted[i] = 0xFF
700+
}
698701
_, err = decodeSingle(corrupted, nil)
699702
if err == nil {
700703
t.Fatal("Expected error for corrupted varint")

0 commit comments

Comments
 (0)