mirror of https://github.com/ConsenSys/mythril
[WIP] Handle exponents (#1497)
* Handle exponents * Bruteforce enumerate constraints * Fix evm tests * Fix imports * Fix z3 version to avoid exception * Fix z3 version to avoid exception * Fix z3 version * Fix z3 version * Hunt the issue * Hunt the issue * Hunt the issue * Hunt the issue * Hunt the issue * Fix issue * Fix issue * Add tests * Black * Fix issue * Fix issue with disassembler test * Fix issue with disassembler testpull/1498/head
parent
d8d469398b
commit
c72d212c7e
@ -0,0 +1,2 @@ |
|||||||
|
from .exponent_function_manager import exponent_function_manager |
||||||
|
from .keccak_function_manager import keccak_function_manager |
@ -0,0 +1,74 @@ |
|||||||
|
import logging |
||||||
|
from typing import Dict, List, Optional, Tuple |
||||||
|
|
||||||
|
from ethereum import utils |
||||||
|
|
||||||
|
from mythril.laser.smt import ( |
||||||
|
And, |
||||||
|
BitVec, |
||||||
|
Bool, |
||||||
|
Function, |
||||||
|
URem, |
||||||
|
symbol_factory, |
||||||
|
) |
||||||
|
|
||||||
|
log = logging.getLogger(__name__) |
||||||
|
|
||||||
|
|
||||||
|
class ExponentFunctionManager: |
||||||
|
""" |
||||||
|
Uses an uninterpreted function for exponentiation with the following properties: |
||||||
|
1) power(a, b) > 0 |
||||||
|
2) if a = 256 => forall i if b = i then power(a, b) = (256 ^ i) % (2^256) |
||||||
|
|
||||||
|
Only these two properties are added as to handle indexing of boolean arrays. |
||||||
|
Caution should be exercised when increasing the conditions since it severely affects |
||||||
|
the solving time. |
||||||
|
""" |
||||||
|
|
||||||
|
def __init__(self): |
||||||
|
power = Function("Power", [256, 256], 256) |
||||||
|
NUMBER_256 = symbol_factory.BitVecVal(256, 256) |
||||||
|
self.concrete_constraints = And( |
||||||
|
*[ |
||||||
|
power(NUMBER_256, symbol_factory.BitVecVal(i, 256)) |
||||||
|
== symbol_factory.BitVecVal(256 ** i, 256) |
||||||
|
for i in range(0, 32) |
||||||
|
] |
||||||
|
) |
||||||
|
self.concrete_constraints_sent = False |
||||||
|
|
||||||
|
def create_condition(self, base: BitVec, exponent: BitVec) -> Tuple[BitVec, Bool]: |
||||||
|
""" |
||||||
|
Creates a condition for exponentiation |
||||||
|
:param base: The base of exponentiation |
||||||
|
:param exponent: The exponent of the exponentiation |
||||||
|
:return: Tuple of condition and the exponentiation result |
||||||
|
""" |
||||||
|
power = Function("Power", [256, 256], 256) |
||||||
|
exponentiation = power(base, exponent) |
||||||
|
|
||||||
|
if exponent.symbolic is False and base.symbolic is False: |
||||||
|
const_exponentiation = symbol_factory.BitVecVal( |
||||||
|
pow(base.value, exponent.value, 2 ** 256), |
||||||
|
256, |
||||||
|
annotations=base.annotations.union(exponent.annotations), |
||||||
|
) |
||||||
|
constraint = const_exponentiation == exponentiation |
||||||
|
return const_exponentiation, constraint |
||||||
|
|
||||||
|
constraint = exponentiation > 0 |
||||||
|
if self.concrete_constraints_sent is False: |
||||||
|
constraint = And(constraint, self.concrete_constraints) |
||||||
|
self.concrete_constraints_sent = True |
||||||
|
if base.value == 256: |
||||||
|
constraint = And( |
||||||
|
constraint, |
||||||
|
power(base, URem(exponent, symbol_factory.BitVecVal(32, 256))) |
||||||
|
== power(base, exponent), |
||||||
|
) |
||||||
|
|
||||||
|
return exponentiation, constraint |
||||||
|
|
||||||
|
|
||||||
|
exponent_function_manager = ExponentFunctionManager() |
@ -0,0 +1,33 @@ |
|||||||
|
import pytest |
||||||
|
import json |
||||||
|
import sys |
||||||
|
|
||||||
|
from subprocess import check_output |
||||||
|
from tests import PROJECT_DIR, TESTDATA |
||||||
|
|
||||||
|
MYTH = str(PROJECT_DIR / "myth") |
||||||
|
test_data = ( |
||||||
|
( |
||||||
|
"flag_array.sol.o", |
||||||
|
{ |
||||||
|
"TX_COUNT": 1, |
||||||
|
"TX_OUTPUT": 1, |
||||||
|
"MODULE": "EtherThief", |
||||||
|
"ISSUE_COUNT": 1, |
||||||
|
"ISSUE_NUMBER": 0, |
||||||
|
}, |
||||||
|
"0xab12585800000000000000000000000000000000000000000000000000000000000004d2", |
||||||
|
), |
||||||
|
) |
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("file_name, tx_data, calldata", test_data) |
||||||
|
def test_analysis(file_name, tx_data, calldata): |
||||||
|
bytecode_file = str(TESTDATA / "inputs" / file_name) |
||||||
|
command = f"""python3 {MYTH} analyze -f {bytecode_file} -t {tx_data["TX_COUNT"]} -o jsonv2 -m {tx_data["MODULE"]} --solver-timeout 60000""" |
||||||
|
output = json.loads(check_output(command, shell=True).decode("UTF-8")) |
||||||
|
|
||||||
|
assert len(output[0]["issues"]) == tx_data["ISSUE_COUNT"] |
||||||
|
test_case = output[0]["issues"][tx_data["ISSUE_NUMBER"]]["extra"]["testCases"][0] |
||||||
|
print(test_case["steps"]) |
||||||
|
assert test_case["steps"][tx_data["TX_OUTPUT"]]["input"] == calldata |
@ -0,0 +1,17 @@ |
|||||||
|
pragma solidity ^0.8.0; |
||||||
|
|
||||||
|
contract BasicLiquidation { |
||||||
|
bool[4096] _flags; |
||||||
|
constructor() payable |
||||||
|
{ |
||||||
|
require(msg.value == 0.1 ether); |
||||||
|
_flags[1234] = true; |
||||||
|
} |
||||||
|
function extractMoney(uint256 idx) public payable |
||||||
|
{ |
||||||
|
require(idx >= 0); |
||||||
|
require(idx < 4096); |
||||||
|
require(_flags[idx]); |
||||||
|
payable(msg.sender).transfer(address(this).balance); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
608060405267016345785d8a0000341461001857600080fd5b600160006104d2611000811061003157610030610055565b5b602091828204019190066101000a81548160ff021916908315150217905550610084565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6101a6806100936000396000f3fe60806040526004361061001e5760003560e01c8063ab12585814610023575b600080fd5b61003d600480360381019061003891906100ee565b61003f565b005b600081101561004d57600080fd5b611000811061005b57600080fd5b60008161100081106100705761006f610125565b5b602091828204019190069054906101000a900460ff1661008f57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f193505050501580156100d5573d6000803e3d6000fd5b5050565b6000813590506100e881610159565b92915050565b60006020828403121561010457610103610154565b5b6000610112848285016100d9565b91505092915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b6101628161011b565b811461016d57600080fd5b5056fea264697066735822122038d1a63a64c5408c7008a0f3746ab94e43a04b5bc74f52e4869d3f15cf5b2b9e64736f6c63430008060033 |
Loading…
Reference in new issue