Summary
When looping over a range
of the form range(start, start + N)
, if start
is negative, the execution will always revert.
Details
This issue is caused by an incorrect assertion inserted by the code generation of the range (stmt.parse_For_range()
):
|
_, hi = start.typ.int_bounds |
|
start = clamp("le", start, hi + 1 - rounds) |
This assertion was introduced in 3de1415 to fix GHSA-6r8q-pfpv-7cgj. The issue arises when start
is signed, instead of using sle
, le
is used and start
is interpreted as an unsigned integer for the comparison. If it is a negative number, its 255th bit is set to 1
and is hence interpreted as a very large unsigned integer making the assertion always fail.
PoC
@external
def foo():
x:int256 = min_value(int256)
# revert when it should not since we have the following assertion that fails:
# [assert, [le, min_value(int256), max_value(int256) + 1 - 10]],
for i in range(x, x + 10):
pass
Patches
patched in v0.4.0, specifically, #3679 disallows this form of range()
.
Impact
Any contract having a range(start, start + N)
where start
is a signed integer with the possibility for start
to be negative is affected. If a call goes through the loop while supplying a negative start
the execution will revert.
Summary
When looping over a
range
of the formrange(start, start + N)
, ifstart
is negative, the execution will always revert.Details
This issue is caused by an incorrect assertion inserted by the code generation of the range (
stmt.parse_For_range()
):vyper/vyper/codegen/stmt.py
Lines 286 to 287 in 9136169
This assertion was introduced in 3de1415 to fix GHSA-6r8q-pfpv-7cgj. The issue arises when
start
is signed, instead of usingsle
,le
is used andstart
is interpreted as an unsigned integer for the comparison. If it is a negative number, its 255th bit is set to1
and is hence interpreted as a very large unsigned integer making the assertion always fail.PoC
Patches
patched in v0.4.0, specifically, #3679 disallows this form of
range()
.Impact
Any contract having a
range(start, start + N)
wherestart
is a signed integer with the possibility forstart
to be negative is affected. If a call goes through the loop while supplying a negativestart
the execution will revert.