Skip to content

Commit 4595938

Browse files
fix[ux]: fix compiler hang for large exponentiations (#3893)
this commit fixes a UX bug where the compiler would hang while trying to constant-fold large exponentiations. it does a loose check to see if the output would be vastly out of bounds and fails fast if so.
1 parent 1a40e93 commit 4595938

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

tests/functional/codegen/types/numbers/test_exponents.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
33
from hypothesis import strategies as st
44

55
from vyper.codegen.arithmetic import calculate_largest_base, calculate_largest_power
6+
from vyper.compiler import compile_code
7+
from vyper.exceptions import InvalidLiteral
8+
9+
10+
def test_compiler_hang():
11+
code = """
12+
@external
13+
def f0():
14+
lv0: uint256 = max_value(int128) ** max_value(int128)
15+
"""
16+
with pytest.raises(InvalidLiteral):
17+
compile_code(code)
618

719

820
@pytest.mark.fuzzing

vyper/ast/nodes.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import copy
44
import decimal
55
import functools
6+
import math
67
import operator
78
import pickle
89
import sys
@@ -1080,6 +1081,15 @@ def _op(self, left, right):
10801081
raise TypeMismatch("Cannot perform exponentiation on decimal values.", self._parent)
10811082
if right < 0:
10821083
raise InvalidOperation("Cannot calculate a negative power", self._parent)
1084+
# prevent a compiler hang. we are ok with false positives at this
1085+
# stage since we are just trying to filter out inputs which can cause
1086+
# the compiler to hang. the others will get caught during constant
1087+
# folding or codegen.
1088+
# l**r > 2**256
1089+
# r * ln(l) > ln(2 ** 256)
1090+
# r > ln(2 ** 256) / ln(l)
1091+
if right > math.log(decimal.Decimal(2**257)) / math.log(decimal.Decimal(left)):
1092+
raise InvalidLiteral("Out of bounds", self)
10831093
return int(left**right)
10841094

10851095

0 commit comments

Comments
 (0)