Add partial abi support (#1655)

* Fix issues with arbitrary jump dest

* Support abi

* Add partial abi support

* Fix test

* Fix test directory
pull/1662/head
Nikhil Parasaram 2 years ago committed by GitHub
parent 842e3da3a4
commit d6e8813100
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      mythril/analysis/report.py
  2. 56
      tests/analysis/abi_decode_test.py
  3. 2
      tests/analysis/arbitrary_jump_test.py

@ -1,7 +1,9 @@
"""This module provides classes that make up an issue report.""" """This module provides classes that make up an issue report."""
import logging import logging
import re
import json import json
import operator import operator
from eth_abi import decode_abi
from jinja2 import PackageLoader, Environment from jinja2 import PackageLoader, Environment
from typing import Dict, List, Any, Optional from typing import Dict, List, Any, Optional
import hashlib import hashlib
@ -193,11 +195,34 @@ class Issue:
# TODO: Check other mythx tools for dependency before supporting multiple possible function names # TODO: Check other mythx tools for dependency before supporting multiple possible function names
if len(sig) > 0: if len(sig) > 0:
step["name"] = sig[0] step["name"] = sig[0]
step["resolved_input"] = Issue.resolve_input(
step["calldata"], sig[0]
)
else: else:
step["name"] = "unknown" step["name"] = "unknown"
except ValueError: except ValueError:
step["name"] = "unknown" step["name"] = "unknown"
@staticmethod
def resolve_input(data, function_name):
"""
Adds decoded calldate to the tx sequence.
"""
data = data[10:]
# Eliminates the first and last brackets
# Since signature such as func((bytes32,bytes32,uint8)[],(address[],uint32)) are valid
type_info = function_name[function_name.find("(") + 1 : -1]
type_info = re.split(r",\s*(?![^()]*\))", type_info)
if len(data) % 64 > 0:
data += "0" * (64 - len(data) % 64)
try:
decoded_output = decode_abi(type_info, bytes.fromhex(data))
return decoded_output
except Exception as e:
return None
class Report: class Report:
"""A report containing the content of multiple issues.""" """A report containing the content of multiple issues."""

@ -0,0 +1,56 @@
import pytest
from mythril.analysis.report import Issue
from mythril.disassembler.disassembly import Disassembly
from mythril.laser.ethereum.state.environment import Environment
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.machine_state import MachineState
from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.instructions import Instruction
from mythril.laser.ethereum.transaction.transaction_models import MessageCallTransaction
from mythril.laser.smt import symbol_factory, simplify, LShR
test_data = (
(
"0xa9059cbb000000000000000000000000010801010101010120020101020401010408040402",
"func(uint256,uint256)",
(
5887484186314823854737699484601117092168074244,
904625697166532776746648320380374280103671755200316906558262375061821325312,
),
),
(
"0xa9059cbb00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002",
"func(uint256,uint256)",
(2, 2),
),
(
"0xa0cce1b3000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000",
"func(bytes32,(bytes32,bytes32,uint8,uint8)[],(address[],uint32))",
(
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02",
(
(
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x90",
0,
0,
),
(
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
1,
0,
),
),
(("0x0000000000000000000000000000000000000000",), 0),
),
),
)
@pytest.mark.parametrize("call_data, signature, expected", test_data)
def test_abi_decode(call_data, signature, expected):
assert Issue.resolve_input(call_data, signature) == expected

@ -37,7 +37,6 @@ def get_global_state(constraints):
world_state = WorldState() world_state = WorldState()
world_state.put_account(active_account) world_state.put_account(active_account)
state = GlobalState(world_state, environment, None, MachineState(gas_limit=8000000)) state = GlobalState(world_state, environment, None, MachineState(gas_limit=8000000))
print(world_state.balances)
state.world_state.transaction_sequence = [ state.world_state.transaction_sequence = [
MessageCallTransaction( MessageCallTransaction(
world_state=world_state, world_state=world_state,
@ -56,7 +55,6 @@ def get_global_state(constraints):
None, None,
) )
) )
print(state.world_state.transaction_sequence[0].call_data.calldatasize)
state.mstate.stack = [symbol_factory.BitVecSym("jump_dest", 256)] state.mstate.stack = [symbol_factory.BitVecSym("jump_dest", 256)]
state.world_state.constraints = Constraints(constraints) state.world_state.constraints = Constraints(constraints)
Loading…
Cancel
Save