[GH-ISSUE #2525] fix(flutter): report conflicting load mappings as unresolved snapshot evidence #842

Closed
opened 2026-10-15 18:28:55 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @coygeek on GitHub (Oct 13, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/2525

Summary

AOT inspection accepts a library whose two file-backed load segments assign different file offsets to the VM snapshot range. It reports a resolved VM section, two agreeing hash sources and complete coverage. Reversing only those program headers changes the parser's VM offset without an ambiguity diagnostic, so the result attributes snapshot evidence to a range that the image does not uniquely establish.

Steps to reproduce

  1. In a focused integration test, construct aotFixtureImage() from the repository's Flutter fixture module. It provides all four snapshot exports and valid VM/isolate data headers. Apply this fixture transformation to add a second file-backed mapping of the VM's 52-byte range.
function additionalVmMapping(image: Buffer, fileOffset: number): Buffer {
  const oldTable = Number(image.readBigUInt64LE(0x20));
  const width = image.readUInt16LE(0x36);
  const count = image.readUInt16LE(0x38);
  const table = Math.ceil(image.length / 8) * 8;
  const result = Buffer.alloc(table + (count + 1) * width);
  image.copy(result);
  image.copy(result, table, oldTable, oldTable + count * width);
  result.writeBigUInt64LE(BigInt(table), 0x20);
  result.writeUInt16LE(count + 1, 0x38);
  const added = table + count * width;
  result.writeUInt32LE(1, added);
  result.writeBigUInt64LE(BigInt(fileOffset), added + 8);
  result.writeBigUInt64LE(0x1000n, added + 0x10);
  result.writeBigUInt64LE(52n, added + 0x20);
  return result;
}
  1. Call readElfSymbols(additionalVmMapping(image, 0x100), ["_kDartVmSnapshotData", "_kDartIsolateSnapshotData"]). Repeat after swapping the two 56-byte records in the relocated program-header table. As a control, add a mapping with file offset 0x1000, which agrees with the original mapping.
  2. Package the original-order conflicted image as lib/x86_64/libapp.so in a disposable APK ZIP. Call new FlutterBuildProvider().execute({ operation: "inspect_dart_aot", input: { path: apkPath } }). Parse the result with the operation's result schema and inspect coverage, section offsets and hash-source count. Close the provider and remove the fixture after the test.

Expected behavior

The VM range with conflicting file translations remains unresolved, and AOT coverage reports the missing structural certainty. The unaffected isolate range remains observable. Two equivalent mappings remain usable because they agree on the file bytes. Snapshot hash observations must identify only headers supported by unambiguous ranges.

Actual behavior

The original-order conflicted image returned VM offset 4096 and the reversed image returned VM offset 256, both with no parser failures. The isolate offset remained 8192 in both orders. The equal-mapping control returned VM offset 4096 without failures. The APK inspection returned coverage: "complete", libapp.coverage: "complete", a VM section at offset 4096 and two snapshot hash sources. The corrected focused probe failed its partial-coverage assertion. An earlier probe failed in its own diagnostic after obtaining the parser results; that diagnostic was corrected before the provider assertion ran.

Evidence

  • Expected source: AGENTS.md requires unresolved identity/applicability to remain unknown. docs/flutter-analysis.md:49 ties section evidence to exported ELF symbols and defines structural coverage; src/flutter/DartElf.ts:49 defines the returned offset as a load-segment mapping and rejects other ambiguous ELF identities.
  • Failure source: src/flutter/DartElf.ts:217 selects the first containing load segment. src/flutter/FlutterBuildProvider.ts:1043 derives structural coverage from the returned inventory, which contains no mapping failure for this fixture. The focused parser and APK provider runs produced the offset-dependent and complete-coverage results above.
  • Evidence provenance: observed
  • Local verification: reproduced
  • Reproduction completeness: complete

The fixture uses src/flutter/FlutterBuild.fixture.ts:8 for the complete AOT image and adds only an in-bounds program-header record. This is a static-analysis reproduction and makes no claim about executing the image in an operating-system loader.

Restoration check

Inspect the conflicting fixture in both header orders. Neither result may assert a uniquely resolved VM file range or count that ambiguous header as a supported hash source. Report partial structural coverage with an actionable ambiguity limitation while preserving the isolate evidence. The equal-mapping control must retain the VM symbol, and the unmodified AOT fixture must retain complete structural coverage.

Runtime or environment

Source baseline 8b181716ac. Node v26.10.0, npm 11.19.1 and lockfile-installed dependencies. Verification used npm run test:focused, synthetic ELF64 bytes and a disposable APK ZIP through the public provider operation.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: A bounded malformed library produces unsupported resolved offsets and complete structural coverage. The parser's result changes with program-header order, and the public AOT provider counts the ambiguous VM header as supported evidence.
  • Workaround status: none
  • Workaround basis: The provider has no input option that exposes the competing mappings or excludes only the ambiguous header. External manual interpretation does not restore the provider's evidence result.
Originally created by @coygeek on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2525 ## Summary AOT inspection accepts a library whose two file-backed load segments assign different file offsets to the VM snapshot range. It reports a resolved VM section, two agreeing hash sources and complete coverage. Reversing only those program headers changes the parser's VM offset without an ambiguity diagnostic, so the result attributes snapshot evidence to a range that the image does not uniquely establish. ## Steps to reproduce 1. In a focused integration test, construct `aotFixtureImage()` from the repository's Flutter fixture module. It provides all four snapshot exports and valid VM/isolate data headers. Apply this fixture transformation to add a second file-backed mapping of the VM's 52-byte range. ```ts function additionalVmMapping(image: Buffer, fileOffset: number): Buffer { const oldTable = Number(image.readBigUInt64LE(0x20)); const width = image.readUInt16LE(0x36); const count = image.readUInt16LE(0x38); const table = Math.ceil(image.length / 8) * 8; const result = Buffer.alloc(table + (count + 1) * width); image.copy(result); image.copy(result, table, oldTable, oldTable + count * width); result.writeBigUInt64LE(BigInt(table), 0x20); result.writeUInt16LE(count + 1, 0x38); const added = table + count * width; result.writeUInt32LE(1, added); result.writeBigUInt64LE(BigInt(fileOffset), added + 8); result.writeBigUInt64LE(0x1000n, added + 0x10); result.writeBigUInt64LE(52n, added + 0x20); return result; } ``` 2. Call `readElfSymbols(additionalVmMapping(image, 0x100), ["_kDartVmSnapshotData", "_kDartIsolateSnapshotData"])`. Repeat after swapping the two 56-byte records in the relocated program-header table. As a control, add a mapping with file offset `0x1000`, which agrees with the original mapping. 3. Package the original-order conflicted image as `lib/x86_64/libapp.so` in a disposable APK ZIP. Call `new FlutterBuildProvider().execute({ operation: "inspect_dart_aot", input: { path: apkPath } })`. Parse the result with the operation's result schema and inspect coverage, section offsets and hash-source count. Close the provider and remove the fixture after the test. ## Expected behavior The VM range with conflicting file translations remains unresolved, and AOT coverage reports the missing structural certainty. The unaffected isolate range remains observable. Two equivalent mappings remain usable because they agree on the file bytes. Snapshot hash observations must identify only headers supported by unambiguous ranges. ## Actual behavior The original-order conflicted image returned VM offset 4096 and the reversed image returned VM offset 256, both with no parser failures. The isolate offset remained 8192 in both orders. The equal-mapping control returned VM offset 4096 without failures. The APK inspection returned `coverage: "complete"`, `libapp.coverage: "complete"`, a VM section at offset 4096 and two snapshot hash sources. The corrected focused probe failed its partial-coverage assertion. An earlier probe failed in its own diagnostic after obtaining the parser results; that diagnostic was corrected before the provider assertion ran. ## Evidence - Expected source: `AGENTS.md` requires unresolved identity/applicability to remain unknown. `docs/flutter-analysis.md:49` ties section evidence to exported ELF symbols and defines structural coverage; `src/flutter/DartElf.ts:49` defines the returned offset as a load-segment mapping and rejects other ambiguous ELF identities. - Failure source: `src/flutter/DartElf.ts:217` selects the first containing load segment. `src/flutter/FlutterBuildProvider.ts:1043` derives structural coverage from the returned inventory, which contains no mapping failure for this fixture. The focused parser and APK provider runs produced the offset-dependent and complete-coverage results above. - Evidence provenance: observed - Local verification: reproduced - Reproduction completeness: complete The fixture uses `src/flutter/FlutterBuild.fixture.ts:8` for the complete AOT image and adds only an in-bounds program-header record. This is a static-analysis reproduction and makes no claim about executing the image in an operating-system loader. ## Restoration check Inspect the conflicting fixture in both header orders. Neither result may assert a uniquely resolved VM file range or count that ambiguous header as a supported hash source. Report partial structural coverage with an actionable ambiguity limitation while preserving the isolate evidence. The equal-mapping control must retain the VM symbol, and the unmodified AOT fixture must retain complete structural coverage. ## Runtime or environment Source baseline 8b181716aca2cb467be499cba226abfb5ae19141. Node v26.10.0, npm 11.19.1 and lockfile-installed dependencies. Verification used `npm run test:focused`, synthetic ELF64 bytes and a disposable APK ZIP through the public provider operation. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: A bounded malformed library produces unsupported resolved offsets and complete structural coverage. The parser's result changes with program-header order, and the public AOT provider counts the ambiguous VM header as supported evidence. - Workaround status: none - Workaround basis: The provider has no input option that exposes the competing mappings or excludes only the ambiguous header. External manual interpretation does not restore the provider's evidence result.
bsakaguchi 2026-10-15 18:28:55 +00:00
Author
Owner

@morluto commented on GitHub (Oct 14, 2026):

Verified the reported defect is addressed on main by e3a012d6c9.

Root cause and resolution: Flutter ELF virtual-address translation accepted an ambiguous PT_LOAD mapping according to header order, which could publish conflicting snapshot evidence.

Validation: tests/acceptance/flutterAnalysis.test.ts — CLI and MCP qualify conflicting load mappings and bounded ELF notes confirms order-independent conflicting mappings produce partial coverage, unresolved VM evidence, while unaffected isolate evidence remains.

Evidence: CI run 500e: owner unchanged and assertion passed.

Verification scope: Constructed ELF through CLI/MCP, not a real Flutter app.

Current main CI has separate failures under repair; this closure does not claim the complete main workflow is green.

<!-- gh-comment-id:6162525119 --> @morluto commented on GitHub (Oct 14, 2026): Verified the reported defect is addressed on main by e3a012d6c98c60f3254e41e8b7d9c9f66e7cbe17. Root cause and resolution: Flutter ELF virtual-address translation accepted an ambiguous PT_LOAD mapping according to header order, which could publish conflicting snapshot evidence. Validation: `tests/acceptance/flutterAnalysis.test.ts` — `CLI and MCP qualify conflicting load mappings and bounded ELF notes` confirms order-independent conflicting mappings produce partial coverage, unresolved VM evidence, while unaffected isolate evidence remains. Evidence: CI run 500e: owner unchanged and assertion passed. Verification scope: Constructed ELF through CLI/MCP, not a real Flutter app. Current main CI has separate failures under repair; this closure does not claim the complete main workflow is green.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#842
No description provided.