Skip to content

Commit

Permalink
Merge pull request #830 from crytic/dev-constant-folding-fix
Browse files Browse the repository at this point in the history
Improve constant folding
  • Loading branch information
montyly authored Apr 22, 2021
2 parents eabdd9e + 6c081fe commit fa04fb6
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 24 deletions.
27 changes: 4 additions & 23 deletions slither/slithir/variables/constant.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from functools import total_ordering
from decimal import Decimal
from functools import total_ordering

from slither.slithir.variables.variable import SlithIRVariable
from slither.slithir.exceptions import SlithIRError
from slither.core.solidity_types.elementary_type import ElementaryType, Int, Uint
from slither.slithir.variables.variable import SlithIRVariable
from slither.utils.arithmetic import convert_subdenomination
from slither.utils.integer_conversion import convert_string_to_int


@total_ordering
Expand All @@ -25,26 +25,7 @@ def __init__(
assert isinstance(constant_type, ElementaryType)
self._type = constant_type
if constant_type.type in Int + Uint + ["address"]:
if val.startswith("0x") or val.startswith("0X"):
self._val = int(val, 16)
else:
if "e" in val or "E" in val:
base, expo = val.split("e") if "e" in val else val.split("E")
base, expo = Decimal(base), int(expo)
# The resulting number must be < 2**256-1, otherwise solc
# Would not be able to compile it
# 10**77 is the largest exponent that fits
# See https://github.com/ethereum/solidity/blob/9e61f92bd4d19b430cb8cb26f1c7cf79f1dff380/libsolidity/ast/Types.cpp#L1281-L1290
if expo > 77:
if base != Decimal(0):
raise SlithIRError(
f"{base}e{expo} is too large to fit in any Solidity integer size"
)
self._val = 0
else:
self._val = int(Decimal(base) * Decimal(10 ** expo))
else:
self._val = int(Decimal(val))
self._val = convert_string_to_int(val)
elif constant_type.type == "bool":
self._val = (val == "true") | (val == "True")
else:
Expand Down
25 changes: 25 additions & 0 deletions slither/utils/integer_conversion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from decimal import Decimal

from slither.exceptions import SlitherError


def convert_string_to_int(val: str) -> int:
if val.startswith("0x") or val.startswith("0X"):
return int(val, 16)

if "e" in val or "E" in val:
base, expo = val.split("e") if "e" in val else val.split("E")
base, expo = Decimal(base), int(expo)
# The resulting number must be < 2**256-1, otherwise solc
# Would not be able to compile it
# 10**77 is the largest exponent that fits
# See https://github.com/ethereum/solidity/blob/9e61f92bd4d19b430cb8cb26f1c7cf79f1dff380/libsolidity/ast/Types.cpp#L1281-L1290
if expo > 77:
if base != Decimal(0):
raise SlitherError(
f"{base}e{expo} is too large to fit in any Solidity integer size"
)
return 0
return int(Decimal(base) * Decimal(10 ** expo))

return int(Decimal(val))
3 changes: 2 additions & 1 deletion slither/visitors/expression/constants_folding.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from slither.core.expressions import BinaryOperationType, Literal
from slither.utils.integer_conversion import convert_string_to_int
from slither.visitors.expression.expression import ExpressionVisitor


Expand Down Expand Up @@ -36,7 +37,7 @@ def _post_identifier(self, expression):
if not isinstance(expr, Literal):
cf = ConstantFolding(expr, self._type)
expr = cf.result()
set_val(expression, int(expr.value))
set_val(expression, convert_string_to_int(expr.value))

def _post_binary_operation(self, expression):
left = get_val(expression.expression_left)
Expand Down

0 comments on commit fa04fb6

Please sign in to comment.