fix: F-2026-18804 | [Dual Defense] EVM ABI readDynamicBytes Uint64 Overflow Panics Can Kill puniversald - #322
Merged
Merged
Conversation
…evm log parser (F-2026-18804)
…18804)" This reverts commit 0eaf1a9.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
F-2026-18804 ABI decoder overflow panics
Issue
readDynamicBytesbounded with additive uint64 arithmetic. Both inputs come from log data an RPC supplies, so both can be chosen to wrap.absOff+32wraps small and passes the guard →data[absOff:absOff+32]panics.dataStart+byteLenwraps belowdataStart→ the length guard fails open →data[dataStart:dataEnd]panics.puniversald— every chain plus TSS in that process.Reproduced both before fixing:
slice bounds out of range [18446744073709551599:15]and[32:31].Approach taken
absOff > n || n-absOff < 32, thenn-dataStart < byteLen.ParseEventrecovers, logs the panic with tx hash and log index, and returns nil so the log is skipped like any other undecodable one. The decode logic is unchanged — the recover is a thin wrapper around it.The recover is deliberately at the log boundary rather than the poll loop: one malformed log is skipped, everything else in the batch still processes, and a genuine bug elsewhere still surfaces rather than being swallowed silently.
Scope
Swept the other decoders for the same class — the overflow is unique to
readDynamicBytes, every other computed bound is already checked before slicing.Tests
MaxUint64and the four values that wrap+32onto a small number are all rejected.MaxUint64is rejected rather than wrapping the end below the start.