vyper Version (output of vyper --version): commit 4b4e188ba83d28b5dd6ff66479e7448e5b925030
Issue description
When a bound is specified, the range() built-in checks at runtime
that ["assert", [le, start, end]]. However, if the type of the loop
iterator, is a signed integer, the check is not always correct as le
here performs an unsigned integer comparison and not a signed one. This
means that:
If the iterator type is int256 it is possible to overflow 256 bits
while looping if end is negative and start is positive.
POC
For example, calling the function foo in the following contract
returns
[57896044618658097711785492504343953926634992332820282019728792003956564819967, -57896044618658097711785492504343953926634992332820282019728792003956564819968, -57896044618658097711785492504343953926634992332820282019728792003956564819967]
@external
def foo() -> DynArray[int256, 10]:
res: DynArray[int256, 10] = empty(DynArray[int256, 10])
x:int256 = max_value(int256)
y:int256 = min_value(int256)+2
for i:int256 in range(x,y , bound=10):
res.append(i)
return res
Version Information
vyper --version
): commit4b4e188ba83d28b5dd6ff66479e7448e5b925030
Issue description
When a
bound
is specified, therange()
built-in checks at runtime that["assert", [le, start, end]]
. However, if the type of the loop iterator, is a signed integer, the check is not always correct asle
here performs an unsigned integer comparison and not a signed one. This means that:If the iterator type is
int256
it is possible to overflow 256 bits while looping ifend
is negative andstart
is positive.POC
For example, calling the function
foo
in the following contract returns[57896044618658097711785492504343953926634992332820282019728792003956564819967, -57896044618658097711785492504343953926634992332820282019728792003956564819968, -57896044618658097711785492504343953926634992332820282019728792003956564819967]
credits: @trocher