From c4127fd229c40e145f4d2826571af81bede09d05 Mon Sep 17 00:00:00 2001 From: Dominik Muhs Date: Mon, 26 Nov 2018 15:47:33 +0100 Subject: [PATCH] Add Ubuntu PPA support to solc installer, fix version to 0.5.0 --- mythril/ethereum/util.py | 20 +++---- mythril/mythril.py | 53 +++++++++---------- tests/cmd_line_test.py | 8 ++- .../transaction/create_transaction_test.py | 4 +- tests/native_test.py | 2 +- tests/solidity_contract_test.py | 6 +-- tests/svm_test.py | 2 +- 7 files changed, 46 insertions(+), 49 deletions(-) diff --git a/mythril/ethereum/util.py b/mythril/ethereum/util.py index 6669dadc..9c5a3fce 100644 --- a/mythril/ethereum/util.py +++ b/mythril/ethereum/util.py @@ -73,12 +73,14 @@ def get_indexed_address(index): def solc_exists(version): - solc_binary = os.path.join( - os.environ.get("HOME", str(Path.home())), - ".py-solc/solc-v" + version, - "bin/solc", - ) - if os.path.exists(solc_binary): - return True - else: - return False + solc_binaries = [ + os.path.join( + os.environ.get("HOME", str(Path.home())), + ".py-solc/solc-v" + version, + "bin/solc", + ), # py-solc setup + "/usr/bin/solc", # Ubuntu PPA setup + ] + for solc_path in solc_binaries: + if os.path.exists(solc_path): + return solc_path diff --git a/mythril/mythril.py b/mythril/mythril.py index ef74c645..3c7c7b5f 100644 --- a/mythril/mythril.py +++ b/mythril/mythril.py @@ -224,36 +224,33 @@ class Mythril(object): # Figure out solc binary and version # Only proper versions are supported. No nightlies, commits etc (such as available in remix) - if version: - # tried converting input to semver, seemed not necessary so just slicing for now - if version == str(solc.main.get_solc_version())[:6]: - logging.info("Given version matches installed version") - try: - solc_binary = os.environ["SOLC"] - except KeyError: - solc_binary = "solc" - else: - if util.solc_exists(version): - logging.info("Given version is already installed") - else: - try: - solc.install_solc("v" + version) - except SolcError: - raise CriticalError( - "There was an error when trying to install the specified solc version" - ) + if not version: + return os.environ.get("SOLC") or "solc" - solc_binary = os.path.join( - os.environ.get("HOME", str(Path.home())), - ".py-solc/solc-v" + version, - "bin/solc", - ) - logging.info("Setting the compiler to " + str(solc_binary)) + # tried converting input to semver, seemed not necessary so just slicing for now + main_version = solc.main.get_solc_version_string() + main_version_number = re.match(r"\d+.\d+.\d+", main_version) + if main_version is None: + raise CriticalError( + "Could not extract solc version from string {}".format(main_version) + ) + if version == main_version_number: + logging.info("Given version matches installed version") + solc_binary = os.environ.get("SOLC") or "solc" else: - try: - solc_binary = os.environ["SOLC"] - except KeyError: - solc_binary = "solc" + solc_binary = util.solc_exists(version) + if solc_binary: + logging.info("Given version is already installed") + else: + try: + solc.install_solc("v" + version) + except SolcError: + raise CriticalError( + "There was an error when trying to install the specified solc version" + ) + + logging.info("Setting the compiler to %s", solc_binary) + return solc_binary def set_api_leveldb(self, leveldb): diff --git a/tests/cmd_line_test.py b/tests/cmd_line_test.py index ef846480..bc45adbd 100644 --- a/tests/cmd_line_test.py +++ b/tests/cmd_line_test.py @@ -10,18 +10,16 @@ def output_of(command): class CommandLineToolTestCase(BaseTestCase): def test_disassemble_code_correctly(self): - command = "python3 {} MYTH -d --bin-runtime -c 0x5050 --solv 0.4.24".format( - MYTH - ) + command = "python3 {} MYTH -d --bin-runtime -c 0x5050 --solv 0.5.0".format(MYTH) self.assertIn("0 POP\n1 POP\n", output_of(command)) def test_disassemble_solidity_file_correctly(self): solidity_file = str(TESTDATA / "input_contracts" / "metacoin.sol") - command = "python3 {} -d {} --solv 0.4.24".format(MYTH, solidity_file) + command = "python3 {} -d {} --solv 0.5.0".format(MYTH, solidity_file) self.assertIn("2 PUSH1 0x40\n4 MSTORE", output_of(command)) def test_hash_a_function_correctly(self): - command = "python3 {} --solv 0.4.24 --hash 'setOwner(address)'".format(MYTH) + command = "python3 {} --solv 0.5.0 --hash 'setOwner(address)'".format(MYTH) self.assertIn("0x13af4035\n", output_of(command)) diff --git a/tests/laser/transaction/create_transaction_test.py b/tests/laser/transaction/create_transaction_test.py index 643e9efb..9b2351e4 100644 --- a/tests/laser/transaction/create_transaction_test.py +++ b/tests/laser/transaction/create_transaction_test.py @@ -13,7 +13,7 @@ from mythril.analysis.symbolic import SymExecWrapper def test_create(): contract = SolidityContract( str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol"), - solc_binary=Mythril._init_solc_binary("0.4.24"), + solc_binary=Mythril._init_solc_binary("0.5.0"), ) laser_evm = svm.LaserEVM({}) @@ -37,7 +37,7 @@ def test_create(): def test_sym_exec(): contract = SolidityContract( str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol"), - solc_binary=Mythril._init_solc_binary("0.4.24"), + solc_binary=Mythril._init_solc_binary("0.5.0"), ) sym = SymExecWrapper( diff --git a/tests/native_test.py b/tests/native_test.py index cf5c2d77..a19e86fd 100644 --- a/tests/native_test.py +++ b/tests/native_test.py @@ -89,7 +89,7 @@ class NativeTests(BaseTestCase): def runTest(): disassembly = SolidityContract( - "./tests/native_tests.sol", solc_binary=Mythril._init_solc_binary("0.4.24") + "./tests/native_tests.sol", solc_binary=Mythril._init_solc_binary("0.5.0") ).disassembly account = Account("0x0000000000000000000000000000000000000000", disassembly) accounts = {account.address: account} diff --git a/tests/solidity_contract_test.py b/tests/solidity_contract_test.py index ba5d9919..6b55aad1 100644 --- a/tests/solidity_contract_test.py +++ b/tests/solidity_contract_test.py @@ -11,7 +11,7 @@ class SolidityContractTest(BaseTestCase): def test_get_source_info_without_name_gets_latest_contract_info(self): input_file = TEST_FILES / "multi_contracts.sol" contract = SolidityContract( - str(input_file), solc_binary=Mythril._init_solc_binary("0.4.24") + str(input_file), solc_binary=Mythril._init_solc_binary("0.5.0") ) code_info = contract.get_source_info(142) @@ -25,7 +25,7 @@ class SolidityContractTest(BaseTestCase): contract = SolidityContract( str(input_file), name="Transfer1", - solc_binary=Mythril._init_solc_binary("0.4.24"), + solc_binary=Mythril._init_solc_binary("0.5.0"), ) code_info = contract.get_source_info(142) @@ -39,7 +39,7 @@ class SolidityContractTest(BaseTestCase): contract = SolidityContract( str(input_file), name="AssertFail", - solc_binary=Mythril._init_solc_binary("0.4.24"), + solc_binary=Mythril._init_solc_binary("0.5.0"), ) code_info = contract.get_source_info(70, constructor=True) diff --git a/tests/svm_test.py b/tests/svm_test.py index e2f31a91..b687e944 100644 --- a/tests/svm_test.py +++ b/tests/svm_test.py @@ -84,7 +84,7 @@ class SVMTestCase(BaseTestCase): ) disassembly = SolidityContract( - str(input_file), solc_binary=Mythril._init_solc_binary("0.4.24") + str(input_file), solc_binary=Mythril._init_solc_binary("0.5.0") ).disassembly account = Account("0x0000000000000000000000000000000000000000", disassembly) accounts = {account.address: account}