What changed, and why it matters
This commit is a simple code cleanup in the Ethereum clear-signing module. It pulls out a repeated snippet of code that reads variable-length data into a new helper function, then replaces two copies of that snippet with calls to the helper. No behavior changes are visible in the diff.
No security action needed; this is a non-functional refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch refactors the Dynamic and Tuple classes in core/src/apps/ethereum/clear_signing.py. Both classes previously inlined the same logic for reading an ABI-encoded dynamic value: bounds-check the 32-byte length prefix, decode the length, bounds-check the payload, and slice the payload. The patch introduces _read_dynamic_data(raw_data, pointer) containing that exact logic and calls it from both sites. The bounds checks, byte offsets, and slicing are identical before and after.
Changed components
core/src/apps/ethereum/clear_signing.pyInspect captured patch +13 / −15
diff --git a/core/src/apps/ethereum/clear_signing.py b/core/src/apps/ethereum/clear_signing.py
index 976220fe..9cbf1f8c 100644
--- a/core/src/apps/ethereum/clear_signing.py
+++ b/core/src/apps/ethereum/clear_signing.py
@@ -450,6 +450,17 @@ class Atomic(ABIValue):
return self.parser(raw_data[offset : offset + 32]), 32
+def _read_dynamic_data(raw_data: memoryview, pointer: int) -> memoryview:
+ """Read a variable-length blob located at `pointer` in `raw_data`,
+ encoded as a 32-byte length prefix followed by `length` bytes of data."""
+ if pointer + 32 > len(raw_data):
+ raise OutOfBounds
+ length = int.from_bytes(raw_data[pointer : pointer + 32], "big")
+ if pointer + 32 + length > len(raw_data):
+ raise OutOfBounds
+ return raw_data[pointer + 32 : pointer + 32 + length]
+
+
class Dynamic(ABIValue):
"""Dynamic values, such as strings or `bytes` are stored later in the calldata,
the inline value being just a pointer to the actual location.
@@ -463,12 +474,7 @@ class Dynamic(ABIValue):
if offset + 32 > len(raw_data):
raise OutOfBounds
pointer = int.from_bytes(raw_data[offset : offset + 32], "big")
- if pointer + 32 > len(raw_data):
- raise OutOfBounds
- length = int.from_bytes(raw_data[pointer : pointer + 32], "big")
- if pointer + 32 + length > len(raw_data):
- raise OutOfBounds
- data = raw_data[pointer + 32 : pointer + 32 + length]
+ data = _read_dynamic_data(raw_data, pointer)
return self.parser(data), 32
@@ -511,15 +517,7 @@ class Tuple(ABIValue):
value[i] = v
else:
field_pointer = base_offset + int.from_bytes(raw_field, "big")
-
- if field_pointer + 32 > len(raw_data):
- raise OutOfBounds
- length = int.from_bytes(
- raw_data[field_pointer : field_pointer + 32], "big"
- )
- if field_pointer + 32 + length > len(raw_data):
- raise OutOfBounds
- raw_field = raw_data[field_pointer + 32 : field_pointer + 32 + length]
+ raw_field = _read_dynamic_data(raw_data, field_pointer)
v = parser(raw_field)
if isinstance(v, (tuple, list)):
# Tuple or Array inside a Tuple
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.