certora-cli 7.20.3__tar.gz → 7.21.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {certora_cli-7.20.3/certora_cli.egg-info → certora_cli-7.21.1}/PKG-INFO +3 -2
- certora_cli-7.21.1/README.md +1 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraBuild.py +21 -16
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraCloudIO.py +1 -1
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraCollectRunMetadata.py +1 -1
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraContext.py +2 -2
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraContextAttributes.py +19 -18
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraContextValidator.py +2 -2
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/Mutate/mutateApp.py +167 -40
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/Mutate/mutateAttributes.py +10 -2
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/Mutate/mutateConstants.py +1 -2
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/Mutate/mutateUtil.py +1 -1
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/Mutate/mutateValidate.py +4 -2
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/Shared/certoraAttrUtil.py +1 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/Shared/certoraUtils.py +40 -10
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/Shared/certoraValidateFuncs.py +9 -3
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/certoraMutate.py +17 -14
- certora_cli-7.21.1/certora_cli/rustMutator.py +286 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1/certora_cli.egg-info}/PKG-INFO +3 -2
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli.egg-info/SOURCES.txt +1 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli.egg-info/requires.txt +1 -0
- certora_cli-7.21.1/certora_jars/CERTORA-CLI-VERSION-METADATA.json +1 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_jars/Typechecker.jar +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/setup.py +3 -3
- certora_cli-7.20.3/README.md +0 -1
- certora_cli-7.20.3/certora_jars/CERTORA-CLI-VERSION-METADATA.json +0 -1
- {certora_cli-7.20.3 → certora_cli-7.21.1}/LICENSE +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/MANIFEST.in +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_bins/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/Compiler/CompilerCollector.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/Compiler/CompilerCollectorFactory.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/Compiler/CompilerCollectorSol.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/Compiler/CompilerCollectorSolBased.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/Compiler/CompilerCollectorVy.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/Compiler/CompilerCollectorYul.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/Compiler/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraBuildCacheManager.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraBuildDataClasses.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraCompilerParameters.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraConfigIO.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraContextClass.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraContractFuncs.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraExtensionInfo.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraJobList.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraMiniSpecParser.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraNodeFilters.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraSourceFinders.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraType.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraVerifyGenerator.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EquivalenceCheck/Eq_default.conf +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EquivalenceCheck/Eq_mc_no_out_template.spec +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EquivalenceCheck/Eq_mc_template.spec +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EquivalenceCheck/Eq_sanity.conf +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EquivalenceCheck/Eq_template.spec +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EquivalenceCheck/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EquivalenceCheck/equivCheck.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EquivalenceCheck/sanity.spec +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/Mutate/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/Shared/ExpectedComparator.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/Shared/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/Shared/certoraLogging.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/certoraEqCheck.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/certoraRun.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli.egg-info/dependency_links.txt +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli.egg-info/entry_points.txt +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli.egg-info/top_level.txt +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/certora_jars/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.21.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: certora-cli
|
|
3
|
-
Version: 7.
|
|
3
|
+
Version: 7.21.1
|
|
4
4
|
Summary: Runner for the Certora Prover
|
|
5
5
|
Home-page: https://pypi.org/project/certora-cli
|
|
6
6
|
Author: Certora
|
|
@@ -21,5 +21,6 @@ Requires-Dist: tabulate
|
|
|
21
21
|
Requires-Dist: tqdm
|
|
22
22
|
Requires-Dist: StrEnum
|
|
23
23
|
Requires-Dist: tomli
|
|
24
|
+
Requires-Dist: universalmutator
|
|
24
25
|
|
|
25
|
-
Commit
|
|
26
|
+
Commit 03eae31. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Commit 03eae31. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
|
|
@@ -515,11 +515,11 @@ class CertoraBuildGenerator:
|
|
|
515
515
|
ret = Path(self.function_finder_file_remappings[file])
|
|
516
516
|
else:
|
|
517
517
|
ret = Path(file)
|
|
518
|
-
abs_sources_dir = Util.get_certora_sources_dir().
|
|
518
|
+
abs_sources_dir = Util.get_certora_sources_dir().absolute()
|
|
519
519
|
if abs_sources_dir in ret.parents:
|
|
520
520
|
# Normalize the file-name to never include the extra `.certora_internal/.../.certora_sources` part
|
|
521
521
|
# of the path.
|
|
522
|
-
ret = ret.relative_to(abs_sources_dir)
|
|
522
|
+
ret = Util.abs_norm_path(ret.relative_to(abs_sources_dir))
|
|
523
523
|
|
|
524
524
|
# things look nicer if they are rooted in .certora_sources
|
|
525
525
|
# note that we only have those fully populated after starting to work on internal function finders
|
|
@@ -1104,12 +1104,12 @@ class CertoraBuildGenerator:
|
|
|
1104
1104
|
function name, inputs, outputs, stateMutability) for each contract
|
|
1105
1105
|
"""
|
|
1106
1106
|
func_signatures = []
|
|
1107
|
-
file_abs_path = Path(self.to_autofinder_file(str(contract_file))).
|
|
1107
|
+
file_abs_path = Path(self.to_autofinder_file(str(contract_file))).absolute()
|
|
1108
1108
|
if file_abs_path.suffix == VY:
|
|
1109
1109
|
smart_contract_lang: CompilerLang = CompilerLangVy()
|
|
1110
|
-
sdc_name = self.file_to_sdc_name[Path(contract_file).
|
|
1110
|
+
sdc_name = self.file_to_sdc_name[Path(contract_file).absolute()]
|
|
1111
1111
|
standard_json_data = self.get_standard_json_data(sdc_name, smart_contract_lang)
|
|
1112
|
-
abi = standard_json_data[CONTRACTS][str(Path(contract_file).
|
|
1112
|
+
abi = standard_json_data[CONTRACTS][str(Path(contract_file).absolute())][contract_name]['abi']
|
|
1113
1113
|
ast_logger.debug(f"abi is: \n{abi}")
|
|
1114
1114
|
for f in filter(lambda x: self.is_imported_abi_entry(x), abi):
|
|
1115
1115
|
func_signature = self.get_full_func_signature(f)
|
|
@@ -1347,6 +1347,11 @@ class CertoraBuildGenerator:
|
|
|
1347
1347
|
settings_dict["optimizer"] = {"enabled": True}
|
|
1348
1348
|
if int(self.context.solc_optimize) > 0:
|
|
1349
1349
|
settings_dict["optimizer"]['runs'] = int(self.context.solc_optimize)
|
|
1350
|
+
|
|
1351
|
+
# if optimizer is true, we should also define settings_dict["optimizer"]["details"]
|
|
1352
|
+
# for both optimize map and optimize
|
|
1353
|
+
optimizer = settings_dict.get("optimizer")
|
|
1354
|
+
if optimizer and isinstance(optimizer, dict) and optimizer.get('enabled'):
|
|
1350
1355
|
# if we are not disabling finder friendly optimizer specifically, enable it whenever viaIR is also enabled
|
|
1351
1356
|
if not self.context.strict_solc_optimizer and (
|
|
1352
1357
|
self.context.solc_via_ir or self.context.solc_experimental_via_ir):
|
|
@@ -1692,7 +1697,7 @@ class CertoraBuildGenerator:
|
|
|
1692
1697
|
is_vyper = smart_contract_lang == CompilerLangVy()
|
|
1693
1698
|
sdc_name = f"{Path(build_arg_contract_file).name}_{file_index}"
|
|
1694
1699
|
compilation_path = self.get_compilation_path(sdc_name)
|
|
1695
|
-
self.file_to_sdc_name[
|
|
1700
|
+
self.file_to_sdc_name[Util.abs_norm_path(build_arg_contract_file)] = sdc_name
|
|
1696
1701
|
# update remappings and collect_cmd:
|
|
1697
1702
|
if not is_vyper:
|
|
1698
1703
|
Util.safe_create_dir(compilation_path)
|
|
@@ -1714,7 +1719,7 @@ class CertoraBuildGenerator:
|
|
|
1714
1719
|
is equivalent to `main_path = self.context.solc_allow_path`, and that's the best we can do in that
|
|
1715
1720
|
case anyway.
|
|
1716
1721
|
"""
|
|
1717
|
-
main_path = (compile_wd / self.context.solc_allow_path).
|
|
1722
|
+
main_path = (compile_wd / self.context.solc_allow_path).absolute()
|
|
1718
1723
|
else:
|
|
1719
1724
|
main_path = self.context.solc_allow_path
|
|
1720
1725
|
self.context.solc_cmd_allow_paths = [f'"{main_path}"', '.']
|
|
@@ -1813,7 +1818,8 @@ class CertoraBuildGenerator:
|
|
|
1813
1818
|
contract_file = str(contract_file_obj)
|
|
1814
1819
|
build_logger.debug(f"Processing dependencies from file {contract_file}")
|
|
1815
1820
|
# make sure path name is in posix format.
|
|
1816
|
-
contract_file_abs =
|
|
1821
|
+
contract_file_abs = str(Util.abs_norm_path(contract_file))
|
|
1822
|
+
|
|
1817
1823
|
# using os.path.relpath because Path.relative_to cannot go up the directory tree (no ..)
|
|
1818
1824
|
contract_file_rel = os.path.relpath(Path(contract_file_abs), Path.cwd())
|
|
1819
1825
|
|
|
@@ -1849,7 +1855,7 @@ class CertoraBuildGenerator:
|
|
|
1849
1855
|
base_contracts = sorted(self.retrieve_base_contracts_list(build_arg_contract_file, contract_file,
|
|
1850
1856
|
contract_name), key=lambda x: x[0])
|
|
1851
1857
|
for c_file, _, _ in base_contracts:
|
|
1852
|
-
norm_c_file =
|
|
1858
|
+
norm_c_file = Util.abs_norm_path(c_file)
|
|
1853
1859
|
resolved_to_orig[str(norm_c_file)] = c_file
|
|
1854
1860
|
if norm_c_file not in seen_link_refs:
|
|
1855
1861
|
build_logger.debug(f"Adding a base contract link ref {norm_c_file} to worklist")
|
|
@@ -1860,7 +1866,7 @@ class CertoraBuildGenerator:
|
|
|
1860
1866
|
contract_object = data[CONTRACTS][contract_file][contract_name]
|
|
1861
1867
|
lib_link_refs = sorted(contract_object["evm"]["deployedBytecode"]["linkReferences"])
|
|
1862
1868
|
for lib_link_ref in lib_link_refs: # linkReference is a library reference
|
|
1863
|
-
norm_link_ref = Path(lib_link_ref).
|
|
1869
|
+
norm_link_ref = Path(lib_link_ref).absolute()
|
|
1864
1870
|
resolved_to_orig[str(norm_link_ref)] = lib_link_ref
|
|
1865
1871
|
if norm_link_ref not in seen_link_refs:
|
|
1866
1872
|
build_logger.debug(f"Adding library link ref {norm_link_ref} to worklist")
|
|
@@ -1879,8 +1885,7 @@ class CertoraBuildGenerator:
|
|
|
1879
1885
|
contract_refs = [c_file for c_file in
|
|
1880
1886
|
data[CONTRACTS].keys() if
|
|
1881
1887
|
ref in data[CONTRACTS][c_file].keys()]
|
|
1882
|
-
contract_files_resolved = sorted([
|
|
1883
|
-
contract_refs])
|
|
1888
|
+
contract_files_resolved = sorted([Util.abs_norm_path(x) for x in contract_refs])
|
|
1884
1889
|
|
|
1885
1890
|
# There may be two non unique paths but actually referring to the same absolute path.
|
|
1886
1891
|
# Normalizing as absolute
|
|
@@ -2302,7 +2307,7 @@ class CertoraBuildGenerator:
|
|
|
2302
2307
|
f" {c.name} that doesn't have a location")
|
|
2303
2308
|
return None
|
|
2304
2309
|
|
|
2305
|
-
instrumentation_path = Util.
|
|
2310
|
+
instrumentation_path = str(Util.abs_norm_path(loc[0]))
|
|
2306
2311
|
if instrumentation_path not in function_finder_instrumentation:
|
|
2307
2312
|
instrumentation_logger.debug(f"New instrumentation for location {loc[0]}, " +
|
|
2308
2313
|
f"instrumentation path {instrumentation_path}")
|
|
@@ -2879,7 +2884,7 @@ class CertoraBuildGenerator:
|
|
|
2879
2884
|
p = Path(path)
|
|
2880
2885
|
if p.is_absolute():
|
|
2881
2886
|
return path
|
|
2882
|
-
return str(Path.cwd() / p.
|
|
2887
|
+
return str(Path.cwd() / p.absolute())
|
|
2883
2888
|
|
|
2884
2889
|
@staticmethod
|
|
2885
2890
|
def merge_dicts_instrumentation(dict1: Dict[str, Dict[int, Instrumentation]],
|
|
@@ -3052,7 +3057,7 @@ class CertoraBuildGenerator:
|
|
|
3052
3057
|
"""
|
|
3053
3058
|
rel_to_cwd_path = Path(os.path.relpath(path, '.'))
|
|
3054
3059
|
new_path = Util.get_certora_sources_dir() / self.cwd_rel_in_sources / rel_to_cwd_path
|
|
3055
|
-
return str(new_path.
|
|
3060
|
+
return str(new_path.absolute())
|
|
3056
3061
|
|
|
3057
3062
|
def handle_links(self) -> None:
|
|
3058
3063
|
# Link processing
|
|
@@ -3481,7 +3486,7 @@ def build_from_scratch(certora_build_generator: CertoraBuildGenerator,
|
|
|
3481
3486
|
saw_paths_not_in_sources = False
|
|
3482
3487
|
paths_not_in_sources = set()
|
|
3483
3488
|
may_store_in_build_cache = True
|
|
3484
|
-
absolute_sources_dir = Util.get_certora_sources_dir().
|
|
3489
|
+
absolute_sources_dir = Util.get_certora_sources_dir().absolute()
|
|
3485
3490
|
for sdc in certora_build_generator.SDCs.values():
|
|
3486
3491
|
# the contract files in SDCs are relative to .certora_sources. Which isn't good for us here.
|
|
3487
3492
|
# Need to be relative to original paths
|
|
@@ -847,7 +847,7 @@ class CloudVerification:
|
|
|
847
847
|
self.vscode_extension_info_writer.add_field("verification_report_url", self.reportUrl)
|
|
848
848
|
self.vscode_extension_info_writer.write_file()
|
|
849
849
|
|
|
850
|
-
if wait_for_results == str(Vf.WaitForResultOptions.NONE):
|
|
850
|
+
if not wait_for_results or wait_for_results == str(Vf.WaitForResultOptions.NONE):
|
|
851
851
|
job_list.save_data()
|
|
852
852
|
job_list.save_recent_jobs_to_path()
|
|
853
853
|
self.print_output_links()
|
{certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraCollectRunMetadata.py
RENAMED
|
@@ -149,7 +149,7 @@ def collect_run_metadata(wd: Path, raw_args: List[str], context: CertoraContext)
|
|
|
149
149
|
group_id=None)
|
|
150
150
|
|
|
151
151
|
# collect information about current git snapshot
|
|
152
|
-
cwd_abs = wd.
|
|
152
|
+
cwd_abs = wd.absolute()
|
|
153
153
|
|
|
154
154
|
is_git_executable = False
|
|
155
155
|
git_present_out = None
|
|
@@ -528,7 +528,7 @@ def run_local_spec_check(with_typechecking: bool, context: CertoraContext) -> No
|
|
|
528
528
|
"To skip local checks run with the --disable_local_typechecking flag")
|
|
529
529
|
|
|
530
530
|
def set_cargo_name(context: CertoraContext) -> None:
|
|
531
|
-
mode = "
|
|
531
|
+
mode = "r" if platform.system().lower() == 'windows' else "rb"
|
|
532
532
|
with open(context.cargo_file, mode) as f:
|
|
533
533
|
cargo_data = tomllib.load(f)
|
|
534
534
|
|
|
@@ -550,7 +550,7 @@ def build_wasm(context: CertoraContext) -> None:
|
|
|
550
550
|
|
|
551
551
|
def run_wasm_compiler(context: CertoraContext) -> None:
|
|
552
552
|
env = os.environ.copy()
|
|
553
|
-
env['RUSTFLAGS'] = "-C strip=none -C debuginfo=2"
|
|
553
|
+
env['RUSTFLAGS'] = "-C strip=none --emit=llvm-ir -C debuginfo=2"
|
|
554
554
|
try:
|
|
555
555
|
context_logger.info("Executing build process...")
|
|
556
556
|
|
{certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraContextAttributes.py
RENAMED
|
@@ -130,6 +130,24 @@ class CommonAttributes(AttrUtil.Attributes):
|
|
|
130
130
|
affects_build_cache_key=False,
|
|
131
131
|
disables_build_cache=False
|
|
132
132
|
)
|
|
133
|
+
# used by certoraMutate, ignored by certoraRun
|
|
134
|
+
MUTATIONS = AttrUtil.AttributeDefinition(
|
|
135
|
+
arg_type=AttrUtil.AttrArgType.MAP,
|
|
136
|
+
argparse_args={
|
|
137
|
+
'action': AttrUtil.NotAllowed
|
|
138
|
+
},
|
|
139
|
+
affects_build_cache_key=False,
|
|
140
|
+
disables_build_cache=False
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
RUN_SOURCE = AttrUtil.AttributeDefinition(
|
|
144
|
+
attr_validation_func=Vf.validate_run_source,
|
|
145
|
+
argparse_args={
|
|
146
|
+
'action': AttrUtil.UniqueStore
|
|
147
|
+
},
|
|
148
|
+
affects_build_cache_key=False,
|
|
149
|
+
disables_build_cache=False
|
|
150
|
+
)
|
|
133
151
|
|
|
134
152
|
class DeprecatedAttributes(AttrUtil.Attributes):
|
|
135
153
|
AUTO_NONDET_DIFFICULT_INTERNAL_FUNCS = AttrUtil.AttributeDefinition(
|
|
@@ -707,15 +725,7 @@ class EvmAttributes(AttrUtil.Attributes):
|
|
|
707
725
|
affects_build_cache_key=True,
|
|
708
726
|
disables_build_cache=True
|
|
709
727
|
)
|
|
710
|
-
|
|
711
|
-
MUTATIONS = AttrUtil.AttributeDefinition(
|
|
712
|
-
arg_type=AttrUtil.AttrArgType.MAP,
|
|
713
|
-
argparse_args={
|
|
714
|
-
'action': AttrUtil.NotAllowed
|
|
715
|
-
},
|
|
716
|
-
affects_build_cache_key=False,
|
|
717
|
-
disables_build_cache=False
|
|
718
|
-
)
|
|
728
|
+
|
|
719
729
|
DISABLE_INTERNAL_FUNCTION_INSTRUMENTATION = AttrUtil.AttributeDefinition(
|
|
720
730
|
arg_type=AttrUtil.AttrArgType.BOOLEAN,
|
|
721
731
|
argparse_args={
|
|
@@ -852,15 +862,6 @@ class BackendAttributes(AttrUtil.Attributes):
|
|
|
852
862
|
disables_build_cache=False
|
|
853
863
|
)
|
|
854
864
|
|
|
855
|
-
RUN_SOURCE = AttrUtil.AttributeDefinition(
|
|
856
|
-
attr_validation_func=Vf.validate_run_source,
|
|
857
|
-
argparse_args={
|
|
858
|
-
'action': AttrUtil.UniqueStore
|
|
859
|
-
},
|
|
860
|
-
affects_build_cache_key=False,
|
|
861
|
-
disables_build_cache=False
|
|
862
|
-
)
|
|
863
|
-
|
|
864
865
|
LOOP_ITER = AttrUtil.AttributeDefinition(
|
|
865
866
|
attr_validation_func=Vf.validate_non_negative_integer,
|
|
866
867
|
jar_flag='-b',
|
{certora_cli-7.20.3 → certora_cli-7.21.1}/certora_cli/EVMVerifier/certoraContextValidator.py
RENAMED
|
@@ -133,7 +133,7 @@ class CertoraContextValidator:
|
|
|
133
133
|
# the absolute one.
|
|
134
134
|
pass
|
|
135
135
|
|
|
136
|
-
|
|
136
|
+
set_bytecode_relative_paths(context)
|
|
137
137
|
check_files_input(context.files)
|
|
138
138
|
check_vyper_flag(context)
|
|
139
139
|
check_compiler_map_flag(context)
|
|
@@ -762,7 +762,7 @@ def to_relative_paths(paths: Union[str, List[str]]) -> Union[str, List[str]]:
|
|
|
762
762
|
if isinstance(paths, list):
|
|
763
763
|
return [os.path.relpath(path, cwd) for path in paths]
|
|
764
764
|
|
|
765
|
-
def
|
|
765
|
+
def set_bytecode_relative_paths(context: CertoraContext) -> None:
|
|
766
766
|
for attr in [Attrs.EvmProverAttributes.BYTECODE_JSONS.get_conf_key(),
|
|
767
767
|
Attrs.EvmProverAttributes.BYTECODE_SPEC.get_conf_key()]:
|
|
768
768
|
value = getattr(context, attr, None)
|
|
@@ -36,6 +36,7 @@ from Mutate import mutateUtil as MutUtil
|
|
|
36
36
|
from Mutate import mutateAttributes as MutAttrs
|
|
37
37
|
import EVMVerifier.certoraContextAttributes as Attrs
|
|
38
38
|
from EVMVerifier.certoraContextClass import CertoraContext
|
|
39
|
+
from rustMutator import run_universal_mutator
|
|
39
40
|
|
|
40
41
|
class RunTimedout(Exception):
|
|
41
42
|
pass
|
|
@@ -43,7 +44,6 @@ class RunTimedout(Exception):
|
|
|
43
44
|
|
|
44
45
|
DEFAULT_NUM_MUTANTS = 5
|
|
45
46
|
ENV_FREE_CHECK = 'envfreeFuncsStaticCheck'
|
|
46
|
-
PATCH_SUFFIXES = ['.sol', '.patch']
|
|
47
47
|
|
|
48
48
|
mutation_logger = logging.getLogger("mutation")
|
|
49
49
|
|
|
@@ -600,7 +600,7 @@ def convert_to_mutation_testing_status(treeview_status: str) -> str:
|
|
|
600
600
|
return MutationTestRuleStatus.UNKNOWN.value
|
|
601
601
|
|
|
602
602
|
|
|
603
|
-
def
|
|
603
|
+
def mutant_object_from_path(manual_mutant: Path, orig_file: Path) -> Mutant:
|
|
604
604
|
"""
|
|
605
605
|
Generate a Mutant object for a manual mutation.
|
|
606
606
|
|
|
@@ -699,9 +699,13 @@ class MutateApp:
|
|
|
699
699
|
request_timeout: Optional[int]
|
|
700
700
|
gambit: Union[Dict, List, None]
|
|
701
701
|
manual_mutants: Optional[Dict]
|
|
702
|
+
universal_mutator: Optional[Dict]
|
|
702
703
|
prover_context: CertoraContext
|
|
703
704
|
|
|
704
|
-
def __init__(self, args_list: List[str]
|
|
705
|
+
def __init__(self, args_list: List[str]) -> None:
|
|
706
|
+
self.mutation_test_id = ''
|
|
707
|
+
self.numb_of_jobs: int = 0
|
|
708
|
+
self.backup_paths: List[Path] = []
|
|
705
709
|
self.sources_dir: Optional[Path] = None
|
|
706
710
|
self.with_split_stats_data = False
|
|
707
711
|
self.manual_mutants_list: List[Mutant] = list()
|
|
@@ -710,6 +714,13 @@ class MutateApp:
|
|
|
710
714
|
self.read_conf_file()
|
|
711
715
|
self.server = self.config_server()
|
|
712
716
|
|
|
717
|
+
def is_soroban_run(self) -> bool:
|
|
718
|
+
try:
|
|
719
|
+
files = self.prover_context.files
|
|
720
|
+
except AttributeError:
|
|
721
|
+
return False
|
|
722
|
+
return Util.CARGO_FILE in files or any(Path(path).suffix == '.wasm' for path in files)
|
|
723
|
+
|
|
713
724
|
def config_server(self) -> str:
|
|
714
725
|
"""
|
|
715
726
|
If given a server, it is taken.
|
|
@@ -856,7 +867,58 @@ class MutateApp:
|
|
|
856
867
|
raise Util.CertoraUserInputError(f"The mutated file, {file_to_mutate}, does not affect"
|
|
857
868
|
" verification results. Please remove or replace the mutation")
|
|
858
869
|
|
|
859
|
-
def
|
|
870
|
+
def restore_backups(self) -> None:
|
|
871
|
+
for backup_path in self.backup_paths:
|
|
872
|
+
Util.restore_backup(backup_path)
|
|
873
|
+
self.backup_paths = []
|
|
874
|
+
|
|
875
|
+
def submit_soroban(self) -> None:
|
|
876
|
+
mutation_logger.info("Generating mutants and submitting...")
|
|
877
|
+
generated_mutants: List[Mutant] = self.get_universal_mutator_mutants()
|
|
878
|
+
|
|
879
|
+
web_utils = WebUtils(SimpleNamespace(**vars(self)))
|
|
880
|
+
# get the mutation test id
|
|
881
|
+
self.numb_of_jobs = len(generated_mutants)
|
|
882
|
+
self.mutation_test_id, collect_presigned_url = self.get_mutation_test_id_request(web_utils,
|
|
883
|
+
self.numb_of_jobs + 1)
|
|
884
|
+
mutation_logger.debug(f"Mutation test id: {self.mutation_test_id}")
|
|
885
|
+
print_separator('PROVER START')
|
|
886
|
+
# run original run. if it fails to compile, nothing to continue with
|
|
887
|
+
|
|
888
|
+
try:
|
|
889
|
+
original_run_result = self.run_certora_prover(self.conf, self.mutation_test_id, msg=MConstants.ORIGINAL)
|
|
890
|
+
except Exception as e:
|
|
891
|
+
raise Util.CertoraUserInputError(f"Orig run: {e}")
|
|
892
|
+
if not original_run_result:
|
|
893
|
+
raise Util.CertoraUserInputError("No Orig results")
|
|
894
|
+
result_link = original_run_result.rule_report_link
|
|
895
|
+
assert result_link, "submit_soroban: Null result_link"
|
|
896
|
+
|
|
897
|
+
if not Vf.Util.is_valid_url(urllib3.util.parse_url(result_link)):
|
|
898
|
+
raise Util.CertoraUserInputError(f"Invalid certoraRun result: {result_link}")
|
|
899
|
+
print_separator('PROVER END')
|
|
900
|
+
# run mutants
|
|
901
|
+
mutant_runs = []
|
|
902
|
+
try:
|
|
903
|
+
self.backup_paths = []
|
|
904
|
+
for mutant in generated_mutants:
|
|
905
|
+
# call certoraRun for each mutant we found
|
|
906
|
+
mutant_runs.append(self.run_mutant_soroban(mutant))
|
|
907
|
+
finally:
|
|
908
|
+
self.restore_backups()
|
|
909
|
+
|
|
910
|
+
# wrap it all up and make the input for the 2nd step: the collector
|
|
911
|
+
assert self.collect_file, "submit_soroban: no collect_file"
|
|
912
|
+
with self.collect_file.open('w+') as collect_file:
|
|
913
|
+
collect_data = {MConstants.ORIGINAL: result_link,
|
|
914
|
+
MConstants.MUTANTS: [dataclasses.asdict(m) for m in mutant_runs]}
|
|
915
|
+
json.dump(collect_data, collect_file, indent=4)
|
|
916
|
+
|
|
917
|
+
self.upload_file_to_cloud_storage(web_utils, collect_presigned_url, collect_data)
|
|
918
|
+
self.print_notification_msg()
|
|
919
|
+
mutation_logger.info(f"... completed submit phase! Now we poll on {self.collect_file}...")
|
|
920
|
+
|
|
921
|
+
def submit_evm(self) -> None:
|
|
860
922
|
mutation_logger.info("Generating mutants and submitting...")
|
|
861
923
|
|
|
862
924
|
# ensure .certora_internal exists
|
|
@@ -875,7 +937,7 @@ class MutateApp:
|
|
|
875
937
|
sys.exit(0) # we exit here so we will not continue with collect in case of sync mode
|
|
876
938
|
|
|
877
939
|
if self.manual_mutants:
|
|
878
|
-
self.manual_mutants_list = self.
|
|
940
|
+
self.manual_mutants_list = self.get_manual_mutations_mutants()
|
|
879
941
|
mutation_logger.debug(f"successfully parsed manual mutants from {self.conf}")
|
|
880
942
|
|
|
881
943
|
# match a generated mutant to a directory where we will apply the diff
|
|
@@ -910,7 +972,7 @@ class MutateApp:
|
|
|
910
972
|
if certora_run_result:
|
|
911
973
|
self.sources_dir = certora_run_result.src_dir
|
|
912
974
|
|
|
913
|
-
assert certora_run_result.rule_report_link, "
|
|
975
|
+
assert certora_run_result.rule_report_link, "submit_evm: no certora_run_result.rule_report_link"
|
|
914
976
|
result_link = certora_run_result.rule_report_link
|
|
915
977
|
if self.wait_for_original_run:
|
|
916
978
|
if wait_for_job(result_link) and download_report_file(result_link, MConstants.SPLIT_STATS_DATA):
|
|
@@ -938,7 +1000,7 @@ class MutateApp:
|
|
|
938
1000
|
with prover_conf.open('w') as p_conf:
|
|
939
1001
|
json.dump(prover_conf_content.__dict__, p_conf)
|
|
940
1002
|
shutil.copy(prover_conf, self.sources_dir)
|
|
941
|
-
assert self.orig_run_dir, "
|
|
1003
|
+
assert self.orig_run_dir, "submit_evm: orig_run_dir"
|
|
942
1004
|
src = self.orig_run_dir / MConstants.TARNAME / MConstants.REPORTS / MConstants.SPLIT_STATS_DATA
|
|
943
1005
|
if src.is_file():
|
|
944
1006
|
try:
|
|
@@ -968,14 +1030,14 @@ class MutateApp:
|
|
|
968
1030
|
num_processes_for_mp = None
|
|
969
1031
|
max_task_per_worker = None
|
|
970
1032
|
|
|
971
|
-
# For debug call
|
|
1033
|
+
# For debug call run_mutant_evm in same process
|
|
972
1034
|
# runs = [(mutant, trg_dir, prover_conf,
|
|
973
1035
|
# mutation_test_id, numb_of_jobs) for mutant, trg_dir in all_mutants_with_target_dir]
|
|
974
1036
|
# mutant_runs = []
|
|
975
1037
|
# for run in runs:
|
|
976
|
-
# mutant_runs.append(self.
|
|
1038
|
+
# mutant_runs.append(self.run_mutant_evm(*run))
|
|
977
1039
|
with multiprocessing.Pool(processes=num_processes_for_mp, maxtasksperchild=max_task_per_worker) as pool:
|
|
978
|
-
mutant_runs = pool.starmap(self.
|
|
1040
|
+
mutant_runs = pool.starmap(self.run_mutant_evm,
|
|
979
1041
|
[(mutant, trg_dir, prover_conf, mutation_test_id, numb_of_jobs)
|
|
980
1042
|
for mutant, trg_dir in all_mutants_with_target_dir])
|
|
981
1043
|
|
|
@@ -986,7 +1048,7 @@ class MutateApp:
|
|
|
986
1048
|
mutation_logger.debug([dataclasses.asdict(m) for m in mutant_runs])
|
|
987
1049
|
|
|
988
1050
|
# wrap it all up and make the input for the 2nd step: the collector
|
|
989
|
-
assert self.collect_file, "
|
|
1051
|
+
assert self.collect_file, "submit_evm: no collect_file"
|
|
990
1052
|
with self.collect_file.open('w+') as collect_file:
|
|
991
1053
|
collect_data = {MConstants.ORIGINAL: result_link,
|
|
992
1054
|
MConstants.MUTANTS: [dataclasses.asdict(m) for m in mutant_runs]}
|
|
@@ -1015,8 +1077,8 @@ class MutateApp:
|
|
|
1015
1077
|
if self.with_split_stats_data and os.environ.get("WITH_AUTOCONFING", False) == '1':
|
|
1016
1078
|
shutil.copy(Path.cwd() / MConstants.SPLIT_STATS_DATA, find_cwd(trg_dir))
|
|
1017
1079
|
|
|
1018
|
-
def
|
|
1019
|
-
|
|
1080
|
+
def run_mutant_evm(self, mutant: Mutant, trg_dir: Path, orig_conf: Path,
|
|
1081
|
+
mutation_test_id: str, numb_of_jobs: int) -> MutantJob:
|
|
1020
1082
|
|
|
1021
1083
|
MutUtil.TOTAL_MUTANTS = numb_of_jobs
|
|
1022
1084
|
with Util.change_working_directory(find_cwd(trg_dir)):
|
|
@@ -1033,7 +1095,7 @@ class MutateApp:
|
|
|
1033
1095
|
rule_report_link=None
|
|
1034
1096
|
)
|
|
1035
1097
|
|
|
1036
|
-
assert certora_run_result, f"
|
|
1098
|
+
assert certora_run_result, f"run_mutant_evm: no result {mutant.id} "
|
|
1037
1099
|
|
|
1038
1100
|
link = certora_run_result.link
|
|
1039
1101
|
self.sources_dir = certora_run_result.src_dir
|
|
@@ -1046,6 +1108,38 @@ class MutateApp:
|
|
|
1046
1108
|
rule_report_link=certora_run_result.rule_report_link
|
|
1047
1109
|
)
|
|
1048
1110
|
|
|
1111
|
+
def run_mutant_soroban(self, mutant: Mutant) -> MutantJob:
|
|
1112
|
+
file_to_mutate = Path(mutant.original_filename)
|
|
1113
|
+
if file_to_mutate not in self.backup_paths:
|
|
1114
|
+
# create a backup copy by adding '.backup' to the end of the file
|
|
1115
|
+
backup_file = Util.create_backup(file_to_mutate)
|
|
1116
|
+
assert backup_file, f"run_mutant_soroban: create_backup for {file_to_mutate} failed"
|
|
1117
|
+
self.backup_paths.append(backup_file)
|
|
1118
|
+
shutil.copy(mutant.filename, file_to_mutate)
|
|
1119
|
+
|
|
1120
|
+
try:
|
|
1121
|
+
certora_run_result = self.run_certora_prover(self.conf, self.mutation_test_id, msg=f"mutant ID: {mutant.id}")
|
|
1122
|
+
except Util.CertoraUserInputError:
|
|
1123
|
+
return MutantJob(
|
|
1124
|
+
gambit_mutant=mutant,
|
|
1125
|
+
success=False,
|
|
1126
|
+
run_directory="",
|
|
1127
|
+
link=None,
|
|
1128
|
+
rule_report_link=None
|
|
1129
|
+
)
|
|
1130
|
+
|
|
1131
|
+
assert certora_run_result, f"run_mutant_soroban: no result {mutant.id} "
|
|
1132
|
+
|
|
1133
|
+
link = certora_run_result.link
|
|
1134
|
+
|
|
1135
|
+
return MutantJob(
|
|
1136
|
+
gambit_mutant=mutant,
|
|
1137
|
+
success=True,
|
|
1138
|
+
run_directory="",
|
|
1139
|
+
link=link,
|
|
1140
|
+
rule_report_link=certora_run_result.rule_report_link
|
|
1141
|
+
)
|
|
1142
|
+
|
|
1049
1143
|
def get_solc_version(self, path_to_file: Path) -> str:
|
|
1050
1144
|
solc = getattr(self.prover_context, 'solc', '')
|
|
1051
1145
|
solc_map = getattr(self.prover_context, 'solc_map', None)
|
|
@@ -1125,7 +1219,7 @@ class MutateApp:
|
|
|
1125
1219
|
evm_version = getattr(self.prover_context, 'solc_evm_version', None)
|
|
1126
1220
|
if evm_version:
|
|
1127
1221
|
shared_attributes['solc_evm_version'] = evm_version
|
|
1128
|
-
assert self.gambit, "
|
|
1222
|
+
assert self.gambit, "submit_evm: no gambit"
|
|
1129
1223
|
for gambit_obj in self.gambit:
|
|
1130
1224
|
if MConstants.NUM_MUTANTS not in gambit_obj:
|
|
1131
1225
|
gambit_obj[MConstants.NUM_MUTANTS] = DEFAULT_NUM_MUTANTS
|
|
@@ -1179,52 +1273,78 @@ class MutateApp:
|
|
|
1179
1273
|
mutation_logger.debug("Got mutant information")
|
|
1180
1274
|
return ret_mutants
|
|
1181
1275
|
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1276
|
+
def valid_extensions(self) -> List[str]:
|
|
1277
|
+
if self.is_soroban_run():
|
|
1278
|
+
return ['.rs']
|
|
1279
|
+
else:
|
|
1280
|
+
return ['.sol', '.patch']
|
|
1281
|
+
|
|
1282
|
+
def add_file_to_mutants(self, mutants: List[Mutant], mutation_file: Path, file_to_mutate: Path) -> None:
|
|
1283
|
+
|
|
1284
|
+
if mutation_file.suffix in self.valid_extensions():
|
|
1285
|
+
mutant_obj = mutant_object_from_path(mutation_file, file_to_mutate)
|
|
1286
|
+
mutants.append(mutant_obj)
|
|
1187
1287
|
else:
|
|
1188
1288
|
raise Util.CertoraUserInputError(f"Illegal mutant file, {mutation_file.name},"
|
|
1189
|
-
" extension must be
|
|
1289
|
+
f" extension must be {' or '.join(self.valid_extensions())}")
|
|
1190
1290
|
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1291
|
+
def add_dir_to_mutants(self, manual_mutants: List[Mutant], mutation_dir: Path, file_to_mutate: Path) -> None:
|
|
1292
|
+
mutation_dir_path = Path(mutation_dir)
|
|
1293
|
+
manual_mutants_files = \
|
|
1294
|
+
[p for p in mutation_dir_path.glob('*') if p.is_file() and p.suffix in self.valid_extensions()]
|
|
1195
1295
|
if not manual_mutants_files:
|
|
1196
1296
|
raise Util.CertoraUserInputError(
|
|
1197
1297
|
f"Could not find any manual mutation files at {mutation_dir}")
|
|
1198
1298
|
for file in manual_mutants_files:
|
|
1199
|
-
|
|
1299
|
+
self.add_file_to_mutants(manual_mutants, file, file_to_mutate)
|
|
1200
1300
|
|
|
1201
|
-
def
|
|
1301
|
+
def get_manual_mutations_mutants(self) -> List[Mutant]:
|
|
1202
1302
|
"""
|
|
1203
|
-
|
|
1303
|
+
Get manual mutations from manual_mutations attribute
|
|
1204
1304
|
|
|
1205
1305
|
Returns:
|
|
1206
|
-
- A list of Mutant objects representing the
|
|
1306
|
+
- A list of Mutant objects representing the found manual mutations.
|
|
1207
1307
|
|
|
1208
1308
|
Raises:
|
|
1209
|
-
- `
|
|
1309
|
+
- `CertoraUserInputError`: If the mutation configuration file does not exist.
|
|
1210
1310
|
"""
|
|
1211
1311
|
|
|
1212
1312
|
ret_mutants: List[Mutant] = []
|
|
1213
|
-
assert self.manual_mutants, "
|
|
1313
|
+
assert self.manual_mutants, "get_manual_mutations_mutants: self.manual_mutants"
|
|
1214
1314
|
for mutant in self.manual_mutants:
|
|
1215
1315
|
file_to_mutate = Path(os.path.normpath(mutant[MConstants.FILE_TO_MUTATE]))
|
|
1216
1316
|
path_to_orig = Path(file_to_mutate).resolve()
|
|
1217
1317
|
if not path_to_orig.exists():
|
|
1218
1318
|
raise Util.CertoraUserInputError(f"Original file '{path_to_orig}' for manual mutations does not exist")
|
|
1219
|
-
mutants_location = Path(mutant[MConstants.MUTANTS_LOCATION])
|
|
1319
|
+
mutants_location = Path(mutant[MConstants.MUTANTS_LOCATION])
|
|
1220
1320
|
if mutants_location.is_dir():
|
|
1221
|
-
|
|
1321
|
+
self.add_dir_to_mutants(ret_mutants, mutants_location, file_to_mutate)
|
|
1222
1322
|
elif mutants_location.is_file():
|
|
1223
|
-
|
|
1323
|
+
self.add_file_to_mutants(ret_mutants, mutants_location, file_to_mutate)
|
|
1224
1324
|
else:
|
|
1225
1325
|
raise Util.CertoraUserInputError(f"{mutants_location} not a valid file or directory")
|
|
1226
1326
|
return ret_mutants
|
|
1227
1327
|
|
|
1328
|
+
def get_universal_mutator_mutants(self) -> List[Mutant]:
|
|
1329
|
+
"""
|
|
1330
|
+
Get manual mutations from universal_mutator attribute
|
|
1331
|
+
|
|
1332
|
+
Returns:
|
|
1333
|
+
- A list of Mutant objects representing the found manual mutations.
|
|
1334
|
+
|
|
1335
|
+
Raises:
|
|
1336
|
+
- `CertoraUserInputError`: If the mutation configuration file does not exist.
|
|
1337
|
+
"""
|
|
1338
|
+
|
|
1339
|
+
ret_mutants: List[Mutant] = []
|
|
1340
|
+
assert self.universal_mutator, "get_universal_mutator_mutants: self.universal_mutator"
|
|
1341
|
+
for mutant in self.universal_mutator:
|
|
1342
|
+
file_to_mutate = Path(os.path.normpath(mutant[MConstants.FILE_TO_MUTATE]))
|
|
1343
|
+
mutants_location = Path(mutant[MConstants.MUTANTS_LOCATION])
|
|
1344
|
+
run_universal_mutator(file_to_mutate, mutants_location)
|
|
1345
|
+
self.add_dir_to_mutants(ret_mutants, mutants_location, file_to_mutate)
|
|
1346
|
+
return ret_mutants
|
|
1347
|
+
|
|
1228
1348
|
def verify_orig_build(self) -> None:
|
|
1229
1349
|
if self.orig_run: # if orig run exists we will not try to build again
|
|
1230
1350
|
return
|
|
@@ -1252,7 +1372,8 @@ class MutateApp:
|
|
|
1252
1372
|
if self.prover_version:
|
|
1253
1373
|
certora_args.extend(["--prover_version", self.prover_version])
|
|
1254
1374
|
|
|
1255
|
-
|
|
1375
|
+
if not self.is_soroban_run():
|
|
1376
|
+
certora_args.extend(["--disable_local_typechecking"])
|
|
1256
1377
|
mutation_logger.debug(f"Running the Prover: {certora_args}")
|
|
1257
1378
|
try:
|
|
1258
1379
|
certora_run_result = run_certora(certora_args)
|
|
@@ -1326,11 +1447,17 @@ class MutateApp:
|
|
|
1326
1447
|
all_mutants_results: List[MutantJobWithResults] = []
|
|
1327
1448
|
for mutant_job in mutants_jobs:
|
|
1328
1449
|
mutant_link = mutant_job.link
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1450
|
+
if not mutant_link:
|
|
1451
|
+
return None
|
|
1452
|
+
try:
|
|
1453
|
+
mutant_run_results = self.get_results(mutant_link, fetcher)
|
|
1454
|
+
except Util.BadMutationError:
|
|
1455
|
+
# we do not want to abort the mutation testing all together just because Prover failed.
|
|
1456
|
+
# Some mutants may compile but fail during runtime. We just should ignore them in the final report
|
|
1457
|
+
mutant_job.success = False
|
|
1458
|
+
continue
|
|
1459
|
+
if not mutant_run_results:
|
|
1332
1460
|
return None
|
|
1333
|
-
|
|
1334
1461
|
mutant_results = MutantJobWithResults(mutant_job, mutant_run_results)
|
|
1335
1462
|
|
|
1336
1463
|
all_mutants_results.append(mutant_results)
|
|
@@ -1578,7 +1705,7 @@ class MutateApp:
|
|
|
1578
1705
|
raise Util.ImplementationError("Could not get progress object")
|
|
1579
1706
|
top_level_rules = get_top_level_rules(progress_json)
|
|
1580
1707
|
if top_level_rules is None:
|
|
1581
|
-
raise Util.
|
|
1708
|
+
raise Util.BadMutationError("Could not get tree view object")
|
|
1582
1709
|
rule_results = []
|
|
1583
1710
|
|
|
1584
1711
|
for rule in top_level_rules:
|