Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Loop Iterator Overflow Signed Type #3963

Closed
cyberthirst opened this issue Apr 19, 2024 · 2 comments
Closed

Loop Iterator Overflow Signed Type #3963

cyberthirst opened this issue Apr 19, 2024 · 2 comments

Comments

@cyberthirst
Copy link
Collaborator

Version Information

  • 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

credits: @trocher

@charles-cooper
Copy link
Member

this was fixed in b4429cf right?

def test_for_range_signed_int_overflow(get_contract, tx_failed):
code = """
@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
"""
c = get_contract(code)
with tx_failed():
c.foo()

@charles-cooper
Copy link
Member

charles-cooper commented Apr 22, 2024

confirmed with @trocher, fixed in #3814

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants