fold binary expressions with constant operands for fuzzing guidance

pull/1508/head
alpharush 2 years ago
parent 5314d7653a
commit 74122a6bd6
  1. 9
      slither/core/expressions/literal.py
  2. 6
      slither/printers/guidance/echidna.py
  3. 25
      slither/visitors/expression/constants_folding.py

@ -20,6 +20,13 @@ class Literal(Expression):
def value(self) -> Union[int, str]: def value(self) -> Union[int, str]:
return self._value return self._value
@property
def converted_value(self) -> int:
"""Return the value of the literal, accounting for subdenomination e.g. ether"""
if self.subdenomination:
return convert_subdenomination(self._value, self.subdenomination)
return self._value
@property @property
def type(self) -> "Type": def type(self) -> "Type":
return self._type return self._type
@ -30,7 +37,7 @@ class Literal(Expression):
def __str__(self): def __str__(self):
if self.subdenomination: if self.subdenomination:
return str(convert_subdenomination(self._value, self.subdenomination)) return str(self.converted_value)
if self.type in Int + Uint + Fixed + Ufixed + ["address"]: if self.type in Int + Uint + Fixed + Ufixed + ["address"]:
return str(convert_string_to_int(self._value)) return str(convert_string_to_int(self._value))

@ -30,6 +30,7 @@ from slither.slithir.operations import (
) )
from slither.slithir.operations.binary import Binary from slither.slithir.operations.binary import Binary
from slither.slithir.variables import Constant from slither.slithir.variables import Constant
from slither.visitors.expression.constants_folding import ConstantFolding
def _get_name(f: Union[Function, Variable]) -> str: def _get_name(f: Union[Function, Variable]) -> str:
@ -175,6 +176,11 @@ def _extract_constants_from_irs( # pylint: disable=too-many-branches,too-many-n
all_cst_used_in_binary[str(ir.type)].append( all_cst_used_in_binary[str(ir.type)].append(
ConstantValue(str(r.value), str(r.type)) ConstantValue(str(r.value), str(r.type))
) )
if isinstance(ir.variable_left, Constant) and isinstance(ir.variable_right, Constant):
if ir.lvalue:
type_ = ir.lvalue.type
cst = ConstantFolding(ir.expression, type_).result()
all_cst_used.append(ConstantValue(str(cst.value), str(type_)))
if isinstance(ir, TypeConversion): if isinstance(ir, TypeConversion):
if isinstance(ir.variable, Constant): if isinstance(ir.variable, Constant):
all_cst_used.append(ConstantValue(str(ir.variable.value), str(ir.type))) all_cst_used.append(ConstantValue(str(ir.variable.value), str(ir.type)))

@ -1,4 +1,11 @@
from slither.core.expressions import BinaryOperationType, Literal, UnaryOperationType from slither.core.expressions import (
BinaryOperationType,
Literal,
UnaryOperationType,
Identifier,
BinaryOperation,
UnaryOperation,
)
from slither.utils.integer_conversion import convert_string_to_fraction, convert_string_to_int from slither.utils.integer_conversion import convert_string_to_fraction, convert_string_to_int
from slither.visitors.expression.expression import ExpressionVisitor from slither.visitors.expression.expression import ExpressionVisitor
@ -29,7 +36,7 @@ class ConstantFolding(ExpressionVisitor):
def result(self): def result(self):
return Literal(int(get_val(self._expression)), self._type) return Literal(int(get_val(self._expression)), self._type)
def _post_identifier(self, expression): def _post_identifier(self, expression: Identifier):
if not expression.value.is_constant: if not expression.value.is_constant:
raise NotConstant raise NotConstant
expr = expression.value.expression expr = expression.value.expression
@ -37,9 +44,9 @@ class ConstantFolding(ExpressionVisitor):
if not isinstance(expr, Literal): if not isinstance(expr, Literal):
cf = ConstantFolding(expr, self._type) cf = ConstantFolding(expr, self._type)
expr = cf.result() expr = cf.result()
set_val(expression, convert_string_to_int(expr.value)) set_val(expression, convert_string_to_int(expr.converted_value))
def _post_binary_operation(self, expression): def _post_binary_operation(self, expression: BinaryOperation):
left = get_val(expression.expression_left) left = get_val(expression.expression_left)
right = get_val(expression.expression_right) right = get_val(expression.expression_right)
if expression.type == BinaryOperationType.POWER: if expression.type == BinaryOperationType.POWER:
@ -64,7 +71,7 @@ class ConstantFolding(ExpressionVisitor):
else: else:
raise NotConstant raise NotConstant
def _post_unary_operation(self, expression): def _post_unary_operation(self, expression: UnaryOperation):
# Case of uint a = -7; uint[-a] arr; # Case of uint a = -7; uint[-a] arr;
if expression.type == UnaryOperationType.MINUS_PRE: if expression.type == UnaryOperationType.MINUS_PRE:
expr = expression.expression expr = expression.expression
@ -72,13 +79,13 @@ class ConstantFolding(ExpressionVisitor):
cf = ConstantFolding(expr, self._type) cf = ConstantFolding(expr, self._type)
expr = cf.result() expr = cf.result()
assert isinstance(expr, Literal) assert isinstance(expr, Literal)
set_val(expression, -convert_string_to_fraction(expr.value)) set_val(expression, -convert_string_to_fraction(expr.converted_value))
else: else:
raise NotConstant raise NotConstant
def _post_literal(self, expression): def _post_literal(self, expression: Literal):
try: try:
set_val(expression, convert_string_to_fraction(expression.value)) set_val(expression, convert_string_to_fraction(expression.converted_value))
except ValueError as e: except ValueError as e:
raise NotConstant from e raise NotConstant from e
@ -115,7 +122,7 @@ class ConstantFolding(ExpressionVisitor):
cf = ConstantFolding(expression.expressions[0], self._type) cf = ConstantFolding(expression.expressions[0], self._type)
expr = cf.result() expr = cf.result()
assert isinstance(expr, Literal) assert isinstance(expr, Literal)
set_val(expression, convert_string_to_fraction(expr.value)) set_val(expression, convert_string_to_fraction(expr.converted_value))
return return
raise NotConstant raise NotConstant

Loading…
Cancel
Save