When the built-in slice()
function is called, there are three special values that have their own logic:
The _build_adhoc_slice_node()
function implements custom logic on the msg.data
, self.code
, and address.code
types to perform custom bounds checks and return the requested slice. The bounds checks implemented in the fetch_call_return()
function are skipped for these types.
Let's look at msg.data
as an example (although the same issue applies to all three):
This IR code performs a runtime bounds check to ensure that start + length
< calldatasize
, in order to ensure that we can only access memory inside of the calldata
.
However, there is no overflow check on the addition. As a result, it is possible for a user who has the ability to specify either the start
or the length
to cause an overflow and bypass the bounds check. The result will be a slice of memory that is outside of the calldata
region, and will return 0
.
Consider the following Vyper contract, which allows a user to specify an index into msg.data
that meets the criteria idx % 32 == 4
and returns 32 bytes from that index. This should only allow a user to choose indexes that correspond to the starts of the function arguments. Any index beyond 68 should throw an out of bound error.
The following Foundry test case demonstrates that the bound check can be violated by using a sufficiently high idx
value:
Vyper functions that are written in order to restrict the possible values that could be returned can be abused by a malicious user to return an unexpected value.
Manual Review, Foundry
The bounds check in the _build_adhoc_slice_node()
function should be updated to ensure that the addition of start
and length
does not overflow:
severity to be re-evaluated
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.