mirror of https://github.com/crytic/slither
Add constant folding visitor (fix #144)
parent
21579edef4
commit
6c2923f254
@ -0,0 +1,104 @@ |
||||
import logging |
||||
|
||||
from .expression import ExpressionVisitor |
||||
from slither.core.expressions import BinaryOperationType, Literal |
||||
|
||||
class NotConstant(Exception): |
||||
pass |
||||
|
||||
|
||||
KEY = 'ConstantFolding' |
||||
|
||||
def get_val(expression): |
||||
val = expression.context[KEY] |
||||
# we delete the item to reduce memory use |
||||
del expression.context[KEY] |
||||
return val |
||||
|
||||
def set_val(expression, val): |
||||
expression.context[KEY] = val |
||||
|
||||
class ConstantFolding(ExpressionVisitor): |
||||
|
||||
def result(self): |
||||
return Literal(int(get_val(self._expression))) |
||||
|
||||
def _post_identifier(self, expression): |
||||
if not expression.value.is_constant: |
||||
raise NotConstant |
||||
expr = expression.value.expression |
||||
# assumption that we won't have infinite loop |
||||
if not isinstance(expr, Literal): |
||||
cf = ConstantFolding(expr) |
||||
expr = cf.result() |
||||
set_val(expression, int(expr.value)) |
||||
|
||||
def _post_binary_operation(self, expression): |
||||
left = get_val(expression.expression_left) |
||||
right = get_val(expression.expression_right) |
||||
if expression.type == BinaryOperationType.POWER: |
||||
set_val(expression, left ** right) |
||||
elif expression.type == BinaryOperationType.MULTIPLICATION: |
||||
set_val(expression, left * right) |
||||
elif expression.type == BinaryOperationType.DIVISION: |
||||
set_val(expression, left / right) |
||||
elif expression.type == BinaryOperationType.MODULO: |
||||
set_val(expression, left % right) |
||||
elif expression.type == BinaryOperationType.ADDITION: |
||||
set_val(expression, left + right) |
||||
elif expression.type == BinaryOperationType.SUBTRACTION: |
||||
if(left-right) <0: |
||||
# Could trigger underflow |
||||
raise NotConstant |
||||
set_val(expression, left - right) |
||||
elif expression.type == BinaryOperationType.LEFT_SHIFT: |
||||
set_val(expression, left << right) |
||||
elif expression.type == BinaryOperationType.RIGHT_SHIFT: |
||||
set_val(expression, left >> right) |
||||
else: |
||||
raise NotConstant |
||||
|
||||
def _post_unary_operation(self, expression): |
||||
raise NotConstant |
||||
|
||||
def _post_literal(self, expression): |
||||
if expression.value.isdigit(): |
||||
set_val(expression, int(expression.value)) |
||||
else: |
||||
raise NotConstant |
||||
|
||||
def _post_assignement_operation(self, expression): |
||||
raise NotConstant |
||||
|
||||
def _post_call_expression(self, expression): |
||||
raise NotConstant |
||||
|
||||
def _post_conditional_expression(self, expression): |
||||
raise NotConstant |
||||
|
||||
def _post_elementary_type_name_expression(self, expression): |
||||
raise NotConstant |
||||
|
||||
def _post_index_access(self, expression): |
||||
raise NotConstant |
||||
|
||||
def _post_member_access(self, expression): |
||||
raise NotConstant |
||||
|
||||
def _post_new_array(self, expression): |
||||
raise NotConstant |
||||
|
||||
def _post_new_contract(self, expression): |
||||
raise NotConstant |
||||
|
||||
def _post_new_elementary_type(self, expression): |
||||
raise NotConstant |
||||
|
||||
def _post_tuple_expression(self, expression): |
||||
raise NotConstant |
||||
|
||||
def _post_type_conversion(self, expression): |
||||
raise NotConstant |
||||
|
||||
|
||||
|
Loading…
Reference in new issue