Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Improve constant folding #830

Merged
merged 3 commits into from
Apr 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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