mirror of https://github.com/crytic/slither
parent
36eda1b3cb
commit
67b95dff74
@ -0,0 +1,38 @@ |
||||
from typing import Dict |
||||
from slither.slithir.operations import Binary, BinaryType |
||||
from slither.formatters.utils.patches import create_patch |
||||
from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass |
||||
|
||||
arithmetic_operators = [ |
||||
BinaryType.ADDITION, |
||||
BinaryType.DIVISION, |
||||
BinaryType.MULTIPLICATION, |
||||
BinaryType.SUBTRACTION, |
||||
BinaryType.MODULO |
||||
] |
||||
|
||||
class AOR(AbstractMutator): # pylint: disable=too-few-public-methods |
||||
NAME = "AOR" |
||||
HELP = "Arithmetic operator replacement" |
||||
FAULTCLASS = FaultClass.Checking |
||||
FAULTNATURE = FaultNature.Missing |
||||
|
||||
def _mutate(self) -> Dict: |
||||
result: Dict = {} |
||||
|
||||
for function in self.contract.functions_and_modifiers_declared: |
||||
for node in function.nodes: |
||||
for ir in node.irs: |
||||
if isinstance(ir, Binary) and ir.type in arithmetic_operators: |
||||
alternative_ops = arithmetic_operators[:] |
||||
alternative_ops.remove(ir.type) |
||||
for op in alternative_ops: |
||||
# Get the string |
||||
start = node.source_mapping.start |
||||
stop = start + node.source_mapping.length |
||||
old_str = self.in_file_str[start:stop] |
||||
line_no = node.source_mapping.lines |
||||
# Replace the expression with true |
||||
new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" |
||||
create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) |
||||
return result |
@ -0,0 +1,50 @@ |
||||
from typing import Dict |
||||
from slither.slithir.operations import Binary, BinaryType |
||||
from slither.formatters.utils.patches import create_patch |
||||
from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass |
||||
from slither.core.expressions.assignment_operation import AssignmentOperationType, AssignmentOperation |
||||
|
||||
assignment_operators = [ |
||||
AssignmentOperationType.ASSIGN_ADDITION, |
||||
AssignmentOperationType.ASSIGN_SUBTRACTION, |
||||
AssignmentOperationType.ASSIGN, |
||||
AssignmentOperationType.ASSIGN_OR, |
||||
AssignmentOperationType.ASSIGN_CARET, |
||||
AssignmentOperationType.ASSIGN_AND, |
||||
AssignmentOperationType.ASSIGN_LEFT_SHIFT, |
||||
AssignmentOperationType.ASSIGN_RIGHT_SHIFT, |
||||
AssignmentOperationType.ASSIGN_MULTIPLICATION, |
||||
AssignmentOperationType.ASSIGN_DIVISION, |
||||
AssignmentOperationType.ASSIGN_MODULO |
||||
] |
||||
|
||||
class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods |
||||
NAME = "ASOR" |
||||
HELP = "Assignment Operator Replacement" |
||||
FAULTCLASS = FaultClass.Checking |
||||
FAULTNATURE = FaultNature.Missing |
||||
|
||||
def _mutate(self) -> Dict: |
||||
result: Dict = {} |
||||
|
||||
for function in self.contract.functions_and_modifiers_declared: |
||||
for node in function.nodes: |
||||
for ir in node.irs: |
||||
if isinstance(ir.expression, AssignmentOperation) and ir.expression.type in assignment_operators: |
||||
if ir.expression.type == AssignmentOperationType.ASSIGN: |
||||
continue |
||||
alternative_ops = assignment_operators[:] |
||||
try: |
||||
alternative_ops.remove(ir.expression.type) |
||||
except: |
||||
continue |
||||
for op in assignment_operators: |
||||
if op != ir.expression: |
||||
start = node.source_mapping.start |
||||
stop = start + node.source_mapping.length |
||||
old_str = self.in_file_str[start:stop] |
||||
line_no = node.source_mapping.lines |
||||
# Replace the expression with true |
||||
new_str = f"{old_str.split(str(ir.expression.type))[0]}{op}{old_str.split(str(ir.expression.type))[1]}" |
||||
create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) |
||||
return result |
@ -0,0 +1,35 @@ |
||||
from typing import Dict |
||||
from slither.slithir.operations import Binary, BinaryType |
||||
from slither.formatters.utils.patches import create_patch |
||||
from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass |
||||
|
||||
bitwise_operators = [ |
||||
BinaryType.AND, |
||||
BinaryType.OR |
||||
] |
||||
|
||||
class BOR(AbstractMutator): # pylint: disable=too-few-public-methods |
||||
NAME = "BOR" |
||||
HELP = "Bitwise Operator Replacement" |
||||
FAULTCLASS = FaultClass.Checking |
||||
FAULTNATURE = FaultNature.Missing |
||||
|
||||
def _mutate(self) -> Dict: |
||||
result: Dict = {} |
||||
|
||||
for function in self.contract.functions_and_modifiers_declared: |
||||
for node in function.nodes: |
||||
for ir in node.irs: |
||||
if isinstance(ir, Binary) and ir.type in bitwise_operators: |
||||
alternative_ops = bitwise_operators[:] |
||||
alternative_ops.remove(ir.type) |
||||
for op in alternative_ops: |
||||
# Get the string |
||||
start = node.source_mapping.start |
||||
stop = start + node.source_mapping.length |
||||
old_str = self.in_file_str[start:stop] |
||||
line_no = node.source_mapping.lines |
||||
# Replace the expression with true |
||||
new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" |
||||
create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) |
||||
return result |
@ -0,0 +1,34 @@ |
||||
from typing import Dict |
||||
from slither.core.cfg.node import NodeType |
||||
from slither.formatters.utils.patches import create_patch |
||||
from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass |
||||
from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation |
||||
|
||||
class MWA(AbstractMutator): # pylint: disable=too-few-public-methods |
||||
NAME = "MIA" |
||||
HELP = '"while" construct around statement' |
||||
FAULTCLASS = FaultClass.Checking |
||||
FAULTNATURE = FaultNature.Missing |
||||
|
||||
def _mutate(self) -> Dict: |
||||
result: Dict = {} |
||||
|
||||
for function in self.contract.functions_and_modifiers_declared: |
||||
for node in function.nodes: |
||||
if node.type == NodeType.IFLOOP: |
||||
# Get the string |
||||
start = node.source_mapping.start |
||||
stop = start + node.source_mapping.length |
||||
old_str = self.in_file_str[start:stop] |
||||
line_no = node.source_mapping.lines |
||||
|
||||
if not isinstance(node.expression, UnaryOperation): |
||||
new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' |
||||
create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) |
||||
return result |
||||
|
||||
|
||||
|
||||
# limitations - won't work if it is tenary operation |
||||
|
||||
|
@ -1,9 +1,13 @@ |
||||
# pylint: disable=unused-import |
||||
# from slither.tools.mutator.mutators.MVIV import MVIV |
||||
# from slither.tools.mutator.mutators.MVIE import MVIE |
||||
# from slither.tools.mutator.mutators.MIA import MIA |
||||
from slither.tools.mutator.mutators.MVIV import MVIV |
||||
from slither.tools.mutator.mutators.MVIE import MVIE |
||||
from slither.tools.mutator.mutators.MIA import MIA |
||||
from slither.tools.mutator.mutators.ROR import ROR |
||||
# from slither.tools.mutator.mutators.LOR import LOR |
||||
# from slither.tools.mutator.mutators.UOI import UOI |
||||
# from slither.tools.mutator.mutators.SBR import SBR |
||||
from slither.tools.mutator.mutators.LOR import LOR |
||||
from slither.tools.mutator.mutators.UOI import UOI |
||||
from slither.tools.mutator.mutators.SBR import SBR |
||||
from slither.tools.mutator.mutators.AOR import AOR |
||||
from slither.tools.mutator.mutators.BOR import BOR |
||||
from slither.tools.mutator.mutators.ASOR import ASOR |
||||
from slither.tools.mutator.mutators.MWA import MWA |
||||
|
||||
|
@ -1,40 +0,0 @@ |
||||
from typing import Dict |
||||
import os |
||||
|
||||
from slither.core.declarations import Contract |
||||
from slither.core.variables.variable import Variable |
||||
from slither.formatters.utils.patches import create_patch |
||||
from slither.tools.mutator.utils.testing_generated_mutant import compile_generated_mutant, run_test_suite |
||||
from slither.tools.mutator.utils.replace_conditions import replace_string_in_source_file |
||||
from slither.tools.mutator.utils.file_handling import create_mutant_file |
||||
|
||||
def remove_assignement(variable: Variable, contract: Contract, result: Dict) -> bool: |
||||
""" |
||||
Remove the variable's initial assignement |
||||
|
||||
:param variable: |
||||
:param contract: |
||||
:param result: |
||||
:return: |
||||
""" |
||||
# Retrieve the file |
||||
in_file = contract.source_mapping.filename.absolute |
||||
# Retrieve the source code |
||||
in_file_str = contract.compilation_unit.core.source_code[in_file] |
||||
|
||||
# Get the string |
||||
start = variable.source_mapping.start |
||||
stop = variable.expression.source_mapping.start |
||||
old_str = in_file_str[start:stop] |
||||
|
||||
new_str = old_str[: old_str.find("=")] |
||||
line_no = [0] |
||||
create_patch( |
||||
result, |
||||
in_file, |
||||
start, |
||||
stop + variable.expression.source_mapping.length, |
||||
old_str, |
||||
new_str, |
||||
line_no |
||||
) |
@ -1,48 +0,0 @@ |
||||
import logging |
||||
import re |
||||
|
||||
logger = logging.getLogger("Slither-Mutate") |
||||
|
||||
# function to replace the string |
||||
def replace_string_in_source_file(file_path: str, old_string: str, new_string: str) -> None: |
||||
try: |
||||
# Read the content of the Solidity file |
||||
with open(file_path, 'r') as file: |
||||
content = file.read() |
||||
|
||||
# Perform the string replacement |
||||
modified_content = content.replace(old_string, new_string) |
||||
|
||||
# Write the modified content back to the file |
||||
with open(file_path, 'w') as file: |
||||
file.write(modified_content) |
||||
|
||||
logger.info(f"String '{old_string}' replaced with '{new_string}' in '{file_path}'.") |
||||
except Exception as e: |
||||
logger.error(f"Error replacing string: {e}") |
||||
|
||||
# function to replace the string in a specific line |
||||
def replace_string_in_source_file_specific_line(file_path: str, old_string: str, new_string: str, line_number : int) -> None: |
||||
try: |
||||
# Read the content of the Solidity file |
||||
with open(file_path, 'r') as file: |
||||
lines = file.readlines() |
||||
|
||||
if 1 <= line_number <= len(lines): |
||||
# remove the spaces in the string |
||||
line = lines[line_number - 1].replace(" ", "") |
||||
old_string = old_string.replace(" ", "") |
||||
|
||||
# Replace the old string with the new string on the specified line |
||||
lines[line_number - 1] = line.replace(old_string.strip(), new_string) |
||||
|
||||
# Write the modified content back to the file |
||||
with open(file_path, 'w') as file: |
||||
file.writelines(lines) |
||||
|
||||
logger.info(f"String '{old_string}' replaced with '{new_string}' in '{file_path}'.' at '{line_number}") |
||||
else: |
||||
logger.error(f'Error: Line number {line_number} is out of range') |
||||
|
||||
except Exception as e: |
||||
logger.erro(f'Error: {e}') |
Loading…
Reference in new issue