low

crash due to shadowing iterator vars

Reward

Total

455.95 USDC

Selected
455.95 USDC
Selected Submission

crash due to shadowing iterator vars

Severity

Low Risk

Relevant GitHub Links

https://github.com/vyperlang/vyper/blob/3b310d5292c4d1448e673d7b3adb223f9353260e/vyper/ir/compile_ir.py#L434-L436

Summary

The compiler crashes with valid input programs containing sqrt due to vyper.exceptions.CompilerPanic: shadowed loop variable range_ix0.

Vulnerability Details

The sqrt function's IR is generated via generate_inline_function which uses a new namespace and context. Additionally, the function's implementation contains a for loop.

The for loop present in the body generates a new fresh iterator variable: range_ix0 independently of the previous contexts. As a result, if there is a call to sqrt inside a for loop, then there will be a name clash of the iterator variables.

The following assert will not pass and the compiler will crash: https://github.com/vyperlang/vyper/blob/3b310d5292c4d1448e673d7b3adb223f9353260e/vyper/ir/compile_ir.py#L434-L436

PoC

Here is a simple contract triggering the bug:

#@version ^0.3.9

@external
def my_little_test() -> decimal:
    j: decimal = 0.0
    for i in range(666):
        j = sqrt(2.0)
    return j

Also contracts like this won't compile:

@external
def my_little_test() -> decimal:
    j: decimal = sqrt(sqrt(666.0))
    return j

Impact

Some valid programs aren't possible to compile. As such developers are forced to code different (and maybe untransparent) contracts to avoid the bug.

Tools Used

Manual review.

Recommendations

Implement the function as other built-ins via manual IR construction.