Skip to content

Ignored loop range bounds

Moderate
hedgar2017 published GHSA-8j77-7rrv-6pxx Aug 13, 2024

Package

zkvyper (Vyper)

Affected versions

>=1.3.12, <1.5.3

Patched versions

1.5.3

Description

Impact

The bound parameter of loop ranges in Vyper v0.3.10 and newer is ignored, as it is represented by a previously unused parameter of the LLL repeat instruction.
In the example below, bound is supposed to break the loop if stop >= 2, allowing to use variables in Vyper as a Turing-incomplete language.

@external
def foo(stop: uint256) -> uint256:
    x: uint256 = 0
    for i:uint256 in range(stop, bound = 2):
        x = i
    return x

Since LLL IR has no Turing-incompletness restrictions, it is compiled to a loop with a much more late exit condition. It leads to a loss of funds or other unwanted behavior if the loop body contains it.

However, more real-life use cases like iterating over an array are not affected. For instance, in the example below, an array length constant is used, which is less or equal to the constant provided as bound.

my_array: DynArray[uint256, MAX_LEN]
for i: uint256 in range(len(my_array), bound=MAX_LEN):
    ...

No contracts were affected, but some of them had patterns similar to the 2nd example.

Patches

Fixed in version 1.5.3.

Workarounds

Upgrading and redeploying affected contracts is the only way.

Severity

Moderate

CVE ID

CVE-2024-43366

Weaknesses

No CWEs

Credits