diff --git a/slither/slithir/variables/constant.py b/slither/slithir/variables/constant.py index ba4f320f2..44f3df855 100644 --- a/slither/slithir/variables/constant.py +++ b/slither/slithir/variables/constant.py @@ -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 @@ -25,26 +25,7 @@ class Constant(SlithIRVariable): 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: diff --git a/slither/utils/integer_conversion.py b/slither/utils/integer_conversion.py new file mode 100644 index 000000000..27e973086 --- /dev/null +++ b/slither/utils/integer_conversion.py @@ -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)) diff --git a/slither/visitors/expression/constants_folding.py b/slither/visitors/expression/constants_folding.py index 018110f25..23de9fa89 100644 --- a/slither/visitors/expression/constants_folding.py +++ b/slither/visitors/expression/constants_folding.py @@ -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 @@ -36,7 +37,7 @@ class ConstantFolding(ExpressionVisitor): 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)