core/state,triedb/pathdb: add defensive length checks in encodeBinary and encodeStemBlob

Addresses review findings I13 and S6.

encodeBinary: reject non-nil bintrie leaves with length != 32 at the
trust boundary between the hasher and the state update. Previously a
wrong-length leaf silently made it into the diff layer's accountData
and only surfaced as a panic deep in the Flush path (stemBuilder.set).

encodeStemBlob: add an upper-bound check on the value count (must be
<= 256, the maximum offsets per stem). Previously a buggy producer
could pass an arbitrarily long values slice.
This commit is contained in:
CPerezz 2026-04-09 12:19:51 +02:00
parent 69c0028094
commit 9fc733c2e2
No known key found for this signature in database
GPG key ID: 62045F34B97177DD
2 changed files with 12 additions and 1 deletions

View file

@ -301,10 +301,18 @@ func (sc *stateUpdate) encodeBinary() (map[common.Hash][]byte, map[common.Addres
accounts[fullKey] = nil
continue
}
// Defensive length check: every non-nil bintrie leaf must be
// exactly 32 bytes. A wrong-length leaf from the hasher would
// silently produce garbage in the diff layer; catch it here at
// the trust boundary rather than deep in the flush path where
// the stemBuilder.set panic would fire with less context.
if len(w.Value) != 32 {
return nil, nil, nil, nil, fmt.Errorf("bintrie leaf at stem %x offset %d has value len %d, want 32", w.Stem, w.Offset, len(w.Value))
}
// Take an owning copy: the hasher reuses its underlying buffers
// across blocks, so retaining its slices would create cross-block
// aliasing bugs in the pathdb diff layer.
v := make([]byte, len(w.Value))
v := make([]byte, 32)
copy(v, w.Value)
accounts[fullKey] = v
}

View file

@ -84,6 +84,9 @@ func encodeStemBlob(bitmap [stemBlobBitmapSize]byte, values [][]byte) ([]byte, e
if count != len(values) {
return nil, fmt.Errorf("stem blob popcount=%d values=%d: %w", count, len(values), errStemBlobMalformed)
}
if count > stemBlobBitmapBits {
return nil, fmt.Errorf("stem blob value count %d exceeds max %d: %w", count, stemBlobBitmapBits, errStemBlobMalformed)
}
if count == 0 {
return nil, nil
}