#!/usr/bin/env python3 """PH-1 (3) / Ph fuzz arm 2: the site -> raw-peer control map, checked (P7 package F2 latch). WHAT IT CHECKS. PH-1 (3) (ID-P7-1) converts the named faults whose input bytes the PEER wrote into a per-session latch (MG_Remote/FatalFunnel.h SessionLatch). Fuzz arm 2 wants one raw-peer negative control per converted site. This script keeps those two lists the same list: * it finds every latch site in the four PH-1 (3) files - each `SessionLatch(` call and each `WireProtocolLatch(` / `WireProtocolLatchAt(` call - and rebuilds the line it logs, `Fatal{Family, "word"} ...` with every printf conversion a wildcard; * it reads the row table (`kRows`) of MobileGL/MG_Test/Wire/PeerLatchTest.cpp, whose Latched rows each carry a marker the test requires to be the FIRST `Fatal{` line of the server log; * a site is COVERED when a Latched row of the same file has a marker that is a prefix of a line the site can log. Otherwise it must be argued in UNREACHABLE: which earlier check refuses the same bytes first. Anything else is red. Sites whose formats are IDENTICAL are one group (a log-reading control cannot tell them apart, and the group is covered once): the three "opcode" copies (the decoder's pre-gate is the reachable one; ApplyChecked's two are behind it) and SetVertexAttribDefaults.Count's two (the count > 32 arm is behind popcount(Mask) == Count, so only the mismatch is reachable). `--table` prints the map as Markdown. `--self-test` proves the check can go red: it drops each covering row in turn and requires its group to turn up unmapped. """ import argparse import re import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[2] TEST = ROOT / "MobileGL" / "MG_Test" / "Wire" / "PeerLatchTest.cpp" FILES = { "PipeWireCodec.cpp": ROOT / "MobileGL" / "MG_Remote" / "Wire" / "PipeWireCodec.cpp", "PipeApplier.cpp": ROOT / "MobileGL" / "MG_Remote" / "Server" / "PipeApplier.cpp", "ServerLoop.cpp": ROOT / "MobileGL" / "MG_Remote" / "Server" / "ServerLoop.cpp", "SurfaceOpCodec.cpp": ROOT / "MobileGL" / "MG_Remote" / "Protocol" / "SurfaceOpCodec.cpp", } # (file, a substring of the site's line) -> why no peer byte reaches it. The site is converted # anyway - it is on the decode path and returns like its neighbours - and the reason names the # earlier check that refuses the same bytes first. UNREACHABLE = [ ("PipeWireCodec.cpp", '"segment-resolve"', "ResolveOrFatal runs RequireDeclaredBlob first, which has already refused a run the segment " "table cannot resolve (R2BlobOutsideItsSegment); reaching it means the table moved"), ("PipeWireCodec.cpp", "the audit was asked to record", "NoteResolvedRun's one caller is ResolveOrFatal after RequireDeclaredBlob: an empty or " "non-SEG_STAGE run never arrives here"), ("PipeWireCodec.cpp", "SEG_STAGE runs in one record", "no record resolves more runs than the audit array holds (CreateShaderState's seven blobs " "are the most, and six of them must be undeclared)"), ("PipeWireCodec.cpp", '"DrawVbo.userIndices"', "MGPipeWireRecordLayout gives a user-index draw exactly one 32-byte second tail and the tail " "cross-check refuses any record that differs (CodecTailCrossCheck)"), ("PipeWireCodec.cpp", '"DrawVbo.indirect"', "as DrawVbo.userIndices: the layout fixes the indirect block's size"), ("ServerLoop.cpp", '"appliedSeq batched"', "both tallies move inside the same ApplyOne callback; no record bytes can separate them"), ("ServerLoop.cpp", '"SurfaceOp.windowBackend"', "SurfaceOpCodec maps the wire WindowKind onto a legal tag or refuses it (the three SurfaceOp " "rows) before a frame reaches the dispatch"), ("ServerLoop.cpp", '"SurfaceOp.kind"', "SurfaceOpCodec refuses an unknown wire kind (SurfaceOpUnknownKind) before the dispatch"), ] LATCH_CALL = re.compile(r"(? control map as Markdown") parser.add_argument("--self-test", action="store_true", help="prove every covered site can go red") args = parser.parse_args() sites = latch_sites() table = rows() mapping = build_map(sites, table) if args.table: print_table(mapping, table) failures = [] if args.self_test: failure = self_test(sites, table) if failure: failures.append(f"self-test did not go red: {failure}") for m in unmapped(mapping): failures.append(f"{m['file']}:{m['lines'][0]} latches `{short(m['fmt'])}` and no PeerLatchTest row's " f"marker names it; add a raw-peer row, or argue it into UNREACHABLE") for file, needle, _ in UNREACHABLE: if not any(m["file"] == file and needle in m["fmt"] for m in mapping): failures.append(f"UNREACHABLE names {file} `{needle}`, which is no longer a latch site") for row in table: if row["outcome"] == "Latched" and row["name"] not in {r for m in mapping for r in m["rows"]} \ and not row["name"].startswith("D11"): failures.append(f"row {row['name']} is Latched but its marker names no latch site of {row['file']}") covered = sum(1 for m in mapping if m["rows"]) argued = sum(1 for m in mapping if not m["rows"] and m["unreachable"]) print(f"ph latch sites: {len(sites)} latch calls = {len(mapping)} distinct lines in {len(FILES)} files; " f"{covered} covered by PeerLatchTest rows ({len(table)} rows), {argued} argued unreachable, " f"{len(unmapped(mapping))} unmapped" + ("; self-test red on every drop" if args.self_test and not any("self-test" in f for f in failures) else "")) for message in failures: print(f"::error::{message}", file=sys.stderr) return 1 if failures else 0 if __name__ == "__main__": sys.exit(main())