def test_process_cli(self): g = config.get_group("grp") g.add("shouldchange", default=123) with tempfile.NamedTemporaryFile("w+") as conf: conf.file.write( 'cli: {overwritten: 1, unchanged: "val"}\ngrp: {val: 1}') conf.file.close() parser = argparse.ArgumentParser("Desc") parser.add_argument("--overwritten", type=int, default=0) parser.add_argument("--config", default=None) parser.add_argument("--unchanged", default=None) config.add_config_vars_to_argparse(parser) args = parser.parse_args([ "--overwritten=42", "--grp.shouldchange=23", f"--config={conf.name}" ]) config.process_config_values(parser, args) # Make sure that cmdline flags get precedence g = config.get_group("cli") self.assertEqual(g.overwritten, 42) self.assertEqual(g.unchanged, "val") # Make sure that we can update defined vars g = config.get_group("grp") self.assertEqual(g.val, 1) self.assertEqual(g.shouldchange, 23)
def test_process_cli(self): g = config.get_group('grp') g.add('shouldchange', default=123) with tempfile.NamedTemporaryFile('w+') as conf: conf.file.write( 'cli: {overwritten: 1, unchanged: "val"}\ngrp: {val: 1}') conf.file.close() parser = argparse.ArgumentParser('Desc') parser.add_argument('--overwritten', type=int, default=0) parser.add_argument('--config', default=None) parser.add_argument('--unchanged', default=None) config.add_config_vars_to_argparse(parser) args = parser.parse_args([ '--overwritten=42', '--grp.shouldchange=23', f'--config={conf.name}' ]) config.process_config_values(parser, args) # Make sure that cmdline flags get precedence g = config.get_group('cli') self.assertEqual(g.overwritten, 42) self.assertEqual(g.unchanged, 'val') # Make sure that we can update defined vars g = config.get_group('grp') self.assertEqual(g.val, 1) self.assertEqual(g.shouldchange, 23)
def test_add_config_vars(self): g = config.get_group("few") g.add("one", default=0, description="desc") g.add("two", default="x", description="desc2t") parser = argparse.ArgumentParser("Description") config.add_config_vars_to_argparse(parser) usage = parser.format_help() # There are no public methods to get at the added options so far, so we're just checking with # usage string self.assertIn("--few.one", usage) self.assertIn("--few.two", usage)
def main(): from crytic_compile import is_supported, cryticparser parser = argparse.ArgumentParser( description="Solidity property verifier", prog="manticore_verifier", # formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) # Add crytic compile arguments # See https://github.com/crytic/crytic-compile/wiki/Configuration cryticparser.init(parser) parser.add_argument( "source_code", type=str, nargs="*", default=[], help="Contract source code", ) parser.add_argument("-v", action="count", default=0, help="Specify verbosity level from -v to -vvvv") parser.add_argument( "--workspace", type=str, default=None, help=("A folder name for temporaries and results." "(default mcore_?????)"), ) current_version = pkg_resources.get_distribution("manticore").version parser.add_argument( "--version", action="version", version=f"Manticore {current_version}", help="Show program version information", ) parser.add_argument( "--propconfig", type=str, help="Solidity property accounts config file (.yml)", ) eth_flags = parser.add_argument_group("Ethereum flags") eth_flags.add_argument( "--quick-mode", action="store_true", help= "Configure Manticore for quick exploration. Disable gas, generate testcase only for alive states, " "do not explore constant functions. Disable all detectors.", ) eth_flags.add_argument( "--contract_name", type=str, help="The target contract name defined in the source code") eth_flags.add_argument( "--maxfail", type=int, help="stop after maxfail properties are failing. All if None") eth_flags.add_argument( "--maxcov", type=int, default=100, help=" Stop after maxcov %% coverage is obtained in the main contract", ) eth_flags.add_argument("--maxt", type=int, default=3, help="Max transaction count to explore") eth_flags.add_argument( "--deployer", type=str, help="(optional) address of account used to deploy the contract") eth_flags.add_argument( "--senders", type=str, help= "(optional) a comma separated list of sender addresses. The properties are going to be tested sending transactions from these addresses.", ) eth_flags.add_argument( "--psender", type=str, help="(optional) address from where the property is tested") eth_flags.add_argument( "--propre", default=r"crytic_.*", type=str, help="A regular expression for selecting properties", ) eth_flags.add_argument("--timeout", default=240, type=int, help="Exploration timeout in seconds") eth_flags.add_argument("--outputspace_url", type=str, help="where to put the extended result") config_flags = parser.add_argument_group("Constants") config.add_config_vars_to_argparse(config_flags) parsed = parser.parse_args(sys.argv[1:]) config.process_config_values(parser, parsed) if not parsed.source_code: print(parser.format_usage() + "error: You need to provide a contract source code.") sys.exit(1) args = parsed set_verbosity(args.v) logger = logging.getLogger("manticore.main") # read yaml config file deployer = None senders = None psenders = None if args.propconfig: """ deployer: "0x41414141414141414141" #who deploys the contract sender: ["0x51515151515151515151", "0x52525252525252525252"] #who calls the transactions (potentially can be multiple users) psender: "0x616161616161616161" #who calls the property """ import yaml with open(args.propconfig) as f: c = yaml.safe_load(f) deployer = c.get("deployer") if deployer is not None: deployer = int(deployer, 0) senders = c.get("sender") if senders is not None: senders = [int(sender, 0) for sender in senders] psender = c.get("psender") if psender is not None: psender = int(psender, 0) # override with commandline args deployer = None if args.deployer is not None: deployer = int(args.deployer, 0) senders = None if args.senders is not None: senders = [int(sender, 0) for sender in args.senders.split(",")] psender = None if args.psender is not None: psender = int(args.psender, 0) source_code = args.source_code[0] contract_name = args.contract_name maxfail = args.maxfail maxt = args.maxt maxcov = args.maxcov return manticore_verifier(source_code, contract_name, maxfail=maxfail, maxt=maxt, maxcov=100, senders=senders, deployer=deployer, psender=psender, timeout=args.timeout, propre=args.propre, compile_args=vars(parsed))
def parse_arguments() -> argparse.Namespace: def positive(value): ivalue = int(value) if ivalue <= 0: raise argparse.ArgumentTypeError("Argument must be positive") return ivalue parser = argparse.ArgumentParser( description="Symbolic execution tool", prog="manticore", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) # Add crytic compile arguments # See https://github.com/crytic/crytic-compile/wiki/Configuration cryticparser.init(parser) parser.add_argument("--context", type=str, default=None, help=argparse.SUPPRESS) parser.add_argument("--coverage", type=str, default="visited.txt", help="Where to write the coverage data") parser.add_argument("--names", type=str, default=None, help=argparse.SUPPRESS) parser.add_argument("--offset", type=int, default=16, help=argparse.SUPPRESS) # FIXME (theo) Add some documentation on the different search policy options parser.add_argument( "--policy", type=str, default="random", help=("Search policy. random|adhoc|uncovered|dicount" "|icount|syscount|depth. (use + (max) or - (min)" " to specify order. e.g. +random)"), ) parser.add_argument( "argv", type=str, nargs="*", default=[], help= "Path to program, path to mutants folder and program arguments ('+' in arguments indicates symbolic byte).", ) parser.add_argument( "--workspace", type=str, default=None, help=("A folder name for temporaries and results." "(default mcore_?????)"), ) parser.add_argument( "--config", type=str, help= "Manticore config file (.yml) to use. (default config file pattern is: ./[.]m[anti]core.yml)", ) eth_flags = parser.add_argument_group("Ethereum flags") eth_flags.add_argument("--verbose-trace", action="store_true", help="Dump an extra verbose trace for each state") eth_flags.add_argument( "--txlimit", type=positive, help= "Maximum number of symbolic transactions to run (positive integer)", ) eth_flags.add_argument("--txnocoverage", action="store_true", help="Do not use coverage as stopping criteria") eth_flags.add_argument("--txnoether", action="store_true", help="Do not attempt to send ether to contract") eth_flags.add_argument( "--txaccount", type=str, default="attacker", help= 'Account used as caller in the symbolic transactions, either "attacker" or ' '"owner" or "combo1" (uses both)', ) eth_flags.add_argument( "--txpreconstrain", action="store_true", help= "Constrain human transactions to avoid exceptions in the contract function dispatcher", ) eth_flags.add_argument( "--contract", type=str, help="Contract name to analyze in case of multiple contracts") eth_flags.add_argument( "--avoid-constant", action="store_true", help="Avoid exploring constant functions for human transactions", ) eth_flags.add_argument( "--limit-loops", action="store_true", help="Limit loops depth", ) eth_flags.add_argument( "--no-testcases", action="store_true", help= "Do not generate testcases for discovered states when analysis finishes", ) eth_flags.add_argument( "--only-alive-testcases", action="store_true", help= "Do not generate testcases for invalid/throwing states when analysis finishes", ) eth_flags.add_argument( "--quick-mode", action="store_true", help= "Configure Manticore for quick exploration. Disable gas, generate testcase only for alive states, " "do not explore constant functions. Disable all detectors.", ) config_flags = parser.add_argument_group("Constants") config.add_config_vars_to_argparse(config_flags) parsed = parser.parse_args(sys.argv[1:]) config.process_config_values(parser, parsed) if not parsed.argv: print(parser.format_usage() + "error: the following arguments are required: argv") sys.exit(1) if parsed.policy.startswith("min"): parsed.policy = "-" + parsed.policy[3:] elif parsed.policy.startswith("max"): parsed.policy = "+" + parsed.policy[3:] return parsed