Apple IPS static inspection verification — 2026-10-24¶
Scope¶
PR #6511 adds portable inspect_apple_ips / inspect-apple-ips over one
caller-selected local file. The metadata must identify string bug_type
"309"; stackshots and other report kinds remain unsupported. No target is
executed, no deep engine starts, and no atos/dSYM lookup is performed. These
checks do not qualify live macOS state, symbolication or Mach-O UUID joins.
The source contract preserves integer literals beyond IEEE-754 precision, observed type mismatches and partial coverage. The frame address is derived from its image's base plus its recorded offset, as described in Apple's crash JSON documentation. That documentation does not provide a 64-bit bound for every numeric field; the parser therefore bounds representation cost without truncating values.
Review corrections and ownership¶
The contributor's 80ad2a02e9c6cbe248d58d78a7a79753bcc09f79 already projects
documented JSON members and checks thread/frame/image/register allowances
before materializing each row. Unknown members are syntax-checked without
retaining their values. Producer controls include a budget error before an
invalid next item, wrong-type collections, frame-role cases, and the DEAD10CC
decimal near miss. Inline-role assumptions are corrected below. Source inspection alone does not
establish the runtime checks below.
Further negative controls expose three remaining boundaries:
- Two contradictory thread/image coverage reports were accepted by the service. Coverage now agrees with the retained arrays before Evidence is issued. Already cancelled requests also preserve the exact caller reason.
- A 20,001-digit image base expanded into 512 derived frame addresses despite a small input file. The field reader now owns an 8 MiB default / 64 MiB maximum UTF-16 allowance for recorded decimal/hex fields. Conservative reservations precede conversion and arithmetic. Source BigInts are reused; derived sums are not retained in a cache. Repeated appearances count separately, including a service control using the same object twice.
- A 20,013-character image architecture appeared 513 times in a 512-frame
report. Frames now retain their recorded
image_index; architecture, UUID anduuid_unknownbelong to the image once. The old per-frame copies and superseded field-access helpers are removed.
Each defect has a failing control before its correction. Raising the integer allowance to 64 MiB preserves the 512-frame decimal facts exactly. The allowance is per call, requires no restart, and is separate from file-size, row, wire and client-buffer limits. Refusal is a typed capacity error without partial success. A refused task is not treated as a completed-task speedup.
Public corpus provenance¶
Two pinned upstream reports are valid two-object JSON and are used without editing their bytes. Their original generation history has not been verified; these are public repository corpus files, not a claim of fresh OS capture.
| Report | Repository revision | Bytes | SHA-256 |
|---|---|---|---|
| LLDB multithread-test.ips | 16dde0db3ce0b9c5eae14178780cc6db1eec7ac8 |
16,093 | 567cadb22af19be798390ab2021ed929fb782c69b2d3b18ff5bb3f39a3741d8c |
| pycrashreport Monterey report | 634dff127fa6d4d3df948a64a3e254fe208a99dc |
7,047 | 7de3d3c3515e2ac1bb6ed4c00b70cb12c1ff6ad4317617d258d58346e00264b7 |
Three other LLDB inputs (a.out.ips, a.out.inline.ips, no_threadState.ips)
contain invalid JSON at their pinned revision. They were not repaired or
counted as successful report qualifications. Files remain temporary local
verification inputs and are not committed to this repository.
Completed-task comparison¶
Compare d4930ed57c0b175a632fd8572732b1e88a73cb2f (original IPS behavior
with main cc18e9ad provider/API integration repairs) against
135cab1234c3663e839f5fbea6bf833737cd140a. Three alternating pairs of five
public CLI tasks complete, 30 tasks total. Every task returns complete
coverage. An independent Python JSON/integer oracle checks all ordered images,
threads, registers, frame offsets, derived addresses and the then-selected
physical-depth roles, as well as process facts and artifact digests. The later
source-backed correction below replaces that role assumption; neither public
report contains an inline row, so its role expectations remain unchanged. The two public reports contain
3/1 threads, 8/4 images, 30/4 frames and 36/22 retained registers respectively.
Every Evidence field agrees after excluding the changed Evidence ID, the new default allowance parameter and the removed per-frame copies. Before excluding those copies, the oracle verifies each against its owning image. Image facts, uncertainty, other report fields, provenance, coverage and limitations remain equal. Artifact digests are unchanged across all runs.
| Complete CLI task | Estimated stdout + invocation tokens, before → after | Elapsed median s | CPU median s | Sampled family RSS median MiB |
|---|---|---|---|---|
| Small synthetic report | 934 → 923 | 2.069 → 1.969 | 2.309 → 2.212 | 368.8 → 369.6 |
| LLDB multithread report | 6,500 → 5,851 | 3.180 → 2.878 | 2.292 → 2.340 | 370.4 → 373.5 |
| Monterey report | 2,377 → 2,309 | 3.330 → 3.029 | 2.230 → 2.208 | 369.6 → 368.8 |
| 20,001-digit base / 64 frames | 402,476 → 401,783 | 2.725 → 2.879 | 2.354 → 2.319 | 375.1 → 371.8 |
| Long image architecture / 512 frames | 1,760,820 → 41,023 | 3.231 → 2.928 | 2.468 → 2.261 | 387.3 → 372.7 |
The long-image task reduces estimated whole-task context by 97.67% while preserving joined facts. Ordinary reports save less. No latency speedup is claimed: elapsed ranges overlap, including the long-image ranges 2.070–3.381 s before and 2.928–3.633 s after. Small-report ranges reach about 9.2 s in both lanes during shared-host contention. The wide-integer elapsed median rises about 0.154 s, while its CPU and sampled RSS medians decrease slightly. Three pairs do not establish universal performance or maximum-capacity behavior.
Each task uses a fresh Node 24.22.1 CLI/provider process, with CPU affinity 0,1. OS caches were not flushed; these are fresh-process runs with uncontrolled warm filesystem caches, not measured cold-disk runs. No result cache or persistent provider session participates. Warm long-lived process behavior is unmeasured. Tokenx 1.3.0 estimates the entire Evidence stdout and invocation; these are estimates, not billed/model token counts. The analyst already knows the single CLI command, so no discovery, paging or extra lookup call is required. Image metadata is inline in the same result. MCP catalog costs, prompts, framing, rendering and client JSON parsing are unmeasured.
CPU is waited-child user plus system time. RSS is a 50 ms recursive process-family sample; it can double-count shared pages and miss short-lived or unobserved descendants. Token estimation and the oracle run outside the timed command. Later main integrations are outside these pinned timings.
Synthetic recipes: small.ips has one frame/register; wide-integer.ips uses
base 10^20000, 64 frames with image offset 1; wide-image-text.ips uses
architecture unknown_arch_ plus 20,000 x characters and 512 frames. Their
SHA-256 values are respectively
1178a013b86f8a6c11abef633fdee5fefd23e010c4af92710321cb0f369ed857,
b455598694d9953031e52450f1a4a6655e16abd683a2cec59e393899883b6994, and
4d3d2f3e4946cbbeed7e14e1f12cd97bd2f119af1b3a33496dd3e8d079c3f999.
Final integration checks¶
Main cd10ee1f8a8e124be4864e77750a16e76c561809 integration passes 167
selected domain/service/parser/filesystem/CLI/MCP/shared lifecycle checks in
74.312 s (80.355 s waited-child CPU; 1,902.0 MiB sampled family peak). Full
npm run check, npm run docs:check and test discovery pass. All 2,324 test
files are discovered exactly once. Earlier source selections overlap these
checks. Two initial public-error assertions placed remediation at the wrong
level; the tests now check the existing top-level error contract. No production
error shape was changed to accommodate them.
Both pinned public reports additionally pass through the actual stdio MCP server and SDK client, with the advertised input/output JSON Schemas validated in AJV 2020. The same independent oracle checks their returned facts. The client explicitly admits a 64 MiB receive buffer for the complete tool catalog; this does not qualify every client's default buffer. Target execution and symbolication remain unverified. The 30-task cost table remains pinned to its recorded revisions, without reusing these integration costs as speed evidence.
Integration after PE imports¶
The following integration includes main 4ef916da03d93729041f79cec0ee243cd2d3097d
and the newly merged PE imports tool. The documentation index retains links to
both static formats. Full static/docs/discovery gates pass, together with
191 selected checks, including the upstream native-plist cleanup test.
The selection takes 49.939 s, 52.461 s waited-child CPU and 2,079.8 MiB sampled
family RSS. It overlaps earlier selections and is not a performance comparison.
Previous-head CI run 40058145277 had one functional failure in
nativePlistFileCleanup.test.ts, repeated by the aggregate lane; seven other
shards were cancelled. Exact main d662fa54a67bf24bd4800d1867231662019d91c6
and actual CI merge 440029745397d78103a623fd1fd91cfa09fc6df5 each reproduce
11 passing / 1 failing cases with identical statuses and normalized failure
messages. The failing test and selected producer sources are byte-identical.
The subsequent main integration fixes that closing race, and all 12 cleanup
cases pass within the 191 checks. Cancelled CI coverage was not executed.
Follow-up string capacity and identity review¶
Baseline 45a570656cb3b9a7a8bf41302e1f01f8662bc884 and candidate
6fa8083fc6974bc18c7d227ded33db28eb590f03 isolate three further corrections:
- Retained JSON strings are syntax-checked by the same scanner used for skipped strings, then escaped literals are decoded by the native JSON string parser. Unescaped strings retain the slice fast path. The superseded per-escape fragment array is gone; decoded length is bounded by the selected input's literal length. Malformed escapes and controls still fail before projection.
- UUID interpretation owns format validation before canonicalization. Both
32 hexadecimal digits and canonical hyphenation are accepted. Malformed
nonempty spellings remain in
coverage.type_mismatches[].recorded_value, canonical identity stays unknown and coverage becomes partial. Absent UUIDs and the documented all-zero unknown sentinel remain distinct from that malformed-value outcome. The field uses the existing exact-optional contract convention; it does not admit an explicit JavaScriptundefinedvalue. metadata.bug_typeis literal"309"in the domain and advertised schema. The service rejects unsupported reports from defective/custom ports too.
Seven new cases failed against the earlier production code: four malformed UUID spellings, two unsupported port kinds and a public CLI capacity case. The latter selects a file below the 16 MiB allowance containing 7,500,000 newline escapes. Earlier decoding exhausts a 256 MiB Node old-space limit; the corrected CLI completes with every character verified by length and SHA-256. This is an old-space setting, not a 256 MiB total RSS claim.
The first expanded run passed 182 of 183 cases; the advertised-schema MCP case
hit its 30-second test deadline. Its isolated two-case file then passed, and
the expanded schema assertions passed again. After switching to the final
exact-optional representation, both MCP cases passed once more: actual SDK
schemas reject a forged bug_type: "288" and admit the partial result with its
exact malformed UUID spelling. check:fast passed. The two public crash
reports also passed again through an actual stdio MCP client and Ajv2020.
Twelve further completed CLI tasks used three alternating pairs for the same
public LLVM report and a generated 4,000,063-byte report containing 2,000,000
newline escapes (SHA-256
5c4a9282da37091973774bf98c6822caeecbc1d74d7c44cd4eda1937ad05e350).
Every complete Evidence field, including IDs, is identical within each case.
The escape case explicitly selects an 8 MiB read allowance; both revisions
complete under the same default 2 GiB old-space task environment.
| Completed task | Estimated tokens, both revisions | Elapsed seconds, before → after | CPU seconds, before → after | Peak family RSS MiB, before → after |
|---|---|---|---|---|
| LLVM public report | 5,851 | 2.071 → 1.970 | 2.378 → 2.328 | 365.3 → 366.0 |
| 2,000,000 escapes | 4,000,703 | 2.425 → 2.374 | 2.457 → 2.289 | 459.3 → 372.1 |
Values are medians. Escape-case elapsed ranges overlap: 2.120–2.930 seconds before and 2.324–2.424 after, so no elapsed-time improvement is established. Its CPU ranges are 2.318–2.521 versus 2.245–2.297 seconds; sampled peak RSS ranges are 457.4–462.9 versus 371.5–372.9 MiB. The measured dense-escape task reduces median CPU by 6.8% and sampled memory by 19.0%; those observations are specific to this case. LLVM ranges overlap and show no general speed gain. Complete output and estimated tokens are unchanged.
Tokens use tokenx 1.3.0 estimates for the invocation plus all stdout, not model billing. These are known CLI tasks with existing inputs, fresh processes and warm OS caches. Input creation, cold disk, discovery, client parsing, prompts, schemas, MCP envelopes and retries are outside that comparison. The same 50 ms descendant RSS sampling and waited-child CPU limitations above apply. Later main integration is not part of these cost measurements.
Final public MCP workflow and main integration¶
Main 21a20306b4887ff8e6b614b6ae34a387cfbdf1d8 was integrated in
6d77f265027d34154145e807b1a5c8fd26a1e567. Its static/documentation checks
and discovery of all 2,339 test files passed. The combined 183-case selection
again reached the in-memory MCP test's 30-second deadline while its other
182 cases passed. Isolated passes did not establish that the setup was robust
under the combined run.
The MCP test now exercises the compiled production stdio entrypoint through the existing local-tools fixture, which owns client/transport cleanup and validates the SDK-advertised schemas. It no longer reconstructs the full source server/catalog inside the shared test worker. One public workflow retains all the prior schema, annotation, capacity, register, malformed-UUID and relative-path assertions; the redundant second connection case was consolidated. No test deadline was increased. The same combined selection then passed all 182 cases, including the large escaped-text CLI case and all producer/service regressions. This is stronger public-path verification, not a claimed runtime speedup from a before/after test-suite timing comparison.
Reference and inline review follow-up¶
Commit 174c7496a2f007a1ef0ab5da0a341b2f801277c3 separates a recorded
uint32 lookup from whether it resolves to an object row. An out-of-range or
malformed faultingThread reference preserves the lookup, marks coverage
partial and leaves row-zero roles unknown. Image lookups use the same owner;
unresolved image references preserve image_index and leave the derived
address unknown. Negative or oversized integer lookups retain their exact
literal in coverage.type_mismatches[].recorded_integer. Reservation happens
before retention, and the service counts these literals against the same
integer-text allowance even for custom ports. No BigInt conversion is needed
for rejected indexes.
The previous comment and guide incorrectly asserted that inline rows share a
subsequent physical row's address. Apple's per-frame imageOffset description
and the pinned LLDB parser
support each row's own base-plus-offset; that parser increments its frame index
for every recorded row. REA therefore keeps its existing address derivation,
leaves a missing offset unknown and corrects roles to use the recorded row
index. The inline flag remains recorded evidence and does not reconstruct a
physical stack. This is source-derived validation; LLDB was not executed.
Nine source controls fail before this correction: two in-range-but-unresolved
faulting indexes, a reference to a malformed thread row, three rejected integer
spellings, the 19-byte rejected-literal allowance, unresolved image coverage and
the corrected row-role oracle. A separate differing/missing-inline-offset case
already passes before the correction and protects the existing address rule;
it is not evidence of a fixed address bug. All 193 selected checks pass
afterward, including CLI, filesystem, custom-provider allowance checks and
production stdio MCP. The actual SDK validates retained lookup literals against
the advertised schema. check:fast, complete formatting, documentation and
cached build also pass. Both pinned public reports pass the real stdio SDK/Ajv
workflow again (13.510 s elapsed, 14.909 s waited CPU, 907.4 MiB sampled family
RSS); the independent integer/JSON oracle checks the CLI comparison below.
Six completed alternating CLI tasks compare the prior actual CI tree
acb837583d8346016fd8b46d4fcf1fdf09fb0b06 with the corrected commit on the
pinned LLDB multithread report. All full Evidence, including IDs, agrees.
Estimated invocation plus full stdout tokens remain 5,851 (tokenx 1.3.0).
Elapsed medians are 2.071 -> 1.969 s (ranges 2.071–2.271 / 1.919–2.069), CPU
2.295 -> 2.278 s (2.140–2.471 / 2.231–2.283), and sampled process-family RSS
366.8 -> 367.0 MiB (348.2–370.9 / 348.9–368.4). CPU/memory ranges overlap;
this small warm-cache sample does not establish a general speed or memory
improvement. Processes are fresh; the OS file cache is warm. Caller input
creation, schemas/discovery, prompts, client parsing and MCP transport are not
included. The same 50 ms family-RSS limitations apply.
JSON admission and output consistency follow-up¶
Three later review findings were reproduced with 19 failing controls before the correction (49 other selected checks pass). Broad JavaScript trimming admitted form-feed, vertical-tab, NBSP and BOM around JSON objects; those are not JSON whitespace. The IPS adapter now passes the original body to the lossless parser, and the complete-value boundary permits only space, tab, CR and LF after the value. Twelve controls cover metadata suffixes and body prefixes/suffixes; a positive control retains JSON whitespace around both objects. Caller bytes and artifact identity stay unchanged.
The shared service no longer accepts a reported faulting-thread index without an established retained owner or its corresponding reference mismatch. Unknown or out-of-range recorded indexes remain available with partial coverage; an unrelated mismatch cannot justify the unresolved lookup. The old empty service fixture incorrectly asserted faulting thread zero and now records null. This is output admission, not reinterpretation of provider source JSON.
Classification is now a named discriminated schema: classified requires at
least one match and unclassified permits none. The source schema rejects both
contradictions. Production SDK/Ajv checks also test both contradictions and both
valid alternatives against the advertised JSON Schema; an actual stdio call
checks that non-JSON trailing whitespace returns a typed caller-input failure.
These are correctness changes. Prior CLI/performance results retain their exact
pins and are not a fresh measurement of the expanded classification schema or
agent catalog costs. No speed or token reduction is claimed for this follow-up.
Final executed source pin 38b5a3c44824282b55041389b7cbb4d9c261cc8c
incorporates main 98ec00f4068bab894639d0d1d83ac0bfc428bcbf. All 216
selected checks pass after the runtime rebuild: 52.922 s elapsed, 51.098 CPU s,
1,347.9 MiB sampled peak family RSS. Type/lint, complete formatting and generated
documentation checks pass. Both pinned public LLVM/pycrashreport inputs were
repeated through the actual stdio SDK/Ajv: 20.231 s elapsed, 20.602 CPU s,
934.0 MiB sampled family RSS, with complete coverage. Full Evidence and IDs agree
with the saved pre-correction public-corpus outputs for both valid inputs.
This repeat is a fresh client/server process with primed OS/file caches; it is
not a cold-system measurement. Client/schema work is included in runtime costs;
model/catalog token usage was not measured in this repeat. The family sampler's
shared-page and short-lived-child limitations described above still apply.
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 rea2/rea