decompile-verify / demo /faultless.py
ejschwartz's picture
Add three Faultless completeness examples
52a9362
Raw History Blame Contribute Delete
2.64 kB
"""Saved O0 completeness pairs, with explicit runnable interface adaptations."""
import json
from pathlib import Path
import subprocess
import tempfile
import cle
import yaml
CASES = Path(__file__).with_name("cases")
NAMES = ("faultless-my-putchar-count", "faultless-upper", "faultless-print-page-header")
CASE_NAMES = ("my_putchar_count", "upper", "print_page_header")
LABELS = ("Faultless: One-byte write", "Faultless: Uppercase loop",
"Faultless: Static page counter")
def source(name, filename):
return (CASES / CASE_NAMES[NAMES.index(name)] / filename).read_text()
def metadata(name):
info = json.loads(source(name, "metadata.json"))
info.update(reference=source(name, "original.c"),
expected_verdict="inconclusive" if name == NAMES[0] else "agree")
return info
def prepare_examples(directory):
output = Path(directory).resolve()
output.mkdir(parents=True, exist_ok=True)
rows = []
with tempfile.TemporaryDirectory(prefix="faultless-completeness-") as temporary:
temporary = Path(temporary)
for name in NAMES:
case = CASES / CASE_NAMES[NAMES.index(name)]
info = json.loads((case / "runnable.json").read_text())
original = temporary / "original.c"
original.write_text(info["declarations"] + source(name, "original.c"))
stubs = temporary / "callees.c"
stubs.write_text(info["stubs"])
binary = output / (name + ".elf")
flags = ["-O0", "-fno-builtin"]
subprocess.run(["gcc", *flags, "-fno-pie", "-no-pie", "-fno-stack-protector",
"-nostdlib", "-Wl,--build-id=none", "-Wl,-e," + info["original_symbol"],
str(original), str(stubs), "-o", str(binary)],
check=True, capture_output=True, text=True, timeout=60)
obj = cle.Loader(str(binary), auto_load_libs=False).main_object
addresses = {symbol.name: symbol.rebased_addr for symbol in obj.symbols
if not symbol.is_import}
bindings = {kind: {candidate: addresses[original] for candidate, original in
info.get(kind, {}).items()} for kind in ("callees", "globals")}
rows.append([str(binary), f"{addresses[info['original_symbol']]:#x}",
(case / "candidate.c").read_text(), yaml.safe_dump(bindings, sort_keys=True),
info["candidate_symbol"], 100, "0", 1000, "gcc", " ".join(flags),
yaml.safe_dump(info["interfaces"], sort_keys=True)])
return rows