From 01aef7783c8c02e6efa5cabd65646d481291b148 Mon Sep 17 00:00:00 2001 From: freewind Date: Sat, 31 Mar 2018 21:23:04 +0800 Subject: [PATCH] Fix some issues per viewers' advices --- README.md | 18 ++++++++- tests/__init__.py | 10 +++++ tests/cmd_line_test.py | 35 ++++++++---------- tests/disassembler_test.py | 15 ++++---- tests/graph_test.py | 11 +++--- tests/ipc_test.py | 3 +- tests/mythril_dir/signatures.json | 1 + tests/report_test.py | 21 +++++------ tests/rpc_test.py | 1 + tests/testdata/outputs/calls.sol.json | 20 +++++----- tests/testdata/outputs/calls.sol.markdown | 18 ++++----- tests/testdata/outputs/calls.sol.text | 18 ++++----- tests/testdata/outputs/ether_send.sol.json | 4 +- .../testdata/outputs/ether_send.sol.markdown | 2 +- tests/testdata/outputs/ether_send.sol.text | 2 +- tests/testdata/outputs/exceptions.sol.json | 10 ++--- .../testdata/outputs/exceptions.sol.markdown | 8 ++-- tests/testdata/outputs/exceptions.sol.text | 8 ++-- .../testdata/outputs/kinds_of_calls.sol.json | 6 +-- .../outputs/kinds_of_calls.sol.markdown | 4 +- .../testdata/outputs/kinds_of_calls.sol.text | 4 +- .../testdata/outputs/multi_contracts.sol.json | 4 +- .../outputs/multi_contracts.sol.markdown | 2 +- .../testdata/outputs/multi_contracts.sol.text | 2 +- tests/testdata/outputs/origin.sol.json | 4 +- tests/testdata/outputs/origin.sol.markdown | 2 +- tests/testdata/outputs/origin.sol.text | 2 +- tests/testdata/outputs/returnvalue.sol.json | 8 ++-- .../testdata/outputs/returnvalue.sol.markdown | 6 +-- tests/testdata/outputs/returnvalue.sol.text | 6 +-- tests/testdata/outputs/rubixi.sol.json | 18 ++++----- tests/testdata/outputs/rubixi.sol.markdown | 16 ++++---- tests/testdata/outputs/rubixi.sol.text | 16 ++++---- tests/testdata/outputs/suicide.sol.json | 4 +- tests/testdata/outputs/suicide.sol.markdown | 2 +- tests/testdata/outputs/suicide.sol.text | 2 +- tests/testdata/outputs/underflow.sol.json | 6 +-- tests/testdata/outputs/underflow.sol.markdown | 4 +- tests/testdata/outputs/underflow.sol.text | 4 +- tests/testdata/outputs/weak_random.sol.json | 10 ++--- .../testdata/outputs/weak_random.sol.markdown | 8 ++-- tests/testdata/outputs/weak_random.sol.text | 8 ++-- tests/teststorage/contractstorage.fs.index | Bin 31 -> 72 bytes 43 files changed, 188 insertions(+), 165 deletions(-) create mode 100644 tests/mythril_dir/signatures.json diff --git a/README.md b/README.md index b5504f1c..f4c515cb 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,20 @@ If you plan to analyze Solidity code you'll also need the [native version of sol ## Running tests +### python version + +First, make sure your python version is `3.6.x`. Some tests will fail with `3.5.x` since some generated easm code is different from `3.6.x`. + +### truffle + +In the tests, we tested the command `--truffle`, which required the `truffle` command is installed. + +``` +npm install -g truffle +``` + +### geth + In order to run tests and coverage reports, you need to run `geth` locally, since some tests depend on it. Install `geth` from here: @@ -59,7 +73,9 @@ geth --syncmode full --rpc --shh --debug We use `--syncmode full` here because the `eth.blockNumber` will get increased soon in this mode, which is useful in tests. -If there is no error thrown, you can wait 1 or 2 minutes, then run the tests: +If there is no error thrown, you can wait 1 or 2 minutes before running tests. + +### Run the tests ```bash pip3 install -r requirements.txt diff --git a/tests/__init__.py b/tests/__init__.py index e69de29b..d7e92230 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1,10 @@ +from pathlib import Path +import os + +TESTS_DIR = Path(__file__).parent +PROJECT_DIR = TESTS_DIR.parent +TESTDATA = TESTS_DIR / "testdata" +TESTDATA_INPUTS = TESTDATA / "inputs" +TESTDATA_OUTPUTS = TESTDATA / "outputs" + +os.environ['MYTHRIL_DIR'] = str(TESTS_DIR / "mythril_dir") diff --git a/tests/cmd_line_test.py b/tests/cmd_line_test.py index 69f16bff..6646afa7 100644 --- a/tests/cmd_line_test.py +++ b/tests/cmd_line_test.py @@ -1,56 +1,53 @@ from unittest import TestCase from subprocess import check_output -from pathlib import Path +from tests import * + +MYTH = str(PROJECT_DIR / "myth") def output_of(command): return check_output(command, shell=True).decode("UTF-8") -class BaseTestCase(TestCase): - def setUp(self): - self.tests_dir = Path(__file__).parent - self.myth = str(self.tests_dir.parent / "myth") - -class CommandLineToolTestCase(BaseTestCase): +class CommandLineToolTestCase(TestCase): def test_disassemble_code_correctly(self): - command = "python3 {} self.myth -d -c 0x5050".format(self.myth) + command = "python3 {} MYTH -d -c 0x5050".format(MYTH) self.assertEqual('0 POP\n1 POP\n', output_of(command)) def test_disassemble_solidity_file_correctly(self): - solidity_file = str(self.tests_dir / 'testdata/inputs/metacoin.sol') - command = "python3 {} -d {}".format(self.myth, solidity_file) + solidity_file = str(TESTDATA_INPUTS / 'metacoin.sol') + command = "python3 {} -d {}".format(MYTH, solidity_file) self.assertIn('0 PUSH1 0x60\n2 PUSH1 0x40', output_of(command)) def test_hash_a_function_correctly(self): - command = "python3 {} --hash 'setOwner(address)'".format(self.myth) + command = "python3 {} --hash 'setOwner(address)'".format(MYTH) self.assertEqual('0x13af4035\n', output_of(command)) -class TruffleTestCase(BaseTestCase): +class TruffleTestCase(TestCase): def test_analysis_truffle_project(self): - truffle_project_root = str(self.tests_dir / "truffle_project") - command = "cd {}; truffle compile; python3 {} --truffle".format(truffle_project_root, self.myth) + truffle_project_root = str(TESTS_DIR / "truffle_project") + command = "cd {}; truffle compile; python3 {} --truffle".format(truffle_project_root, MYTH) self.assertIn("In the function 'withdrawfunds()' a non-zero amount of Ether is sent to msg.sender.", output_of(command)) -class InfuraTestCase(BaseTestCase): +class InfuraTestCase(TestCase): def test_infura_mainnet(self): - command = "python3 {} --rpc infura-mainnet -d -a 0x2a0c0dbecc7e4d658f48e01e3fa353f44050c208".format(self.myth) + command = "python3 {} --rpc infura-mainnet -d -a 0x2a0c0dbecc7e4d658f48e01e3fa353f44050c208".format(MYTH) output = output_of(command) self.assertIn("0 PUSH1 0x60\n2 PUSH1 0x40\n4 MSTORE", output) self.assertIn("7278 POP\n7279 POP\n7280 JUMP\n7281 STOP", output) def test_infura_rinkeby(self): - command = "python3 {} --rpc infura-rinkeby -d -a 0xB6f2bFED892a662bBF26258ceDD443f50Fa307F5".format(self.myth) + command = "python3 {} --rpc infura-rinkeby -d -a 0xB6f2bFED892a662bBF26258ceDD443f50Fa307F5".format(MYTH) output = output_of(command) self.assertIn("34 JUMPDEST\n35 CALLVALUE", output) def test_infura_kovan(self): - command = "python3 {} --rpc infura-kovan -d -a 0xE6bBF9B5A3451242F82f8cd458675092617a1235".format(self.myth) + command = "python3 {} --rpc infura-kovan -d -a 0xE6bBF9B5A3451242F82f8cd458675092617a1235".format(MYTH) output = output_of(command) self.assertIn("9999 PUSH1 0x00\n10001 NOT\n10002 AND\n10003 PUSH1 0x00", output) def test_infura_ropsten(self): - command = "python3 {} --rpc infura-ropsten -d -a 0x6e0E0e02377Bc1d90E8a7c21f12BA385C2C35f78".format(self.myth) + command = "python3 {} --rpc infura-ropsten -d -a 0x6e0E0e02377Bc1d90E8a7c21f12BA385C2C35f78".format(MYTH) output = output_of(command) self.assertIn("1821 PUSH1 0x01\n1823 PUSH2 0x070c", output) diff --git a/tests/disassembler_test.py b/tests/disassembler_test.py index 27238533..505a81ef 100644 --- a/tests/disassembler_test.py +++ b/tests/disassembler_test.py @@ -1,17 +1,15 @@ -import unittest -from pathlib import Path +from unittest import TestCase from mythril.disassembler.disassembly import Disassembly from mythril.ether import util - -TEST_FILES = Path(__file__).parent / "testdata" +from tests import * def _compile_to_code(input_file): compiled = util.get_solc_json(str(input_file)) code = list(compiled['contracts'].values())[0]['bin-runtime'] return code -class DisassemblerTestCase(unittest.TestCase): +class DisassemblerTestCase(TestCase): def test_instruction_list(self): code = "0x606060405236156100ca5763ffffffff60e060020a600035041663054f7d9c81146100d3578063095c21e3146100f45780630ba50baa146101165780631a3719321461012857806366529e3f14610153578063682789a81461017257806389f21efc146101915780638da5cb5b146101ac5780638f4ffcb1146101d55780639a1f2a5714610240578063b5f522f71461025b578063bd94b005146102b6578063c5ab5a13146102c8578063cc424839146102f1578063deb077b914610303578063f3fef3a314610322575b6100d15b5b565b005b34610000576100e0610340565b604080519115158252519081900360200190f35b3461000057610104600435610361565b60408051918252519081900360200190f35b34610000576100d1600435610382565b005b3461000057610104600160a060020a03600435166103b0565b60408051918252519081900360200190f35b346100005761010461041e565b60408051918252519081900360200190f35b3461000057610104610424565b60408051918252519081900360200190f35b34610000576100d1600160a060020a036004351661042b565b005b34610000576101b961046f565b60408051600160a060020a039092168252519081900360200190f35b3461000057604080516020600460643581810135601f81018490048402850184019095528484526100d1948235600160a060020a039081169560248035966044359093169594608494929391019190819084018382808284375094965061048595505050505050565b005b34610000576100d1600160a060020a03600435166106e7565b005b346100005761026b60043561072b565b60408051600160a060020a0390991689526020890197909752878701959095526060870193909352608086019190915260a085015260c084015260e083015251908190036101000190f35b34610000576100d160043561077a565b005b34610000576101b9610830565b60408051600160a060020a039092168252519081900360200190f35b34610000576100d160043561083f565b005b34610000576101046108a1565b60408051918252519081900360200190f35b34610000576100d1600160a060020a03600435166024356108a7565b005b60015474010000000000000000000000000000000000000000900460ff1681565b600681815481101561000057906000526020600020900160005b5054905081565b600054600160a060020a036301000000909104811690331681146103a557610000565b60038290555b5b5050565b6005546040805160006020918201819052825160e260020a631d010437028152600160a060020a03868116600483015293519194939093169263740410dc92602480830193919282900301818787803b156100005760325a03f115610000575050604051519150505b919050565b60035481565b6006545b90565b600054600160a060020a0363010000009091048116903316811461044e57610000565b60018054600160a060020a031916600160a060020a0384161790555b5b5050565b60005463010000009004600160a060020a031681565b6000600060006000600060006000600160149054906101000a900460ff16156104ad57610000565b87600081518110156100005760209101015160005460f860020a918290048202975002600160f860020a031990811690871614156105405760009450600196505b600587101561053057878781518110156100005790602001015160f860020a900460f860020a0260f860020a900485610100020194505b6001909601956104ee565b61053b8b868c610955565b6106d6565b600054610100900460f860020a02600160f860020a0319908116908716141561069e57506001955060009250829150819050805b60058710156105b657878781518110156100005790602001015160f860020a900460f860020a0260f860020a900481610100020190505b600190960195610574565b600596505b60098710156105fd57878781518110156100005790602001015160f860020a900460f860020a0260f860020a900484610100020193505b6001909601956105bb565b600996505b600d87101561064457878781518110156100005790602001015160f860020a900460f860020a0260f860020a900483610100020192505b600190960195610602565b600d96505b601187101561068b57878781518110156100005790602001015160f860020a900460f860020a0260f860020a900482610100020191505b600190960195610649565b61053b8b828c878787610bc4565b6106d6565b60005462010000900460f860020a02600160f860020a031990811690871614156106d15761053b8b8b610e8e565b6106d6565b610000565b5b5b5b5b5050505050505050505050565b600054600160a060020a0363010000009091048116903316811461070a57610000565b60058054600160a060020a031916600160a060020a0384161790555b5b5050565b600760208190526000918252604090912080546001820154600283015460038401546004850154600586015460068701549690970154600160a060020a03909516969395929491939092909188565b600081815260076020526040812054600160a060020a0390811690331681146107a257610000565b600083815260076020526040902080546004820154600583015460038401549395506107dc93600160a060020a039093169291029061105e565b50600060058301556107ed83611151565b6040805184815290517fb5dc9baf0cb4e7e4759fa12eadebddf9316e26147d5a9ae150c4228d5a1dd23f9181900360200190a161082933611244565b5b5b505050565b600154600160a060020a031681565b600054600160a060020a0363010000009091048116903316811461086257610000565b600080546040516301000000909104600160a060020a0316916108fc851502918591818181858888f1935050505015156103ab57610000565b5b5b5050565b60025481565b600054600160a060020a036301000000909104811690331681146108ca57610000565b6000805460408051602090810184905281517fa9059cbb0000000000000000000000000000000000000000000000000000000081526301000000909304600160a060020a0390811660048501526024840187905291519187169363a9059cbb9360448082019492918390030190829087803b156100005760325a03f115610000575050505b5b505050565b610100604051908101604052806000600160a060020a03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525060006007600085815260200190815260200160002061010060405190810160405290816000820160009054906101000a9004600160a060020a0316600160a060020a0316600160a060020a0316815260200160018201548152602001600282015481526020016003820154815260200160048201548152602001600582015481526020016006820154815260200160078201548152505091508260001415610a4857610000565b8160400151838115610000570615610a5f57610000565b6002548410610a6d57610000565b8160400151838115610000570490508160a00151811115610a8d57610000565b610a9c8584846020015161128e565b1515610aa757610000565b60a082018051829003815260008581526007602081815260409283902086518154600160a060020a031916600160a060020a038216178255918701516001820181905593870151600282015560608701516003820155608087015160048201559351600585015560c0860151600685015560e08601519390910192909255610b319190859061105e565b1515610b3c57610000565b610b518582846080015102846060015161105e565b1515610b5c57610000565b60a0820151158015610b71575060c082015115155b15610b7f57610b7f84611151565b5b6040805185815290517fb5dc9baf0cb4e7e4759fa12eadebddf9316e26147d5a9ae150c4228d5a1dd23f9181900360200190a1610bbc85611244565b5b5050505050565b831515610bd057610000565b82851415610bdd57610000565b801580610be8575081155b15610bf257610000565b80848115610000570615610c0557610000565b6005546040805160006020918201819052825160e260020a631d010437028152600160a060020a038b8116600483015293518695949094169363740410dc9360248084019491938390030190829087803b156100005760325a03f11561000057505050604051805190501015610c7a57610000565b610c8586858761128e565b1515610c9057610000565b600554604080517fbe0140a6000000000000000000000000000000000000000000000000000000008152600160a060020a03898116600483015260006024830181905260448301869052925193169263be0140a69260648084019391929182900301818387803b156100005760325a03f115610000575050506101006040519081016040528087600160a060020a03168152602001848152602001838152602001868152602001828681156100005704815260200182815260200160068054905081526020014281525060076000600254815260200190815260200160002060008201518160000160006101000a815481600160a060020a030219169083600160a060020a031602179055506020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e0820151816007015590505060068054806001018281815481835581811511610e2757600083815260209020610e279181019083015b80821115610e235760008155600101610e0f565b5090565b5b505050916000526020600020900160005b50600280549182905560018201905560408051918252517fb5dc9baf0cb4e7e4759fa12eadebddf9316e26147d5a9ae150c4228d5a1dd23f92509081900360200190a1610e8586611244565b5b505050505050565b600354818115610000570615610ea357610000565b600160009054906101000a9004600160a060020a0316600160a060020a031663cf35bdd060016000604051602001526040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b156100005760325a03f115610000575050604080518051600080546020938401829052845160e060020a6323b872dd028152600160a060020a038981166004830152630100000090920482166024820152604481018890529451921694506323b872dd936064808201949392918390030190829087803b156100005760325a03f1156100005750506040515115159050610f9857610000565b600554600354600160a060020a039091169063be0140a6908490600190858115610000576040805160e060020a63ffffffff8816028152600160a060020a039095166004860152921515602485015204604483015251606480830192600092919082900301818387803b156100005760325a03f1156100005750505061101d82611244565b60408051600160a060020a038416815290517f30a29a0aa75376a69254bb98dbd11db423b7e8c3473fb5bf0fcba60bcbc42c4b9181900360200190a15b5050565b600081151561106c57610000565b6001546040805160006020918201819052825160e460020a630cf35bdd028152600481018790529251600160a060020a039094169363cf35bdd09360248082019493918390030190829087803b156100005760325a03f1156100005750505060405180519050600160a060020a031663a9059cbb85856000604051602001526040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050602060405180830381600087803b156100005760325a03f115610000575050604051519150505b9392505050565b6000818152600760205260409020600690810154815490919060001981019081101561000057906000526020600020900160005b5054600682815481101561000057906000526020600020900160005b50556006805460001981018083559091908280158290116111e7576000838152602090206111e79181019083015b80821115610e235760008155600101610e0f565b5090565b5b50506006548314915061122d9050578060076000600684815481101561000057906000526020600020900160005b505481526020810191909152604001600020600601555b6000828152600760205260408120600601555b5050565b60045481600160a060020a031631101561128957600454604051600160a060020a0383169180156108fc02916000818181858888f19350505050151561128957610000565b5b5b50565b600081151561129c57610000565b6001546040805160006020918201819052825160e460020a630cf35bdd028152600481018790529251600160a060020a039094169363cf35bdd09360248082019493918390030190829087803b156100005760325a03f11561000057505060408051805160006020928301819052835160e060020a6323b872dd028152600160a060020a038a811660048301523081166024830152604482018a905294519490921694506323b872dd93606480840194939192918390030190829087803b156100005760325a03f115610000575050604051519150505b93925050505600a165627a7a723058204dee0e1bf170a9d122508f3e876c4a84893b12a7345591521af4ca737bb765000029" @@ -19,12 +17,13 @@ class DisassemblerTestCase(unittest.TestCase): self.assertEqual(len(disassembly.instruction_list), 3523) def test_easm_from_solidity_files(self): - for input_file in (TEST_FILES / "inputs").iterdir(): + for input_file in TESTDATA_INPUTS.iterdir(): code = _compile_to_code(input_file) disassembly = Disassembly(code) - # (TEST_FILES / "outputs" / (input_file.name + ".easm")).write_text(disassembly.get_easm()) + # Useful for generating output file + # (TESTDATA_OUTPUTS / (input_file.name + ".easm")).write_text(disassembly.get_easm()) - expected_easm = (TEST_FILES / "outputs" / (input_file.name + ".easm")).read_text() + expected_easm = (TESTDATA_OUTPUTS / (input_file.name + ".easm")).read_text() self.assertEqual(disassembly.get_easm(), expected_easm, "{} returns invalid easm".format(str(input_file))) diff --git a/tests/graph_test.py b/tests/graph_test.py index 95deca7a..95b1cf0f 100644 --- a/tests/graph_test.py +++ b/tests/graph_test.py @@ -1,5 +1,4 @@ from unittest import TestCase -from pathlib import Path from mythril.analysis.callgraph import generate_graph from mythril.analysis.report import Report @@ -7,13 +6,12 @@ from mythril.analysis.security import fire_lasers from mythril.analysis.symbolic import SymExecWrapper from mythril.ether import util from mythril.ether.soliditycontract import SolidityContract - -TEST_FILES = Path(__file__).parent / "testdata" +from tests import * class GraphTest(TestCase): def test_generate_graph(self): - for input_file in (TEST_FILES / "inputs").iterdir(): + for input_file in TESTDATA_INPUTS.iterdir(): contract = SolidityContract(str(input_file), name=None, solc_args=None) sym = SymExecWrapper(contract, address=(util.get_indexed_address(0))) issues = fire_lasers(sym) @@ -27,7 +25,8 @@ class GraphTest(TestCase): html = generate_graph(sym) - # (TEST_FILES / "outputs" / (input_file.name + ".graph.html")).write_text(html) + # Useful for generating output file + # (TESTDATA_OUTPUTS / (input_file.name + ".graph.html")).write_text(html) - expected = (TEST_FILES / "outputs" / (input_file.name + ".graph.html")).read_text() + expected = (TESTDATA_OUTPUTS / (input_file.name + ".graph.html")).read_text() self.assertEqual(html, expected, "{}: graph html is changed".format(str(input_file))) diff --git a/tests/ipc_test.py b/tests/ipc_test.py index 022136b5..56e5583f 100644 --- a/tests/ipc_test.py +++ b/tests/ipc_test.py @@ -10,7 +10,7 @@ class IpcTest(TestCase): return self.client.eth_newFilter(from_block="0x1", to_block="0x2", address="0x8888f1f195afa192cfee860698584c030f4c9db1") def setUp(self): - self.client = EthIpc(socket_timeout=1.0) + self.client = EthIpc() def test_web3_clientVersion(self): version = self.client.web3_clientVersion() @@ -172,6 +172,7 @@ class IpcTest(TestCase): count = self.client.eth_getUncleCountByBlockNumber(105) self.assertEqual(count, 1, "there should be 1 uncle at block 105") + @skip("""{'jsonrpc': '2.0', 'id': 1, 'error': {'code': -32000, 'message': "mining not ready: No work available yet, don't panic."}}""") def test_eth_getWork(self): work = self.client.eth_getWork() self.assertEqual(len(work), 3) diff --git a/tests/mythril_dir/signatures.json b/tests/mythril_dir/signatures.json new file mode 100644 index 00000000..9dc205ce --- /dev/null +++ b/tests/mythril_dir/signatures.json @@ -0,0 +1 @@ +{"0x07f9f7ba": "StandardBounties(address)", "0x8c590917": "contribute(uint256,uint256)", "0x626a413a": "activateBounty(uint256,uint256)", "0x1e688c14": "fulfillBounty(uint256,string)", "0x41ac5dd0": "updateFulfillment(uint256,uint256,string)", "0xd9583497": "acceptFulfillment(uint256,uint256)", "0x16b57509": "killBounty(uint256)", "0x2d1fdef6": "extendDeadline(uint256,uint256)", "0x5d19606e": "transferIssuer(uint256,address)", "0xd6c0ceab": "changeBountyDeadline(uint256,uint256)", "0xf3d3402a": "changeBountyData(uint256,string)", "0x452ccadb": "changeBountyFulfillmentAmount(uint256,uint256)", "0xcdad6576": "changeBountyArbiter(uint256,address)", "0x992a3e75": "changeBountyPaysTokens(uint256,bool,address)", "0x422d4cd6": "increasePayout(uint256,uint256,uint256)", "0xb94b0a3a": "getFulfillment(uint256,uint256)", "0xee8c4bbf": "getBounty(uint256)", "0x86647bac": "getBountyArbiter(uint256)", "0xa60745aa": "getBountyData(uint256)", "0x19dba3d2": "getBountyToken(uint256)", "0x3278ba2f": "getNumBounties()", "0xfbe334f8": "getNumFulfillments(uint256)", "0xdb3b6263": "transitionToState(uint256,BountyStages)", "0x4e3b52fe": "metaCoin()", "0x412664ae": "sendToken(address,uint256)", "0x56885cd8": "crowdfunding()", "0x6c343ffe": "withdrawfunds()", "0xe8b5e51f": "invest()", "0xaa3288f4": "getBalance())", "0xc11a4b47": "Origin()", "0xf2fde38b": "transferOwnership(address)", "0x00362a95": "donate(address)", "0x70a08231": "balanceOf(address)", "0x2e1a7d4d": "withdraw(uint256)", "0x6241bfd1": "Token(uint256)", "0xa3210e87": "sendeth(address,uint256)", "0xcd38aa87": "chooseWinner()", "0xd6d22fa4": "MetaCoin()", "0x90b98a11": "sendCoin(address,uint256)", "0x7bd703e8": "getBalanceInEth(address)", "0xf8b2cb4f": "getBalance(address)", "0xa360b26f": "Migrations()", "0xfdacd576": "setCompleted(uint256)", "0x0900f010": "upgrade(address)", "0xcae9ca51": "approveAndCall(address,uint256,bytes)", "0xa9059cbb": "transfer(address,uint256)", "0x23b872dd": "transferFrom(address,address,uint256)", "0x095ea7b3": "approve(address,uint256)", "0xdd62ed3e": "allowance(address,address)", "0x525f8a5c": "setSaleStartTime(uint256)", "0xd132391a": "setSaleEndTime(uint256)", "0x0a0cd8c8": "setupDone()", "0xd7bb99ba": "contribute()", "0xf0349d5f": "setupStages()", "0x2a4f6533": "createTokenContract())", "0x42a6b21a": "getContributionLimit(address)", "0x1a787915": "startConditions(bytes32)", "0xf3fde261": "onTransition(bytes32)", "0x27816235": "onSaleEnded()", "0x091cde0b": "DisbursementHandler(address)", "0xf3fef3a3": "withdraw(address,uint256)", "0x4bc9fdc2": "calcMaxWithdraw()", "0xc9e61599": "createTarget())", "0x200094e0": "deployContract())", "0x5a048d78": "claim(Target)", "0x16ae6b67": "checkInvariant())", "0x2aa5ed61": "DayLimit(uint256)", "0xe7dde9a3": "_setDailyLimit(uint256)", "0x4a4c82c6": "_resetSpentToday()", "0x180aadb7": "underLimit(uint256)", "0x9d4468ff": "today())", "0x19045a25": "recover(bytes32,bytes)", "0xe92dfb23": "LimitBalance(uint256)", "0xd73dd623": "increaseApproval(address,uint256)", "0x66188463": "decreaseApproval(address,uint256)", "0xabaf5880": "Crowdsale(uint256,uint256,uint256,address)", "0xec8ac4d8": "buyTokens(address)", "0x9d735286": "forwardFunds()", "0x605120cf": "validPurchase())", "0x6e42787f": "hasEnded())", "0xe5c46944": "MultiSigWallet(address[],uint256)", "0x7065cb48": "addOwner(address)", "0x173825d9": "removeOwner(address)", "0xe20056e6": "replaceOwner(address,address)", "0xba51a6df": "changeRequirement(uint256)", "0xc6427474": "submitTransaction(address,uint256,bytes)", "0xc01a8c84": "confirmTransaction(uint256)", "0x20ea8d86": "revokeConfirmation(uint256)", "0xee22610b": "executeTransaction(uint256)", "0x784547a7": "isConfirmed(uint256)", "0xec096f8d": "addTransaction(address,uint256,bytes)", "0x8b51d13f": "getConfirmationCount(uint256)", "0x54741525": "getTransactionCount(bool,bool)", "0xa0e67e2b": "getOwners()", "0xb5dc40c3": "getConfirmations(uint256)", "0xa8abe69a": "getTransactionIds(uint256,uint256,bool,bool)"} \ No newline at end of file diff --git a/tests/report_test.py b/tests/report_test.py index adc7b056..7f8afd86 100644 --- a/tests/report_test.py +++ b/tests/report_test.py @@ -1,5 +1,4 @@ from unittest import TestCase -from pathlib import Path from mythril.analysis.report import Report from mythril.analysis.security import fire_lasers @@ -7,11 +6,10 @@ from mythril.analysis.symbolic import SymExecWrapper from mythril.ether import util from mythril.ether.soliditycontract import SolidityContract import json - -TEST_FILES = Path(__file__).parent / "testdata" +from tests import * def _fix_path(text): - return text.replace(str(TEST_FILES), "") + return text.replace(str(TESTDATA), "") def _fix_debug_data(json_str): read_json = json.loads(json_str) @@ -22,7 +20,7 @@ def _fix_debug_data(json_str): class AnalysisReportTest(TestCase): def test_reports(self): - for input_file in (TEST_FILES / "inputs").iterdir(): + for input_file in (TESTDATA / "inputs").iterdir(): contract = SolidityContract(str(input_file), name=None, solc_args=None) sym = SymExecWrapper(contract, address=(util.get_indexed_address(0))) issues = fire_lasers(sym) @@ -34,13 +32,14 @@ class AnalysisReportTest(TestCase): for issue in issues: report.append_issue(issue) - # (TEST_FILES / "outputs" / (input_file.name + ".text")).write_text(_fix_path(report.as_text())) - # (TEST_FILES / "outputs" / (input_file.name + ".json")).write_text(_fix_path(_fix_debug_data(report.as_json()))) - # (TEST_FILES / "outputs" / (input_file.name + ".markdown")).write_text(_fix_path(report.as_markdown())) + # Useful for generating output file + # (TESTDATA_OUTPUTS / (input_file.name + ".text")).write_text(_fix_path(report.as_text())) + # (TESTDATA_OUTPUTS / (input_file.name + ".json")).write_text(_fix_path(_fix_debug_data(report.as_json()))) + # (TESTDATA_OUTPUTS / (input_file.name + ".markdown")).write_text(_fix_path(report.as_markdown())) - text = (TEST_FILES / "outputs" / (input_file.name + ".text")).read_text() - json_report = (TEST_FILES / "outputs" / (input_file.name + ".json")).read_text() - markdown = (TEST_FILES / "outputs" / (input_file.name + ".markdown")).read_text() + text = (TESTDATA / "outputs" / (input_file.name + ".text")).read_text() + json_report = (TESTDATA / "outputs" / (input_file.name + ".json")).read_text() + markdown = (TESTDATA / "outputs" / (input_file.name + ".markdown")).read_text() self.assertEqual(_fix_path(report.as_text()), text, "{}: text report is changed".format(str(input_file))) self.assertEqual(_fix_path(report.as_markdown()), markdown, "{}: markdown report is changed".format(str(input_file))) diff --git a/tests/rpc_test.py b/tests/rpc_test.py index b16b8f5f..287b7556 100644 --- a/tests/rpc_test.py +++ b/tests/rpc_test.py @@ -175,6 +175,7 @@ class RpcTest(TestCase): count = self.client.eth_getUncleCountByBlockNumber(105) self.assertEqual(count, 1, "there should be 1 uncle at block 105") + @skip("""{'jsonrpc': '2.0', 'id': 1, 'error': {'code': -32000, 'message': "mining not ready: No work available yet, don't panic."}}""") def test_eth_getWork(self): work = self.client.eth_getWork() self.assertEqual(len(work), 3) diff --git a/tests/testdata/outputs/calls.sol.json b/tests/testdata/outputs/calls.sol.json index 2f8cb959..cc2c23f0 100644 --- a/tests/testdata/outputs/calls.sol.json +++ b/tests/testdata/outputs/calls.sol.json @@ -9,7 +9,7 @@ "type": "Informational", "address": 661, "debug": "", - "filename": "/inputs/calls.sol", + "filename": "/inputs/calls.sol", "lineno": 16, "code": "fixed_address.call()" }, @@ -20,7 +20,7 @@ "type": "Warning", "address": 779, "debug": "", - "filename": "/inputs/calls.sol", + "filename": "/inputs/calls.sol", "lineno": 29, "code": "stored_address.call()" }, @@ -31,7 +31,7 @@ "type": "Informational", "address": 858, "debug": "", - "filename": "/inputs/calls.sol", + "filename": "/inputs/calls.sol", "lineno": 20, "code": "fixed_address.call()" }, @@ -42,7 +42,7 @@ "type": "Warning", "address": 869, "debug": "", - "filename": "/inputs/calls.sol", + "filename": "/inputs/calls.sol", "lineno": 21, "code": "statevar = 0" }, @@ -53,7 +53,7 @@ "type": "Warning", "address": 912, "debug": "", - "filename": "/inputs/calls.sol", + "filename": "/inputs/calls.sol", "lineno": 25, "code": "addr.call()" }, @@ -64,7 +64,7 @@ "type": "Informational", "address": 661, "debug": "", - "filename": "/inputs/calls.sol", + "filename": "/inputs/calls.sol", "lineno": 16, "code": "fixed_address.call()" }, @@ -75,7 +75,7 @@ "type": "Informational", "address": 779, "debug": "", - "filename": "/inputs/calls.sol", + "filename": "/inputs/calls.sol", "lineno": 29, "code": "stored_address.call()" }, @@ -86,7 +86,7 @@ "type": "Informational", "address": 858, "debug": "", - "filename": "/inputs/calls.sol", + "filename": "/inputs/calls.sol", "lineno": 20, "code": "fixed_address.call()" }, @@ -97,9 +97,9 @@ "type": "Informational", "address": 912, "debug": "", - "filename": "/inputs/calls.sol", + "filename": "/inputs/calls.sol", "lineno": 25, "code": "addr.call()" } ] -} \ No newline at end of file +} diff --git a/tests/testdata/outputs/calls.sol.markdown b/tests/testdata/outputs/calls.sol.markdown index fb398644..2125f4eb 100644 --- a/tests/testdata/outputs/calls.sol.markdown +++ b/tests/testdata/outputs/calls.sol.markdown @@ -8,7 +8,7 @@ ### Description This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code. -In */inputs/calls.sol:16* +In */inputs/calls.sol:16* ``` fixed_address.call() @@ -22,7 +22,7 @@ fixed_address.call() ### Description This contract executes a message call to an address found at storage slot 1. This storage slot can be written to by calling the function '_function_0x2776b163'. Generally, it is not recommended to call user-supplied adresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state. -In */inputs/calls.sol:29* +In */inputs/calls.sol:29* ``` stored_address.call() @@ -36,7 +36,7 @@ stored_address.call() ### Description This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code. -In */inputs/calls.sol:20* +In */inputs/calls.sol:20* ``` fixed_address.call() @@ -50,7 +50,7 @@ fixed_address.call() ### Description The contract account state is changed after an external call. Consider that the called contract could re-enter the function before this state change takes place. This can lead to business logic vulnerabilities. -In */inputs/calls.sol:21* +In */inputs/calls.sol:21* ``` statevar = 0 @@ -64,7 +64,7 @@ statevar = 0 ### Description This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied adresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state. -In */inputs/calls.sol:25* +In */inputs/calls.sol:25* ``` addr.call() @@ -78,7 +78,7 @@ addr.call() ### Description The return value of an external call is not checked. Note that execution continue even if the called contract throws. -In */inputs/calls.sol:16* +In */inputs/calls.sol:16* ``` fixed_address.call() @@ -92,7 +92,7 @@ fixed_address.call() ### Description The return value of an external call is not checked. Note that execution continue even if the called contract throws. -In */inputs/calls.sol:29* +In */inputs/calls.sol:29* ``` stored_address.call() @@ -106,7 +106,7 @@ stored_address.call() ### Description The return value of an external call is not checked. Note that execution continue even if the called contract throws. -In */inputs/calls.sol:20* +In */inputs/calls.sol:20* ``` fixed_address.call() @@ -120,7 +120,7 @@ fixed_address.call() ### Description The return value of an external call is not checked. Note that execution continue even if the called contract throws. -In */inputs/calls.sol:25* +In */inputs/calls.sol:25* ``` addr.call() diff --git a/tests/testdata/outputs/calls.sol.text b/tests/testdata/outputs/calls.sol.text index 5ac70cf0..40b4ef78 100644 --- a/tests/testdata/outputs/calls.sol.text +++ b/tests/testdata/outputs/calls.sol.text @@ -5,7 +5,7 @@ Function name: _function_0x5a6814ec PC address: 661 This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code. -------------------- -In file: /inputs/calls.sol:16 +In file: /inputs/calls.sol:16 fixed_address.call() @@ -18,7 +18,7 @@ Function name: _function_0xd24b08cc PC address: 779 This contract executes a message call to an address found at storage slot 1. This storage slot can be written to by calling the function '_function_0x2776b163'. Generally, it is not recommended to call user-supplied adresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state. -------------------- -In file: /inputs/calls.sol:29 +In file: /inputs/calls.sol:29 stored_address.call() @@ -31,7 +31,7 @@ Function name: _function_0xe11f493e PC address: 858 This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code. -------------------- -In file: /inputs/calls.sol:20 +In file: /inputs/calls.sol:20 fixed_address.call() @@ -44,7 +44,7 @@ Function name: _function_0xe11f493e PC address: 869 The contract account state is changed after an external call. Consider that the called contract could re-enter the function before this state change takes place. This can lead to business logic vulnerabilities. -------------------- -In file: /inputs/calls.sol:21 +In file: /inputs/calls.sol:21 statevar = 0 @@ -57,7 +57,7 @@ Function name: _function_0xe1d10f79 PC address: 912 This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied adresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state. -------------------- -In file: /inputs/calls.sol:25 +In file: /inputs/calls.sol:25 addr.call() @@ -70,7 +70,7 @@ Function name: _function_0x5a6814ec PC address: 661 The return value of an external call is not checked. Note that execution continue even if the called contract throws. -------------------- -In file: /inputs/calls.sol:16 +In file: /inputs/calls.sol:16 fixed_address.call() @@ -83,7 +83,7 @@ Function name: _function_0xd24b08cc PC address: 779 The return value of an external call is not checked. Note that execution continue even if the called contract throws. -------------------- -In file: /inputs/calls.sol:29 +In file: /inputs/calls.sol:29 stored_address.call() @@ -96,7 +96,7 @@ Function name: _function_0xe11f493e PC address: 858 The return value of an external call is not checked. Note that execution continue even if the called contract throws. -------------------- -In file: /inputs/calls.sol:20 +In file: /inputs/calls.sol:20 fixed_address.call() @@ -109,7 +109,7 @@ Function name: _function_0xe1d10f79 PC address: 912 The return value of an external call is not checked. Note that execution continue even if the called contract throws. -------------------- -In file: /inputs/calls.sol:25 +In file: /inputs/calls.sol:25 addr.call() diff --git a/tests/testdata/outputs/ether_send.sol.json b/tests/testdata/outputs/ether_send.sol.json index 57f0d747..de2823bd 100644 --- a/tests/testdata/outputs/ether_send.sol.json +++ b/tests/testdata/outputs/ether_send.sol.json @@ -9,9 +9,9 @@ "type": "Warning", "address": 816, "debug": "", - "filename": "/inputs/ether_send.sol", + "filename": "/inputs/ether_send.sol", "lineno": 18, "code": "msg.sender.transfer(this.balance)" } ] -} \ No newline at end of file +} diff --git a/tests/testdata/outputs/ether_send.sol.markdown b/tests/testdata/outputs/ether_send.sol.markdown index e34e51a0..f240880c 100644 --- a/tests/testdata/outputs/ether_send.sol.markdown +++ b/tests/testdata/outputs/ether_send.sol.markdown @@ -10,7 +10,7 @@ In the function 'withdrawfunds()' a non-zero amount of Ether is sent to msg.send There is a check on storage index 1. This storage slot can be written to by calling the function 'crowdfunding()'. -In */inputs/ether_send.sol:18* +In */inputs/ether_send.sol:18* ``` msg.sender.transfer(this.balance) diff --git a/tests/testdata/outputs/ether_send.sol.text b/tests/testdata/outputs/ether_send.sol.text index a2ae5846..9fcc44a6 100644 --- a/tests/testdata/outputs/ether_send.sol.text +++ b/tests/testdata/outputs/ether_send.sol.text @@ -7,7 +7,7 @@ In the function 'withdrawfunds()' a non-zero amount of Ether is sent to msg.send There is a check on storage index 1. This storage slot can be written to by calling the function 'crowdfunding()'. -------------------- -In file: /inputs/ether_send.sol:18 +In file: /inputs/ether_send.sol:18 msg.sender.transfer(this.balance) diff --git a/tests/testdata/outputs/exceptions.sol.json b/tests/testdata/outputs/exceptions.sol.json index 1c603858..2e31057d 100644 --- a/tests/testdata/outputs/exceptions.sol.json +++ b/tests/testdata/outputs/exceptions.sol.json @@ -9,7 +9,7 @@ "type": "Informational", "address": 446, "debug": "", - "filename": "/inputs/exceptions.sol", + "filename": "/inputs/exceptions.sol", "lineno": 16, "code": "assert(input != 23)" }, @@ -20,7 +20,7 @@ "type": "Informational", "address": 484, "debug": "", - "filename": "/inputs/exceptions.sol", + "filename": "/inputs/exceptions.sol", "lineno": 34, "code": "myarray[index]" }, @@ -31,7 +31,7 @@ "type": "Informational", "address": 506, "debug": "", - "filename": "/inputs/exceptions.sol", + "filename": "/inputs/exceptions.sol", "lineno": 24, "code": "1/input" }, @@ -42,9 +42,9 @@ "type": "Informational", "address": 531, "debug": "", - "filename": "/inputs/exceptions.sol", + "filename": "/inputs/exceptions.sol", "lineno": 7, "code": "assert(i == 0)" } ] -} \ No newline at end of file +} diff --git a/tests/testdata/outputs/exceptions.sol.markdown b/tests/testdata/outputs/exceptions.sol.markdown index 4d0fc877..2f228da0 100644 --- a/tests/testdata/outputs/exceptions.sol.markdown +++ b/tests/testdata/outputs/exceptions.sol.markdown @@ -8,7 +8,7 @@ ### Description A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -In */inputs/exceptions.sol:16* +In */inputs/exceptions.sol:16* ``` assert(input != 23) @@ -22,7 +22,7 @@ assert(input != 23) ### Description A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -In */inputs/exceptions.sol:34* +In */inputs/exceptions.sol:34* ``` myarray[index] @@ -36,7 +36,7 @@ myarray[index] ### Description A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -In */inputs/exceptions.sol:24* +In */inputs/exceptions.sol:24* ``` 1/input @@ -50,7 +50,7 @@ In */inputs/exceptions.sol:24* ### Description A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -In */inputs/exceptions.sol:7* +In */inputs/exceptions.sol:7* ``` assert(i == 0) diff --git a/tests/testdata/outputs/exceptions.sol.text b/tests/testdata/outputs/exceptions.sol.text index e2df4630..409dc190 100644 --- a/tests/testdata/outputs/exceptions.sol.text +++ b/tests/testdata/outputs/exceptions.sol.text @@ -5,7 +5,7 @@ Function name: _function_0x546455b5 PC address: 446 A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -------------------- -In file: /inputs/exceptions.sol:16 +In file: /inputs/exceptions.sol:16 assert(input != 23) @@ -18,7 +18,7 @@ Function name: _function_0x92dd38ea PC address: 484 A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -------------------- -In file: /inputs/exceptions.sol:34 +In file: /inputs/exceptions.sol:34 myarray[index] @@ -31,7 +31,7 @@ Function name: _function_0xa08299f1 PC address: 506 A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -------------------- -In file: /inputs/exceptions.sol:24 +In file: /inputs/exceptions.sol:24 1/input @@ -44,7 +44,7 @@ Function name: _function_0xb34c3610 PC address: 531 A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -------------------- -In file: /inputs/exceptions.sol:7 +In file: /inputs/exceptions.sol:7 assert(i == 0) diff --git a/tests/testdata/outputs/kinds_of_calls.sol.json b/tests/testdata/outputs/kinds_of_calls.sol.json index ea50da54..057c94fc 100644 --- a/tests/testdata/outputs/kinds_of_calls.sol.json +++ b/tests/testdata/outputs/kinds_of_calls.sol.json @@ -9,7 +9,7 @@ "type": "Warning", "address": 1038, "debug": "", - "filename": "/inputs/kinds_of_calls.sol", + "filename": "/inputs/kinds_of_calls.sol", "lineno": 6, "code": "_e.call(bytes4(sha3(\"setN(uint256)\")), _n)" }, @@ -20,9 +20,9 @@ "type": "Informational", "address": 1038, "debug": "", - "filename": "/inputs/kinds_of_calls.sol", + "filename": "/inputs/kinds_of_calls.sol", "lineno": 6, "code": "_e.call(bytes4(sha3(\"setN(uint256)\")), _n)" } ] -} \ No newline at end of file +} diff --git a/tests/testdata/outputs/kinds_of_calls.sol.markdown b/tests/testdata/outputs/kinds_of_calls.sol.markdown index 5353ea30..0aaa5405 100644 --- a/tests/testdata/outputs/kinds_of_calls.sol.markdown +++ b/tests/testdata/outputs/kinds_of_calls.sol.markdown @@ -8,7 +8,7 @@ ### Description This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied adresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state. -In */inputs/kinds_of_calls.sol:6* +In */inputs/kinds_of_calls.sol:6* ``` _e.call(bytes4(sha3("setN(uint256)")), _n) @@ -22,7 +22,7 @@ _e.call(bytes4(sha3("setN(uint256)")), _n) ### Description The return value of an external call is not checked. Note that execution continue even if the called contract throws. -In */inputs/kinds_of_calls.sol:6* +In */inputs/kinds_of_calls.sol:6* ``` _e.call(bytes4(sha3("setN(uint256)")), _n) diff --git a/tests/testdata/outputs/kinds_of_calls.sol.text b/tests/testdata/outputs/kinds_of_calls.sol.text index 088b3541..4cc889fd 100644 --- a/tests/testdata/outputs/kinds_of_calls.sol.text +++ b/tests/testdata/outputs/kinds_of_calls.sol.text @@ -5,7 +5,7 @@ Function name: _function_0xeea4c864 PC address: 1038 This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied adresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state. -------------------- -In file: /inputs/kinds_of_calls.sol:6 +In file: /inputs/kinds_of_calls.sol:6 _e.call(bytes4(sha3("setN(uint256)")), _n) @@ -18,7 +18,7 @@ Function name: _function_0xeea4c864 PC address: 1038 The return value of an external call is not checked. Note that execution continue even if the called contract throws. -------------------- -In file: /inputs/kinds_of_calls.sol:6 +In file: /inputs/kinds_of_calls.sol:6 _e.call(bytes4(sha3("setN(uint256)")), _n) diff --git a/tests/testdata/outputs/multi_contracts.sol.json b/tests/testdata/outputs/multi_contracts.sol.json index 2b09e970..de5780c1 100644 --- a/tests/testdata/outputs/multi_contracts.sol.json +++ b/tests/testdata/outputs/multi_contracts.sol.json @@ -9,9 +9,9 @@ "type": "Warning", "address": 142, "debug": "", - "filename": "/inputs/multi_contracts.sol", + "filename": "/inputs/multi_contracts.sol", "lineno": 14, "code": "msg.sender.transfer(2 ether)" } ] -} \ No newline at end of file +} diff --git a/tests/testdata/outputs/multi_contracts.sol.markdown b/tests/testdata/outputs/multi_contracts.sol.markdown index 459b0084..25b6f401 100644 --- a/tests/testdata/outputs/multi_contracts.sol.markdown +++ b/tests/testdata/outputs/multi_contracts.sol.markdown @@ -9,7 +9,7 @@ In the function '_function_0x8a4068dd' a non-zero amount of Ether is sent to msg.sender. It seems that this function can be called without restrictions. -In */inputs/multi_contracts.sol:14* +In */inputs/multi_contracts.sol:14* ``` msg.sender.transfer(2 ether) diff --git a/tests/testdata/outputs/multi_contracts.sol.text b/tests/testdata/outputs/multi_contracts.sol.text index e1f0ceb1..89168baa 100644 --- a/tests/testdata/outputs/multi_contracts.sol.text +++ b/tests/testdata/outputs/multi_contracts.sol.text @@ -6,7 +6,7 @@ PC address: 142 In the function '_function_0x8a4068dd' a non-zero amount of Ether is sent to msg.sender. It seems that this function can be called without restrictions. -------------------- -In file: /inputs/multi_contracts.sol:14 +In file: /inputs/multi_contracts.sol:14 msg.sender.transfer(2 ether) diff --git a/tests/testdata/outputs/origin.sol.json b/tests/testdata/outputs/origin.sol.json index 20cc0b9e..acd376b2 100644 --- a/tests/testdata/outputs/origin.sol.json +++ b/tests/testdata/outputs/origin.sol.json @@ -9,9 +9,9 @@ "type": "Warning", "address": 317, "debug": "", - "filename": "/inputs/origin.sol", + "filename": "/inputs/origin.sol", "lineno": 18, "code": "tx.origin" } ] -} \ No newline at end of file +} diff --git a/tests/testdata/outputs/origin.sol.markdown b/tests/testdata/outputs/origin.sol.markdown index 3f2eb992..19e1810c 100644 --- a/tests/testdata/outputs/origin.sol.markdown +++ b/tests/testdata/outputs/origin.sol.markdown @@ -9,7 +9,7 @@ Function transferOwnership(address) retrieves the transaction origin (tx.origin) using the ORIGIN opcode. Use tx.sender instead. See also: https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin -In */inputs/origin.sol:18* +In */inputs/origin.sol:18* ``` tx.origin diff --git a/tests/testdata/outputs/origin.sol.text b/tests/testdata/outputs/origin.sol.text index 486f0c51..42a7ecc3 100644 --- a/tests/testdata/outputs/origin.sol.text +++ b/tests/testdata/outputs/origin.sol.text @@ -6,7 +6,7 @@ PC address: 317 Function transferOwnership(address) retrieves the transaction origin (tx.origin) using the ORIGIN opcode. Use tx.sender instead. See also: https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin -------------------- -In file: /inputs/origin.sol:18 +In file: /inputs/origin.sol:18 tx.origin diff --git a/tests/testdata/outputs/returnvalue.sol.json b/tests/testdata/outputs/returnvalue.sol.json index 561779de..d13d7c2a 100644 --- a/tests/testdata/outputs/returnvalue.sol.json +++ b/tests/testdata/outputs/returnvalue.sol.json @@ -9,7 +9,7 @@ "type": "Informational", "address": 196, "debug": "", - "filename": "/inputs/returnvalue.sol", + "filename": "/inputs/returnvalue.sol", "lineno": 10, "code": "callee.call()" }, @@ -20,7 +20,7 @@ "type": "Informational", "address": 285, "debug": "", - "filename": "/inputs/returnvalue.sol", + "filename": "/inputs/returnvalue.sol", "lineno": 6, "code": "callee.call()" }, @@ -31,9 +31,9 @@ "type": "Informational", "address": 285, "debug": "", - "filename": "/inputs/returnvalue.sol", + "filename": "/inputs/returnvalue.sol", "lineno": 6, "code": "callee.call()" } ] -} \ No newline at end of file +} diff --git a/tests/testdata/outputs/returnvalue.sol.markdown b/tests/testdata/outputs/returnvalue.sol.markdown index e76bd268..faa81ee9 100644 --- a/tests/testdata/outputs/returnvalue.sol.markdown +++ b/tests/testdata/outputs/returnvalue.sol.markdown @@ -8,7 +8,7 @@ ### Description This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code. -In */inputs/returnvalue.sol:10* +In */inputs/returnvalue.sol:10* ``` callee.call() @@ -22,7 +22,7 @@ callee.call() ### Description This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code. -In */inputs/returnvalue.sol:6* +In */inputs/returnvalue.sol:6* ``` callee.call() @@ -36,7 +36,7 @@ callee.call() ### Description The return value of an external call is not checked. Note that execution continue even if the called contract throws. -In */inputs/returnvalue.sol:6* +In */inputs/returnvalue.sol:6* ``` callee.call() diff --git a/tests/testdata/outputs/returnvalue.sol.text b/tests/testdata/outputs/returnvalue.sol.text index 14abe1a0..aabdac0f 100644 --- a/tests/testdata/outputs/returnvalue.sol.text +++ b/tests/testdata/outputs/returnvalue.sol.text @@ -5,7 +5,7 @@ Function name: _function_0x633ab5e0 PC address: 196 This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code. -------------------- -In file: /inputs/returnvalue.sol:10 +In file: /inputs/returnvalue.sol:10 callee.call() @@ -18,7 +18,7 @@ Function name: _function_0xe3bea282 PC address: 285 This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code. -------------------- -In file: /inputs/returnvalue.sol:6 +In file: /inputs/returnvalue.sol:6 callee.call() @@ -31,7 +31,7 @@ Function name: _function_0xe3bea282 PC address: 285 The return value of an external call is not checked. Note that execution continue even if the called contract throws. -------------------- -In file: /inputs/returnvalue.sol:6 +In file: /inputs/returnvalue.sol:6 callee.call() diff --git a/tests/testdata/outputs/rubixi.sol.json b/tests/testdata/outputs/rubixi.sol.json index b4a64b14..009a4609 100644 --- a/tests/testdata/outputs/rubixi.sol.json +++ b/tests/testdata/outputs/rubixi.sol.json @@ -9,7 +9,7 @@ "type": "Warning", "address": 1599, "debug": "", - "filename": "/inputs/rubixi.sol", + "filename": "/inputs/rubixi.sol", "lineno": 93, "code": "creator.send(feesToCollect)" }, @@ -20,7 +20,7 @@ "type": "Warning", "address": 1940, "debug": "", - "filename": "/inputs/rubixi.sol", + "filename": "/inputs/rubixi.sol", "lineno": 75, "code": "creator.send(collectedFees)" }, @@ -31,7 +31,7 @@ "type": "Informational", "address": 1653, "debug": "", - "filename": "/inputs/rubixi.sol", + "filename": "/inputs/rubixi.sol", "lineno": 131, "code": "participants[payoutOrder]" }, @@ -42,7 +42,7 @@ "type": "Informational", "address": 2085, "debug": "", - "filename": "/inputs/rubixi.sol", + "filename": "/inputs/rubixi.sol", "lineno": 148, "code": "participants[orderInPyramid]" }, @@ -53,7 +53,7 @@ "type": "Warning", "address": 2743, "debug": "", - "filename": "/inputs/rubixi.sol", + "filename": "/inputs/rubixi.sol", "lineno": 143, "code": "participants.length - payoutOrder" }, @@ -64,7 +64,7 @@ "type": "Informational", "address": 1599, "debug": "", - "filename": "/inputs/rubixi.sol", + "filename": "/inputs/rubixi.sol", "lineno": 93, "code": "creator.send(feesToCollect)" }, @@ -75,7 +75,7 @@ "type": "Informational", "address": 1940, "debug": "", - "filename": "/inputs/rubixi.sol", + "filename": "/inputs/rubixi.sol", "lineno": 75, "code": "creator.send(collectedFees)" }, @@ -86,9 +86,9 @@ "type": "Informational", "address": 2582, "debug": "", - "filename": "/inputs/rubixi.sol", + "filename": "/inputs/rubixi.sol", "lineno": 85, "code": "creator.send(_amt)" } ] -} \ No newline at end of file +} diff --git a/tests/testdata/outputs/rubixi.sol.markdown b/tests/testdata/outputs/rubixi.sol.markdown index 5e6f22f5..581442c9 100644 --- a/tests/testdata/outputs/rubixi.sol.markdown +++ b/tests/testdata/outputs/rubixi.sol.markdown @@ -12,7 +12,7 @@ There is a check on storage index 5. This storage slot can be written to by call There is a check on storage index 5. This storage slot can be written to by calling the function '_function_0x67f809e9'. There is a check on storage index 1. This storage slot can be written to by calling the function 'fallback'. -In */inputs/rubixi.sol:93* +In */inputs/rubixi.sol:93* ``` creator.send(feesToCollect) @@ -30,7 +30,7 @@ There is a check on storage index 5. This storage slot can be written to by call There is a check on storage index 5. This storage slot can be written to by calling the function '_function_0x67f809e9'. There is a check on storage index 1. This storage slot can be written to by calling the function 'fallback'. -In */inputs/rubixi.sol:75* +In */inputs/rubixi.sol:75* ``` creator.send(collectedFees) @@ -44,7 +44,7 @@ creator.send(collectedFees) ### Description A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -In */inputs/rubixi.sol:131* +In */inputs/rubixi.sol:131* ``` participants[payoutOrder] @@ -58,7 +58,7 @@ participants[payoutOrder] ### Description A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -In */inputs/rubixi.sol:148* +In */inputs/rubixi.sol:148* ``` participants[orderInPyramid] @@ -73,7 +73,7 @@ participants[orderInPyramid] A possible integer underflow exists in the function _function_0xd11f13df. The substraction may result in a value < 0. -In */inputs/rubixi.sol:143* +In */inputs/rubixi.sol:143* ``` participants.length - payoutOrder @@ -87,7 +87,7 @@ participants.length - payoutOrder ### Description The return value of an external call is not checked. Note that execution continue even if the called contract throws. -In */inputs/rubixi.sol:93* +In */inputs/rubixi.sol:93* ``` creator.send(feesToCollect) @@ -101,7 +101,7 @@ creator.send(feesToCollect) ### Description The return value of an external call is not checked. Note that execution continue even if the called contract throws. -In */inputs/rubixi.sol:75* +In */inputs/rubixi.sol:75* ``` creator.send(collectedFees) @@ -115,7 +115,7 @@ creator.send(collectedFees) ### Description The return value of an external call is not checked. Note that execution continue even if the called contract throws. -In */inputs/rubixi.sol:85* +In */inputs/rubixi.sol:85* ``` creator.send(_amt) diff --git a/tests/testdata/outputs/rubixi.sol.text b/tests/testdata/outputs/rubixi.sol.text index 3193f1c8..d2de7361 100644 --- a/tests/testdata/outputs/rubixi.sol.text +++ b/tests/testdata/outputs/rubixi.sol.text @@ -9,7 +9,7 @@ There is a check on storage index 5. This storage slot can be written to by call There is a check on storage index 5. This storage slot can be written to by calling the function '_function_0x67f809e9'. There is a check on storage index 1. This storage slot can be written to by calling the function 'fallback'. -------------------- -In file: /inputs/rubixi.sol:93 +In file: /inputs/rubixi.sol:93 creator.send(feesToCollect) @@ -26,7 +26,7 @@ There is a check on storage index 5. This storage slot can be written to by call There is a check on storage index 5. This storage slot can be written to by calling the function '_function_0x67f809e9'. There is a check on storage index 1. This storage slot can be written to by calling the function 'fallback'. -------------------- -In file: /inputs/rubixi.sol:75 +In file: /inputs/rubixi.sol:75 creator.send(collectedFees) @@ -39,7 +39,7 @@ Function name: _function_0x57d4021b PC address: 1653 A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -------------------- -In file: /inputs/rubixi.sol:131 +In file: /inputs/rubixi.sol:131 participants[payoutOrder] @@ -52,7 +52,7 @@ Function name: _function_0x9dbc4f9b PC address: 2085 A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -------------------- -In file: /inputs/rubixi.sol:148 +In file: /inputs/rubixi.sol:148 participants[orderInPyramid] @@ -66,7 +66,7 @@ PC address: 2743 A possible integer underflow exists in the function _function_0xd11f13df. The substraction may result in a value < 0. -------------------- -In file: /inputs/rubixi.sol:143 +In file: /inputs/rubixi.sol:143 participants.length - payoutOrder @@ -79,7 +79,7 @@ Function name: _function_0x4229616d PC address: 1599 The return value of an external call is not checked. Note that execution continue even if the called contract throws. -------------------- -In file: /inputs/rubixi.sol:93 +In file: /inputs/rubixi.sol:93 creator.send(feesToCollect) @@ -92,7 +92,7 @@ Function name: _function_0xb4022950 PC address: 1940 The return value of an external call is not checked. Note that execution continue even if the called contract throws. -------------------- -In file: /inputs/rubixi.sol:75 +In file: /inputs/rubixi.sol:75 creator.send(collectedFees) @@ -105,7 +105,7 @@ Function name: _function_0xb4022950 PC address: 2582 The return value of an external call is not checked. Note that execution continue even if the called contract throws. -------------------- -In file: /inputs/rubixi.sol:85 +In file: /inputs/rubixi.sol:85 creator.send(_amt) diff --git a/tests/testdata/outputs/suicide.sol.json b/tests/testdata/outputs/suicide.sol.json index b5dc2f3d..a781045c 100644 --- a/tests/testdata/outputs/suicide.sol.json +++ b/tests/testdata/outputs/suicide.sol.json @@ -9,9 +9,9 @@ "type": "Warning", "address": 146, "debug": "", - "filename": "/inputs/suicide.sol", + "filename": "/inputs/suicide.sol", "lineno": 4, "code": "selfdestruct(addr)" } ] -} \ No newline at end of file +} diff --git a/tests/testdata/outputs/suicide.sol.markdown b/tests/testdata/outputs/suicide.sol.markdown index ee5285de..1a9905fd 100644 --- a/tests/testdata/outputs/suicide.sol.markdown +++ b/tests/testdata/outputs/suicide.sol.markdown @@ -10,7 +10,7 @@ The function _function_0xcbf0b0c0 executes the SUICIDE instruction. The remainin It seems that this function can be called without restrictions. -In */inputs/suicide.sol:4* +In */inputs/suicide.sol:4* ``` selfdestruct(addr) diff --git a/tests/testdata/outputs/suicide.sol.text b/tests/testdata/outputs/suicide.sol.text index 6c0f2973..f9b206f7 100644 --- a/tests/testdata/outputs/suicide.sol.text +++ b/tests/testdata/outputs/suicide.sol.text @@ -7,7 +7,7 @@ The function _function_0xcbf0b0c0 executes the SUICIDE instruction. The remainin It seems that this function can be called without restrictions. -------------------- -In file: /inputs/suicide.sol:4 +In file: /inputs/suicide.sol:4 selfdestruct(addr) diff --git a/tests/testdata/outputs/underflow.sol.json b/tests/testdata/outputs/underflow.sol.json index 7083e7ec..81eaa0b7 100644 --- a/tests/testdata/outputs/underflow.sol.json +++ b/tests/testdata/outputs/underflow.sol.json @@ -9,7 +9,7 @@ "type": "Warning", "address": 649, "debug": "", - "filename": "/inputs/underflow.sol", + "filename": "/inputs/underflow.sol", "lineno": 12, "code": "balances[msg.sender] -= _value" }, @@ -20,9 +20,9 @@ "type": "Warning", "address": 567, "debug": "", - "filename": "/inputs/underflow.sol", + "filename": "/inputs/underflow.sol", "lineno": 11, "code": "balances[msg.sender] - _value" } ] -} \ No newline at end of file +} diff --git a/tests/testdata/outputs/underflow.sol.markdown b/tests/testdata/outputs/underflow.sol.markdown index aa6c208c..54d9cdf2 100644 --- a/tests/testdata/outputs/underflow.sol.markdown +++ b/tests/testdata/outputs/underflow.sol.markdown @@ -9,7 +9,7 @@ A possible integer underflow exists in the function sendeth(address,uint256). The substraction may result in a value < 0. -In */inputs/underflow.sol:12* +In */inputs/underflow.sol:12* ``` balances[msg.sender] -= _value @@ -24,7 +24,7 @@ balances[msg.sender] -= _value A possible integer underflow exists in the function sendeth(address,uint256). The substraction may result in a value < 0. -In */inputs/underflow.sol:11* +In */inputs/underflow.sol:11* ``` balances[msg.sender] - _value diff --git a/tests/testdata/outputs/underflow.sol.text b/tests/testdata/outputs/underflow.sol.text index 90d81787..70f0256c 100644 --- a/tests/testdata/outputs/underflow.sol.text +++ b/tests/testdata/outputs/underflow.sol.text @@ -6,7 +6,7 @@ PC address: 649 A possible integer underflow exists in the function sendeth(address,uint256). The substraction may result in a value < 0. -------------------- -In file: /inputs/underflow.sol:12 +In file: /inputs/underflow.sol:12 balances[msg.sender] -= _value @@ -20,7 +20,7 @@ PC address: 567 A possible integer underflow exists in the function sendeth(address,uint256). The substraction may result in a value < 0. -------------------- -In file: /inputs/underflow.sol:11 +In file: /inputs/underflow.sol:11 balances[msg.sender] - _value diff --git a/tests/testdata/outputs/weak_random.sol.json b/tests/testdata/outputs/weak_random.sol.json index 89a817ed..ac69d48f 100644 --- a/tests/testdata/outputs/weak_random.sol.json +++ b/tests/testdata/outputs/weak_random.sol.json @@ -9,7 +9,7 @@ "type": "Warning", "address": 1285, "debug": "", - "filename": "/inputs/weak_random.sol", + "filename": "/inputs/weak_random.sol", "lineno": 47, "code": "winningAddress.transfer(prize)" }, @@ -20,7 +20,7 @@ "type": "Warning", "address": 1285, "debug": "", - "filename": "/inputs/weak_random.sol", + "filename": "/inputs/weak_random.sol", "lineno": 47, "code": "winningAddress.transfer(prize)" }, @@ -31,7 +31,7 @@ "type": "Informational", "address": 356, "debug": "", - "filename": "/inputs/weak_random.sol", + "filename": "/inputs/weak_random.sol", "lineno": 11, "code": "prize / totalTickets" }, @@ -42,9 +42,9 @@ "type": "Informational", "address": 146, "debug": "", - "filename": "/inputs/weak_random.sol", + "filename": "/inputs/weak_random.sol", "lineno": 11, "code": "prize / totalTickets" } ] -} \ No newline at end of file +} diff --git a/tests/testdata/outputs/weak_random.sol.markdown b/tests/testdata/outputs/weak_random.sol.markdown index 06b597c7..e4eb77d8 100644 --- a/tests/testdata/outputs/weak_random.sol.markdown +++ b/tests/testdata/outputs/weak_random.sol.markdown @@ -10,7 +10,7 @@ In the function '_function_0xe9874106' the following predictable state variables - block.coinbase -In */inputs/weak_random.sol:47* +In */inputs/weak_random.sol:47* ``` winningAddress.transfer(prize) @@ -28,7 +28,7 @@ There is a check on storage index 0. This storage slot can be written to by call There is a check on storage index 1. This storage slot can be written to by calling the function 'fallback'. There is a check on storage index 1. This storage slot can be written to by calling the function 'fallback'. -In */inputs/weak_random.sol:47* +In */inputs/weak_random.sol:47* ``` winningAddress.transfer(prize) @@ -42,7 +42,7 @@ winningAddress.transfer(prize) ### Description A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -In */inputs/weak_random.sol:11* +In */inputs/weak_random.sol:11* ``` prize / totalTickets @@ -56,7 +56,7 @@ prize / totalTickets ### Description A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -In */inputs/weak_random.sol:11* +In */inputs/weak_random.sol:11* ``` prize / totalTickets diff --git a/tests/testdata/outputs/weak_random.sol.text b/tests/testdata/outputs/weak_random.sol.text index 93faaff0..88859731 100644 --- a/tests/testdata/outputs/weak_random.sol.text +++ b/tests/testdata/outputs/weak_random.sol.text @@ -7,7 +7,7 @@ In the function '_function_0xe9874106' the following predictable state variables - block.coinbase -------------------- -In file: /inputs/weak_random.sol:47 +In file: /inputs/weak_random.sol:47 winningAddress.transfer(prize) @@ -24,7 +24,7 @@ There is a check on storage index 0. This storage slot can be written to by call There is a check on storage index 1. This storage slot can be written to by calling the function 'fallback'. There is a check on storage index 1. This storage slot can be written to by calling the function 'fallback'. -------------------- -In file: /inputs/weak_random.sol:47 +In file: /inputs/weak_random.sol:47 winningAddress.transfer(prize) @@ -37,7 +37,7 @@ Function name: fallback PC address: 356 A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -------------------- -In file: /inputs/weak_random.sol:11 +In file: /inputs/weak_random.sol:11 prize / totalTickets @@ -50,7 +50,7 @@ Function name: _function_0xe9874106 PC address: 146 A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that assert() should only be used to check invariants. Use require() for regular input checking. -------------------- -In file: /inputs/weak_random.sol:11 +In file: /inputs/weak_random.sol:11 prize / totalTickets diff --git a/tests/teststorage/contractstorage.fs.index b/tests/teststorage/contractstorage.fs.index index cb464437599f88b1191c517f24653536af58c484..c7d9803d5b9aad25ee20e956fecf8890d44507f6 100644 GIT binary patch literal 72 zcmZo*_FZnT*TC$|#sCJ+20)6Dfr){cfrWt;EVLIyGS-7g=7S)TDF)025ezITZ9v_A FdH^DQ2e1GD literal 31 dcmZo*_Fksf!0gP%00zz+5SqcH4JhiT2LMor1fc)`