Skip to content

fix(dyn-abi): limit struct metadata copied by EIP-712 coercion - #1258

Merged
DaniPopes merged 5 commits into
mainfrom
dani/eip712-struct-metadata
Nov 2, 2026
Merged

DaniPopes merged 5 commits into
mainfrom
dani/eip712-struct-metadata

Conversation

@DaniPopes

@DaniPopes DaniPopes commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Coercing an EIP-712 message into a DynSolValue copies the struct name and property names into every DynSolValue::CustomStruct, and resolving a type copies them into every DynSolType::CustomStruct. Names have no length limit, so a schema like Root(LongName[] items) with a 64 KiB LongName and 16,384 array elements allocates over 1 GiB of copied names from a message under 400 KiB (VER-1060).

DynSolType::coerce_json now charges each coerced struct's name, property names and fixed-size value against a 16 MiB budget shared across the whole call, and Resolver::resolve charges the names of every expanded struct against a 1 MiB budget. Both return an error once exhausted. This bounds the amplification without changing any public type, and covers TypedData::coerce, encode_data, hash_struct and eip712_signing_hash. Real messages carry a few hundred bytes of metadata per struct, far below the limits.

Coercing a custom struct copies its name and property names into each
DynSolValue::CustomStruct. A long type name and a long array of small
structs could therefore allocate gigabytes from a small message.

Charge those bytes against a 16 MiB budget shared across one
coerce_json call and fail once it is exhausted.
@DaniPopes
DaniPopes marked this pull request as ready for review November 2, 2026 16:01
@DaniPopes
DaniPopes requested a review from mattsse as a code owner November 2, 2026 16:01
@tempoxyz-bot

tempoxyz-bot commented Nov 2, 2026 •

Copy link
Copy Markdown

👁️ Cyclops Security Review

✅ Reviewed f41df0a (latest) · Coverage: partial · no open findings · report
⚠️ Not checked: Coercion metadata accounting across nested containers and error branches: ruled out without reading the cited code at this commit
⚠️ Not checked: I have not identified which downstream consumers (wallet signers, RPC eth_signTypedData handlers, relayers) pass untrusted TypedData to coerce, encode_data or eip712_signing_hash in production.
⚠️ Not checked: ABI decoding into a DynSolType that contains CustomStruct (decode_sequence and detokenize) still clones the struct name and property names into every decoded value, with no metadata budget. This is the same amplification the PR fixes for co
ℹ️ Not verifiable from the source alone (needs running code or deployed state): The added regression tests and feature builds were inspected but not executed during this read-only review; runtime allocation behavior and test outcomes are not established. To verify it: Run cargo t (2 more in the report)

@DaniPopes
DaniPopes merged commit 70a63bd into main Nov 2, 2026
56 checks passed
@DaniPopes
DaniPopes deleted the dani/eip712-struct-metadata branch November 2, 2026 21:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants