fix[venom]: reject statically undersized abi_decode input#5094
Conversation
| assert_compile_failed(lambda: get_contract(bad_code), exception) | ||
|
|
||
|
|
||
| def test_abi_decode_undersized_buffer_venom(): |
There was a problem hiding this comment.
do we not already have a test for this which is just not tripped on venom pipeline?
There was a problem hiding this comment.
Yes, there was already a length-mismatch compile-failure table. I folded the public abi_decode(data, (uint256, uint256)) undersized-buffer case into test_abi_decode_length_mismatch and removed the separate Venom-named test in b0de8d8. Validation: uv run --python 3.12 -m pytest tests/functional/builtins/codegen/test_abi_decode.py -k length_mismatch -q and the focused black check.
charles-cooper
left a comment
There was a problem hiding this comment.
ok in principle; see my testing comment. paging @HodanPlodky for review
Gas ChangesNo changes detected. Summary
|
📊 Bytecode Size Changes (venom)No changes detected. Full bytecode sizes
|
| ( | ||
| """ | ||
| @external | ||
| def foo(data: Bytes[4]) -> (uint256, uint256): |
There was a problem hiding this comment.
this test passes also in the master why was the change in logic necessary?
There was a problem hiding this comment.
You're right - the folded table row passes on master in a default local run because that path uses legacy codegen. The regression is only in Venom.
I added test_abi_decode_undersized_buffer_venom, which forces Settings(experimental_codegen=True): on origin/master the reproducer compiles, while this branch raises StructureException. I also updated the PR body to make that distinction explicit.
Validation:
uv run --python 3.12 -m pytest tests/functional/builtins/codegen/test_abi_decode.py -k "length_mismatch or undersized_buffer_venom" -q
uv run --python 3.12 -m pytest tests/functional/builtins/codegen/test_abi_decode.py -k "length_mismatch or undersized_buffer_venom" --experimental-codegen -q
uv run --python 3.12 black --check tests/functional/builtins/codegen/test_abi_decode.py vyper/codegen_venom/builtins/abi.py
git diff --check
What I did
Fixes #5055.
The Venom
abi_decodelowering was missing legacy's compile-time check that the input bytestring's max length can fit the ABI size bound of the requested output type.abi_decode(data, (uint256, uint256))withdata: Bytes[4]compiled under--experimental-codegeninto code that can only revert at runtime, while legacy rejects it at compile time.How I did it
Ported the check from legacy
ABIDecode.build_IRintolower_abi_decode, afterwrapped_typis computed and before any IR is emitted. The condition is the same as legacy: reject wheninput_max_len < wrapped_typ.abi_type.size_bound(), usingStructureExceptionat the input argument source location.How to verify it
The shared length-mismatch table now includes the public
abi_decode(data, (uint256, uint256))shape. That row can pass on master in a default local run because it is exercising legacy codegen there; the differentiating regression is the explicittest_abi_decode_undersized_buffer_venom, which forcesSettings(experimental_codegen=True).I checked that the direct experimental-codegen reproducer compiles on
origin/masterand raisesStructureExceptionon this branch.Focused validation:
Commit message
Description for the changelog
Fix: experimental codegen rejects
abi_decodewith statically undersized input buffers at compile time, matching legacy.Cute Animal Picture