Skip to content

Commit

Permalink
Fix for dynamic array operations
Browse files Browse the repository at this point in the history
  • Loading branch information
smonicas committed Jun 14, 2024
1 parent 02df0dc commit 48fc49a
Showing 1 changed file with 38 additions and 1 deletion.
39 changes: 38 additions & 1 deletion slither/tools/mutator/mutators/AOR.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
from slither.slithir.operations import Binary, BinaryType
from slither.tools.mutator.utils.patch import create_patch_with_line
from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator
from slither.core.variables.variable import Variable
from slither.core.expressions.unary_operation import UnaryOperation
from slither.core.expressions.call_expression import CallExpression
from slither.core.expressions.member_access import MemberAccess
from slither.core.expressions.identifier import Identifier
from slither.core.solidity_types.array_type import ArrayType

arithmetic_operators = [
BinaryType.ADDITION,
Expand All @@ -27,7 +32,39 @@ def _mutate(self) -> Dict:
ir_expression = node.expression
except: # pylint: disable=bare-except
continue
for ir in node.irs:

# Special cases handling .push and .pop on dynamic arrays.
# The IR for these operations has a binary operation due to internal conversion
# (see convert_to_push and convert_to_pop in slithir/convert.py)
# however it's not present in the source code and should not be mutated.
# pylint: disable=too-many-boolean-expressions
if (
isinstance(ir_expression, CallExpression)
and isinstance(ir_expression.called, MemberAccess)
and ir_expression.called.member_name == "pop"
and isinstance(ir_expression.called.expression, Identifier)
and isinstance(ir_expression.called.expression.value, Variable)
and isinstance(ir_expression.called.expression.value.type, ArrayType)
):
continue

# For a .push instruction we skip the last 6 IR operations
# because they are fixed based on the internal conversion to the IR
# while we need to look at the preceding instructions because
# they might contain Binary IR to be mutated.
# For example for a.push(3+x) it's correct to mutate 3+x.
irs = (
node.irs[:-6]
if isinstance(ir_expression, CallExpression)
and isinstance(ir_expression.called, MemberAccess)
and ir_expression.called.member_name == "push"
and isinstance(ir_expression.called.expression, Identifier)
and isinstance(ir_expression.called.expression.value, Variable)
and isinstance(ir_expression.called.expression.value.type, ArrayType)
else node.irs
)

for ir in irs:
if isinstance(ir, Binary) and ir.type in arithmetic_operators:
if isinstance(ir_expression, UnaryOperation):
continue
Expand Down

0 comments on commit 48fc49a

Please sign in to comment.