refactor(clear_signing): remove dead parse_uint256_array and unreachable guards.
What changed, and why it matters
This commit removes unused code and unreachable safety checks from the Ethereum clear-signing module. The removed function (parse_uint256_array) was never actually used, and the type-check guards it supported could never be triggered. There is no evidence this change fixes or introduces a security vulnerability; it is a code cleanup.
No security action required. Treat as routine refactoring. If reviewing, verify that no other code path references parse_uint256_array and that the Parser type narrowing does not break static analysis elsewhere.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change deletes parse_uint256_array, which was not constructed by from_proto or any built-in definition. The commit message explains that even if wired in, it would be incorrect because dynamic tuple fields use _read_dynamic_data, which interprets the 32-byte prefix as a byte length, whereas arrays use an element count. With no Parser returning a tuple/list, the isinstance(v, (tuple, list)) -> NotImplementedError checks in Tuple.parse become unreachable and are removed. The Parser type alias is narrowed from AnyValue to Value. No functional behavior changes for reachable code paths.
Changed components
core/src/apps/ethereum/clear_signing.pyInspect captured patch +4 / −21
diff --git a/core/src/apps/ethereum/clear_signing.py b/core/src/apps/ethereum/clear_signing.py
index 811b1f5e..08a0ee54 100644
--- a/core/src/apps/ethereum/clear_signing.py
+++ b/core/src/apps/ethereum/clear_signing.py
@@ -44,7 +44,7 @@ if TYPE_CHECKING:
# Parses a Value from a slice of the calldata.
# Assumes that the memoryview contains just that value.
- Parser = Callable[[memoryview], AnyValue]
+ Parser = Callable[[memoryview], Value]
SC_FUNC_SIG_BYTES = const(4)
@@ -164,16 +164,7 @@ def parse_string(raw_data: memoryview) -> Value:
return bytes(raw_data).decode("utf-8")
-def parse_uint256_array(raw_data: memoryview) -> list[Value]:
- if len(raw_data) % 32 != 0:
- raise InvalidFunctionCall
- return [
- parse_uint256(raw_data[i * 32 : (i + 1) * 32])
- for i in range(len(raw_data) // 32)
- ]
-
-
-DYNAMIC_DATA_PARSERS = [parse_bytes, parse_string, parse_uint256_array]
+DYNAMIC_DATA_PARSERS = [parse_bytes, parse_string]
def _get_parser(t: int, is_dynamic: bool) -> Parser:
@@ -648,19 +639,11 @@ class Tuple(ABIValue):
field_head_pos = base_offset + (i * 32)
raw_field = raw_data[field_head_pos : field_head_pos + 32]
if parser not in DYNAMIC_DATA_PARSERS:
- v = parser(raw_field)
- if isinstance(v, (tuple, list)):
- # Tuple or Array inside a Tuple
- raise NotImplementedError
- value[i] = v
+ value[i] = parser(raw_field)
else:
field_pointer = base_offset + int.from_bytes(raw_field, "big")
raw_field = _read_dynamic_data(raw_data, field_pointer)
- v = parser(raw_field)
- if isinstance(v, (tuple, list)):
- # Tuple or Array inside a Tuple
- raise NotImplementedError
- value[i] = v
+ value[i] = parser(raw_field)
return tuple(value), consumed
Why this scored 13/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.