Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions mythril/disassembler/disassembly.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""This module contains the class used to represent disassembly code."""

from ast import literal_eval
from typing import Dict, List, Tuple

from mythril.disassembler import asm
from mythril.ethereum import util
from mythril.support.signatures import SignatureDB
from mythril.support.support_args import args


class Disassembly(object):
Expand Down Expand Up @@ -42,11 +44,26 @@ def assign_bytecode(self, bytecode):
jump_table_indices = asm.find_op_code_sequence(
[("PUSH1", "PUSH2", "PUSH3", "PUSH4"), ("EQ",)], self.instruction_list
)
ignore_false_funcs = args.ignore_false_funcs
if ignore_false_funcs is None:
ignore_false_funcs = [1, 2, 3, 4]

for index in jump_table_indices:
# ignore the default func hashes if ignore_false_funcs is None
argument = self.instruction_list[index]["argument"]
if isinstance(argument, str):
function_hash = literal_eval(argument)
if function_hash in ignore_false_funcs:
continue
elif isinstance(argument, tuple):
function_hash = int.from_bytes(bytes(argument), "big")
if function_hash in ignore_false_funcs:
continue

function_hash, jump_target, function_name = get_function_info(
index, self.instruction_list, signatures
)

self.func_hashes.append(function_hash)
if jump_target is not None and function_name is not None:
self.function_name_to_address[function_name] = jump_target
Expand Down
20 changes: 20 additions & 0 deletions mythril/interfaces/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from mythril.laser.ethereum.transaction.symbolic import ACTORS
from mythril.mythril import MythrilAnalyzer, MythrilConfig, MythrilDisassembler
from mythril.plugin.loader import MythrilPluginLoader
from mythril.support.support_args import args as support_args

# Initialise core Mythril Component
_ = MythrilPluginLoader()
Expand Down Expand Up @@ -470,6 +471,13 @@ def add_analysis_args(options):
"Like [[func_hash1, func_hash2], [func_hash2, func_hash3]] where the first transaction is constrained "
"with func_hash1 and func_hash2, and the second tx is constrained with func_hash2 and func_hash3. Use -1 as a proxy for fallback() function and -2 for receive() function.",
)
options.add_argument(
"--ignore-false-funcs",
type=str,
default=None,
help="List of function signatures that should be ignored as false positives."
"usage: --ignore-false-funcs [func1, func2, ...]",
)
options.add_argument(
"--beam-search",
type=int,
Expand Down Expand Up @@ -662,6 +670,17 @@ def validate_args(args: Namespace):
if len(args.transaction_sequences) != args.transaction_count:
args.transaction_count = len(args.transaction_sequences)

if getattr(args, "ignore_false_funcs", None):
try:
args.ignore_false_funcs = literal_eval(str(args.ignore_false_funcs))
except ValueError:
exit_with_error(
args.outform,
"The ignore false functions are in incorrect format, It should be "
"[func1, func2, ...]. The default ignore false functions are "
"[0x00000001, 0x00000002, 0x00000003, 0x00000004]",
)


def set_config(args: Namespace):
"""
Expand Down Expand Up @@ -954,6 +973,7 @@ def parse_args_and_execute(parser: ArgumentParser, args: Namespace) -> None:
solc_json = getattr(args, "solc_json", None)
solv = getattr(args, "solv", None)
solc_args = getattr(args, "solc_args", None)
support_args.ignore_false_funcs = getattr(args, "ignore_false_funcs", None)
disassembler = MythrilDisassembler(
eth=config.eth,
solc_version=solv,
Expand Down
1 change: 1 addition & 0 deletions mythril/support/support_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def __init__(self):
self.disable_iprof = False
self.solver_log = None
self.transaction_sequences: List[List[str]] = None
self.ignore_false_funcs: List[str] = None
self.use_integer_module = True
self.use_issue_annotations = False
self.solc_args = None
Expand Down
17 changes: 17 additions & 0 deletions tests/integration_tests/ignore_false_funcs_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import pytest
from utils import output_of

from tests import PROJECT_DIR, TESTDATA

MYTH = str(PROJECT_DIR / "myth")

test_data = [
(f"{TESTDATA}/input_contracts/base_case.sol", "0x83197ef0"),
]


@pytest.mark.parametrize("file_name, ignore_func", test_data)
def test_ignore_false_funcs(file_name, ignore_func):
print(file_name)
output = output_of(f"{MYTH} a {file_name} --ignore-false-funcs [{ignore_func}]")
assert "Function name: destroy()" not in output