#37985 [SC-Low] Incorrectly Eliminate Code With Side Effect In Slice Args
Submitted on Dec 20th 2024 at 19:11:37 UTC by @anatomist for Attackathon | Ethereum Protocol
Report ID: #37985
Report Type: Smart Contract
Report severity: Low
Target: https://github.com/vyperlang/vyper
Impacts:
(Compiler) Incorrect bytecode generation leading to incorrect behavior
(Compiler) Unexpected behavior
Description
Brief/Intro
The slice
precompile skips length != 0
check when the first argument is an is_adhoc_slice
. However, if length == 0
, the make_setter
function will discard all operations except mstore dst_size_field 0
regardless of any potential side effect, leading to incorrect compilation.
Vulnerability Details
The slice buildin skips a lot of checks when the src to be slices is an adhoc_slice
(msg.data
or (address).code
). Notably, the length_literal < 1
check is skipped.
Thus the following code will compile
During code generation, the IR for the slice builtin is created by the following snippet
And then returned to parse_AnnAssign
as rhs
Then make_setter
is called to generate the final ir for this statement.
Unfortunately, rhs
(slice
result) ir is completely dropped when its src.typ.maxlen == 0
, along with any side effects that it may have. This in turn leads to incorrect compilation.
While we use slice
as an entry point for this issue, we consider the actual root cause to be make_setter
and make_byte_array_copier
which eliminates ir without checking whether it contains side effect. There are potentially other entry points that we haven't explored yet, but can lead to the same issue.
Additionally, the is_adhoc_slice
checker is also not precise, since it doesn't check whether the code
attribute comes from an address
, so if user defined a struct that contains a field calls code
, then it'll also be treated as an is_adhoc_slice
in Slice.fetch_call_return
.
Impact Details
Incorrectly optimizing out side effects can result in all kinds of unexpected behaviors in a contract, such as skipping critical checks performed in the incorrectly eliminated code, skipping important business logic, and more. This exposes contract developers to substantial risks.
References
https://github.com/vyperlang/vyper/blob/12ab4919cc4618fcac4f5d24d45a0e7fdbc4a48c/vyper/builtins/functions.py#L320
https://github.com/vyperlang/vyper/blob/12ab4919cc4618fcac4f5d24d45a0e7fdbc4a48c/vyper/builtins/functions.py#L247
https://github.com/vyperlang/vyper/blob/12ab4919cc4618fcac4f5d24d45a0e7fdbc4a48c/vyper/codegen/stmt.py#L63
https://github.com/vyperlang/vyper/blob/12ab4919cc4618fcac4f5d24d45a0e7fdbc4a48c/vyper/codegen/core.py#L983
https://github.com/vyperlang/vyper/blob/12ab4919cc4618fcac4f5d24d45a0e7fdbc4a48c/vyper/codegen/core.py#L160
Proof of Concept
Proof of Concept
Already shown in Vulnerability Details section.
Was this helpful?