Commit Graph
55 Commits
Author SHA1 Message Date
morluto 63b0426e40 fix(errors): rethrow internal invariant violations from plist consumers and the native output projection (#11029)
* fix(plist): rethrow internal invariant violations from plist consumers

KeyedArchiveReader reported any non-limit decode failure as a format
failure, InterfaceBuilderAnalysis listed it as an invalid archive,
ReleaseExposureReader fell back to scanning raw bytes, and the native
plist parser reported it as provider output. An InternalInvariantError
is a REA defect, not evidence about the input, so each consumer now
rethrows it. The native parser's binary path now shares its one cause
projection instead of a duplicate.

* fix(native): rethrow internal invariant violations from the native output projection

nativeOutputFailure wrapped any producer failure as AnalysisOutputError,
so a REA defect thrown while reading a plist or dispatching a command was
reported as native output parsing. It now rethrows InternalInvariantError,
which reaches the provider's adapter-failure path with the invariant as
its cause.

* fix(artifacts): rethrow internal invariant violations from the shared artifact failure mapper

translateArtifactFailure turned every unrecognised cause into an
ArtifactOperationError with reason io, so the keyed-archive and
Interface Builder rethrows still reached users as artifact read
failures. The shared mapper now rethrows InternalInvariantError, and the
deferred client reports it as a ProviderAdapterError. Provider-level
tests drive both operations through that client.

* refactor(dotnet): report managed reader defects through invariantViolation (#11030)

* refactor(dotnet): report managed reader defects through invariantViolation

The managed readers threw plain TypeError and RangeError for states their
callers rule out: an allowance or method page outside the input schema, a
missing snapshot after identity admission, and a missing CLI header after
the caller already returned for it. These are REA defects, not malformed
targets, so they throw invariantViolation. The two CLI re-checks are gone:
the callers pass the CLI header they already narrowed. The dotnet
parser-plain-throw baseline drops from 6 to 0.

* refactor(providers): refuse unusable tool paths and record marker mismatches without throwing to their own catch (#11031)

* refactor(firmware): refuse unusable tool paths without throwing to its own catch

resolveFirmwareCommand threw a plain TypeError for a configured engine or
limiter path that is not a regular file, only to catch it in the next line
and wrap it as an unavailable capability. A helper now returns why a path
cannot run, and each caller builds the one refusal directly. Refusal
reasons are unchanged; the directory tests now pin them exactly. The
firmware parser-plain-throw baseline drops from 2 to 0.

* refactor(pwndbg): refuse unusable debugger paths without throwing to its own catch

inspectPwndbgCore threw plain Errors for a relative or wrong-kind
configured path only to catch them and wrap them as an unavailable
capability. A helper now returns why a path cannot be used, with any host
error as its cause, and the loop builds the one refusal. Cancellation
between host checks still propagates. Refusal reasons are unchanged. The
PwndbgCoreContext parser-plain-throw baseline entry is removed.

* refactor(pwntools): record a mismatched failure marker without throwing to its own catch

readPwntoolsFailureEvidence threw a plain Error when the private bridge
marker disagreed with the exit status, only to catch it and record its
message as the marker failure. The mismatch is now recorded directly. The
recorded evidence is unchanged; a unit test pins both the matching and
the mismatched marker. The PwntoolsResourceLimits parser-plain-throw
baseline entry is removed.

* fix(android): report an unobserved Java probe as a REA defect, not a Java refusal (#11032)

* fix(android): report an unobserved Java probe as a REA defect, not a Java refusal

When runOwnedCommand resolved without observing the completed run, the
probe threw a plain Error that its catch then classified as a Java
runtime refusal, telling the caller to review their launcher. The state
is a broken internal assumption, so the probe throws invariantViolation
and projects it as a jadx adapter failure. The JadxJavaProbe
parser-plain-throw baseline entry is removed.

* refactor(native): report native provider defects through invariantViolation (#11033)

* refactor(native): report native provider defects through invariantViolation

Native providers threw plain Error and TypeError for states their own
earlier steps rule out: a client with no target, a measured slice with no
selection, a read longer than requested, a decoder command without its
runtime, an LLDB root released before its children, and an IPS integer
fact from another reader. These are REA defects, so they throw
invariantViolation. NativeUiInterruptionControl no longer needs a throw:
recording the deadline interruption returns the interruption its error is
built from. Six native parser-plain-throw baseline entries drop.

* refactor(native): report malformed lipo, swift-demangle and UI helper output through ParseFailure (#11034)

* refactor(native): report malformed lipo and swift-demangle output through ParseFailure

The lipo and swift-demangle output parsers threw plain TypeError for
output that breaks their framing, and the lipo result classifier caught
every TypeError as malformed output, so a host TypeError from a REA defect
was reported as lipo output. Both parsers now throw malformedInput with
their own format, and the lipo classifier accepts ParseFailureError
instead of TypeError. Messages and the consumers' output and format
failure categories are unchanged. Four native parser-plain-throw
baseline entries drop.

* refactor(native): report the UI helper's non-JSON output through ParseFailure

The native UI helper runtime threw a plain Error when the helper's
stdout was not JSON. It now throws malformedInput with its own format and
the JSON failure as cause. The observation boundary still reports it as a
native-macos adapter failure with the same reason. The
NativeUiHelperRuntime parser-plain-throw baseline entry is removed.

* refactor(verify): keep process-lifecycle owners out of the parser plain-throw guard (#11035)

* refactor(verify): keep process-lifecycle owners out of the parser plain-throw guard

JadxWorkspaceRoot and PwntoolsDecoder sit in parser folders but own a
private helper process; their remaining plain throws report the helper's
startup, handshake and cleanup outcomes, not parse faults. The guard now
names them as process-lifecycle owners and leaves them out, so their
five baseline entries drop without inventing parse errors for process
failures.

* refactor(parsers): report the remaining artifact, il2cpp, model and domain defects through invariantViolation (#11036)

* refactor(parsers): report the remaining artifact, il2cpp, model and domain defects through invariantViolation

Nine plain Error, TypeError and RangeError throws in parser folders
reported broken internal assumptions or caller contracts (an
uninitialized ZIP or DMG reader, a missing scan result, a non-byte
stream chunk, an invalid traversal or marshal limit, a header count or
linking fact the reader itself should have produced, a misordered
Safetensors budget, an append after fingerprinting). None is an input
fault, and no catch site depends on their class. They now throw
invariantViolation with the same messages, and their parser-plain-throw
baseline entries drop.

* refactor(evidence): refuse an earlier Evidence format through ParseFailure (#11037)

* refactor(evidence): refuse an earlier Evidence format through ParseFailure

UnsupportedEvidenceFormatError restated the ParseFailure algebra as its
own TypeError subclass. The format owner now throws unsupportedInput for
the evidence-bundle format at the evidence_format field and exports the
predicate its consumers use. The bundle reader's unsupported-format kind
and message are unchanged. The snapshot reader surfaced only TypeError
messages, so it now also surfaces the format refusal and keeps its
recreate guidance; a boundary test pins that.

* refactor(native): report Mach-O reader and inspection defects through invariantViolation (#11042)

The Mach-O inspection plan reads the lipo, nm and dyld_info captures it
just ran, the dispatch metadata reader is called only for Mach-O
executables, and the command-name reader takes limits its callers
derive. A missing capture, a non-Mach-O target or a malformed limit is a
REA defect, not an input fault, so these six sites throw
invariantViolation with their existing messages instead of TypeError.
No catch site depends on their class. Their parser-plain-throw baseline
entries drop.

* fix(artifacts): join the Interface Builder cleanup failure to a catalog defect

When catalog work failed while the concurrent Interface Builder reader
failed to close, analyzeAppleAssetCatalogs built the primary through
translateArtifactFailure before joining cleanup. That mapper now rethrows
an InternalInvariantError, so a defect skipped the join and the reader's
retained resources were lost. The defect now becomes the artifact graph
provider's adapter failure at that site and joins the cleanup failure as
before.
2026-11-15 19:35:22 +08:00
morluto 557bf41c2c refactor(macho): select slices through one owner with typed refusals (#10874)
* refactor(macho): name load-command codes through the shared LC table

* refactor(macho): name version-min and string commands through the shared tables

* refactor(parsers): report XML, web artifact and Mach-O failures through ParseFailure (#10760)

* refactor(parsers): report XML, web artifact and Mach-O failures through ParseFailure

* refactor(xml): type XML parse failures as malformed or unsupported only

* refactor(parsers): catch per-format document and source failure classes (#10794)

* refactor(parsers): report apktool strings and XML plist source failures through ParseFailure

* refactor(apktool): drop the unused ParseFailureError import

* refactor(native): select ELF sections through the keyed owner

* test(native): pin returned exports and versions for repeated version sections

* refactor(nativeaot): read neither of repeated frozen object regions (#10790)

* refactor(nativeaot): read neither of repeated frozen object regions through the keyed owner

* refactor(parsers): retire every first-match section lookup (#10793)

* fix(nativeaot): report an ambiguous frozen object region as partial (#10812)

* refactor(native): select program headers and load commands through the keyed owner (#10827)

* refactor(native): select the GOT base and dependency segments through the keyed owner (#10847)

* refactor(native): select the GOT base and dependency segments through the keyed owner

resolveGotBase selects the SHT_DYNAMIC section and the allocated .got.plt/.got sections with uniqueKeyed, so a repeat leaves the GOT base unknown instead of taking the first match; elfDependencies reads PT_LOAD segments through the same keyed program table as PT_DYNAMIC. A new keyed-first-match guard recognizes a find/findLast or filter-then-[0] whose predicate compares a key field, whatever the table is called; existing matches are baselined. The unwind fixture can declare PT_DYNAMIC headers and repeated .dynamic/.got.plt sections.

* test(native): pin the PT_DYNAMIC path and destructured keyed lookups

The keyed-first-match guard moves to scripts/verify/keyed-first-match.mjs with focused tests, and now recognizes a destructured key in any position and a destructured filter predicate. The single PT_DYNAMIC unwind test declares .dynamic as SHT_PROGBITS so only the program header supplies DT_PLTGOT, and asserts the resolved ranges.

* fix(macho): refuse repeated chained-fixup and dyld-info tables (#10850)

parseMachoLayout kept the last LC_DYLD_CHAINED_FIXUPS range and merged the rebase/bind streams of every LC_DYLD_INFO(_ONLY) command. A repeat now refuses the slice as malformed. NativeMachoInspection's chained import-name reader already declined repeated LC_DYLD_CHAINED_FIXUPS; that rule is now covered by a test.

* refactor(parsers): retire the Mach-O, source-map, NDJSON and managed-graph failure classes (#10818)

* refactor(parsers): retire the Mach-O, source-map, NDJSON and managed-graph failure classes

* refactor(plist): report property-list and keyed-archive failures through ParseFailure (#10822)

* refactor(plist): report property-list and keyed-archive failures through ParseFailure

* refactor(kuna): report Kuna document failures through ParseFailure (#10824)

* refactor(kuna): report Kuna document failures through ParseFailure

* test(kuna): pin the limit and malformed facts of Kuna document failures

* refactor(plist): report plist decode budgets through ParseFailure (#10842)

* refactor(plist): report plist decode budgets through ParseFailure

The plist preflight owner throws a ParseFailure limit (plist-decode-bytes) for its byte budget, the shared PlistNestingLimitError for nesting depth, and a malformed failure for a reference cycle, instead of a per-format PropertyListDecodeBudgetFailure whose meaning each caller re-mapped through a fail callback. The fail option, PropertyListDecodeBudgetFailure and interfaceBuilderDecodeBudgetFailure are removed; the parser-format-failure-class baseline reaches zero.

* refactor(plist): report keyed-archive allowances as typed limit failures (#10844)

keyedArchive.ts and decodeKeyedArchiveBytes throw decodeLimit parse failures (keyed-archive-bytes, -object-table-entries, -values-per-object, -reference-edges) and malformed parse failures instead of plain RangeError/TypeError. KeyedArchiveReader no longer classifies every RangeError as a limit: only a limit parse failure or a host stack/capacity limit is one. The unreachable 128-level scan nesting check is removed; projectPlistValue already refuses the archive first.

* test(plist): expect the nesting limit as its ParseFailure carrier

* fix(verify): count a filter index only on the filter's own result

* refactor(macho): select slices through one owner with typed refusals

* refactor(keyed): select FIT properties and certificate extensions through uniqueKeyed

* refactor(keyed): key each FIT node once, pin repeated FIT properties and subjectKeyIdentifiers, and type the unknown Mach-O header as unsupported

* refactor(plist): report plist and NIBArchive input faults through ParseFailure and defects through invariantViolation (#10895)

* refactor(plist): report plist and NIBArchive input faults through ParseFailure and defects through invariantViolation

* fix(plist): report a cut-short NIB header or plist length record as truncated

* fix(native): project the selected Mach-O's parse failures through the shared owner

nativeMachoSourcePrimary mapped every non-limit ParseFailureError to
AnalysisOutputError, so a malformed or truncated selected Mach-O was
reported as unreadable tool output and an unsupported one lost its
category. It now uses parseFailureAnalysisError like the ELF, Go and
other byte-format providers: malformed and truncated bytes are an
invalid path, unsupported bytes an unsupported target, and a limit
still falls through to its producer's budget.
2026-11-15 18:36:30 +08:00
morluto 78fd365bdd refactor(macho): name load-command codes through the shared LC table (#10714)
* refactor(macho): name load-command codes through the shared LC table

* refactor(macho): name version-min and string commands through the shared tables

* refactor(parsers): report XML, web artifact and Mach-O failures through ParseFailure (#10760)

* refactor(parsers): report XML, web artifact and Mach-O failures through ParseFailure

* refactor(xml): type XML parse failures as malformed or unsupported only

* refactor(parsers): catch per-format document and source failure classes (#10794)

* refactor(parsers): report apktool strings and XML plist source failures through ParseFailure

* refactor(apktool): drop the unused ParseFailureError import

* refactor(parsers): retire the Mach-O, source-map, NDJSON and managed-graph failure classes (#10818)

* refactor(parsers): retire the Mach-O, source-map, NDJSON and managed-graph failure classes

* refactor(plist): report property-list and keyed-archive failures through ParseFailure (#10822)

* refactor(plist): report property-list and keyed-archive failures through ParseFailure

* refactor(kuna): report Kuna document failures through ParseFailure (#10824)

* refactor(kuna): report Kuna document failures through ParseFailure

* test(kuna): pin the limit and malformed facts of Kuna document failures

* refactor(plist): report plist decode budgets through ParseFailure (#10842)

* refactor(plist): report plist decode budgets through ParseFailure

The plist preflight owner throws a ParseFailure limit (plist-decode-bytes) for its byte budget, the shared PlistNestingLimitError for nesting depth, and a malformed failure for a reference cycle, instead of a per-format PropertyListDecodeBudgetFailure whose meaning each caller re-mapped through a fail callback. The fail option, PropertyListDecodeBudgetFailure and interfaceBuilderDecodeBudgetFailure are removed; the parser-format-failure-class baseline reaches zero.

* refactor(plist): report keyed-archive allowances as typed limit failures (#10844)

keyedArchive.ts and decodeKeyedArchiveBytes throw decodeLimit parse failures (keyed-archive-bytes, -object-table-entries, -values-per-object, -reference-edges) and malformed parse failures instead of plain RangeError/TypeError. KeyedArchiveReader no longer classifies every RangeError as a limit: only a limit parse failure or a host stack/capacity limit is one. The unreachable 128-level scan nesting check is removed; projectPlistValue already refuses the archive first.

* test(plist): expect the nesting limit as its ParseFailure carrier

* refactor(plist): report plist and NIBArchive input faults through ParseFailure and defects through invariantViolation (#10895)

* refactor(plist): report plist and NIBArchive input faults through ParseFailure and defects through invariantViolation

* fix(plist): report a cut-short NIB header or plist length record as truncated

* fix(native): project the selected Mach-O's parse failures through the shared owner

nativeMachoSourcePrimary mapped every non-limit ParseFailureError to
AnalysisOutputError, so a malformed or truncated selected Mach-O was
reported as unreadable tool output and an unsupported one lost its
category. It now uses parseFailureAnalysisError like the ELF, Go and
other byte-format providers: malformed and truncated bytes are an
invalid path, unsupported bytes an unsupported target, and a limit
still falls through to its producer's budget.
2026-11-15 18:24:35 +08:00
morluto a090fa7098 fix(il2cpp): report the exceeded native-link maximum in the public refusal (#10741)
* fix(il2cpp): report the exceeded native-link maximum in the public refusal

* fix(il2cpp): report each native-link budget's maximum in the unit its producer counts

* refactor(elf): report pointer relocation failures through ParseFailure (#10748)
2026-11-15 13:44:54 +08:00
morluto 3a29b6b8ea refactor(il2cpp): report format failures through ParseFailure (#10701) 2026-11-14 21:11:29 -05:00
morluto 89640a446a fix(parsers): stop reading every RangeError as a format failure (#10602)
* refactor(parsers): report format failures through one ParseFailure algebra

Add ParseFailure (malformed, truncated, unsupported, limit, with format,
offset and field) and its one carrier, ParseFailureError, in the domain.
BinaryReader now names truncation and the field it read, and its native
format and resource failures are ParseFailureError subclasses.

Providers projected a format failure with their own instanceof ladder,
and some dropped the selected path from the invalid_format message.
parseFailureAnalysisError now owns that projection for the native,
Go, devicetree, V8, Windows Shortcut and Electron fuse providers.
The V8 code cache, Windows Shortcut and Electron fuse format classes
are removed in favour of the algebra.

The architecture guard counts raw Buffer and DataView reads, plain
Error throws in parser folders and plain JSON.parse of parser input
against baselines that can only shrink.

* fix(parsers): stop reading every RangeError as a format failure

Mach-O, Swift and Objective-C metadata parsers threw RangeError for a
truncated or malformed record, so their catch sites treated any
RangeError as a partial decode: a call stack overflow or a host string
limit became an "unresolved" metadata reason, and the IL2CPP Mach-O
path reported it as a malformed container.

Those parsers and the CIL method body reader now throw ParseFailureError.
hostRangeErrorKind is the one interpreter of a host RangeError (stack
overflow, host capacity, raw out-of-bounds read), and
parseFailureFromCause admits only a parse failure or a raw
out-of-bounds read as evidence about the input. Fixup stream catch-alls
rethrow host limits. The architecture guard counts the remaining direct
instanceof RangeError checks.

* fix(parsers): preserve Apple metadata failure ownership

* test(architecture): shrink parser failure baseline

* fix: preserve uncertainty for host range errors
2026-11-15 10:03:26 +08:00
morluto 2705aad365 fix(il2cpp): select universal binary slices through the shared Mach-O selection (#10661)
* fix(il2cpp): select universal binary slices through the shared Mach-O selection

* test(il2cpp): assert selection facts instead of full sentences
2026-11-14 18:58:48 -05:00
morluto ef15353c69 refactor(android): build mobile-provider cancellations with a required reason (#10590)
* refactor(errors): require a reason for every analysis cancellation

Add cancelledBy, the one constructor for AnalysisCancelledError. Its
reason argument is required: an aborted signal, an earlier cancellation,
a reason carried from an inner failure, or an OwnerCancellation when REA
closed the work's owner itself.

Closed adb, apktool, firmware, sqlite, gdb, web-bundle analyzer and
binary-session record owners now report OwnerCancellation.ownerClosed
instead of an absent reason. Firmware's predecessor wait returns its
cancellation as a Result, removing an unreachable reason-less fallback.

An architecture guard rejects new direct constructions, with a counted
per-file baseline that can only shrink.

* refactor(errors): share one aborted-signal predicate with cancelledBy

* refactor(process): return a departing caller's reason from a shared startup wait

* refactor(android): build mobile-provider cancellations with a required reason

Migrate every remaining AnalysisCancelledError construction under
src/adb, src/android, src/apktool, src/apkSignature, src/flutter,
src/il2cpp, src/dotnet and src/frida to cancelledBy and lower the guard
baseline from 671 to 608. A closed adb provider reports
OwnerCancellation.ownerClosed for later probes, and JADX and apktool
shutdown abort with that typed reason.

* refactor(providers): build decompiler-provider cancellations with a required reason (#10587)

Migrate every AnalysisCancelledError construction under src/ghidra,
src/ida, src/cutter, src/jeb and src/kuna to cancelledBy and lower the
guard baseline from 671 to 572. Closed Kuna target commands report
OwnerCancellation.ownerClosed instead of an absent reason, and Kuna and
JEB close abort their lifetimes with that typed reason.

* fix(errors): read the reason of any signal-shaped cancellation source

* test(ci): cover the counted-baseline comparison behind the architecture guard
2026-11-14 18:58:38 -05:00
morluto b138f52e12 refactor: prune internal seams and preserve configuration ownership (#10430)
* refactor: prune internal seams and preserve configuration ownership

* fix(setup): keep YAML aliases and inherited registration settings on refresh

- Reuse an unchanged YAML collection only while every alias in it still
  resolves after the edit; otherwise rebuild it so the alias becomes its
  value. A sibling anchor replaced or moved in the same refresh no longer
  leaves an unresolved alias in Hermes or Goose output.
- Keep a connection selector whose existing value already chooses stdio
  (for example an inherited Hermes transport: stdio) instead of superseding
  it; remote selectors are still replaced. Explicit stdio selectors are
  therefore no longer rewritten (Kimi expectation updated).
- When the whole Hermes registration is inherited through a merge,
  override it with that merge and write only the changed fields.

* fix(setup): edit registration fields whose YAML key is an alias

A key written as an alias to a string scalar (for example *field with
field: &field env) was treated as a source-only key, so any change to
its value was refused in Hermes and Goose. Resolve such keys to their
string, keep the aliased spelling while its anchor survives the edit,
and write the plain key when the same edit rebuilds the anchor.

* test(process): bound cleanup-boundary waits and always release gates

Both cancellation tests awaited a bare started promise and released
their gates only on success, so a missed boundary waited for the outer
deadline and could leave cleanup parked. Use awaitAcknowledgement and
release and join the cleanup in finally.

* fix(setup): repair only aliases an edit leaves unresolved

Replace the pre-edit alias survival guess, which expanded aliases to
sibling anchors that survive unchanged, with an exact repair: record
what each alias in the replaced value resolves to, write the edit, then
replace only aliases left without a preceding anchor by that value.

- Keep an aliased key's source position, so its anchor stays ahead of
  later aliases.
- Treat an aliased key as its string only when no other key in the map
  resolves to the same string; an ambiguous one stays guarded.
- Override an inherited Hermes registration only when the requested
  entry keeps every inherited field, so an explicit replacement can drop
  remote selectors.

* fix(setup): repair aliases whose binding an edit changes, keeping comments

An alias whose own anchor was removed could resolve to an earlier anchor
with the same name and silently change value. Record the node each alias
resolved to and repair any alias that no longer resolves to that node.
Carry the alias's comments and spacing onto the repaired value.

* test(setup): split the Hermes anchor and merge refresh cases

* fix(setup): refuse removing an overridden key its merge would restore

The merge-retention check skipped keys the mapping also overrides, so
dropping such a key (for example a remote url during an explicit stdio
replacement) let the retained merge restore it. Check removal before
skipping overridden keys, so the edit is refused with the existing
message instead of producing a registration that cannot be applied.
2026-11-14 04:08:37 -05:00
morluto cdc4541ef7 refactor: remove redundant seams and preserve cleanup ownership (#10375)
* refactor: remove redundant seams and preserve cleanup ownership

* fix: validate PE resource extents before budget checks
2026-11-13 10:11:06 -05:00
morluto 02ebd3e02d refactor: prune test-only seams and obsolete helpers (#10275) 2026-11-12 19:24:54 -05:00
be6ec3f164 feat(il2cpp): retain v108 header and string evidence (#9925)
* feat(il2cpp): retain v108 header and string evidence

* fix(il2cpp): preserve v108 BOMs and yield while scanning

* fix(il2cpp): preserve uncertainty in v108 layout refusals

---------

Co-authored-by: dhruvac29 <dhruvac29@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-11-11 08:42:55 -05:00
8052f8daf0 fix(elf): preserve virtual relocation identity (#9990)
* fix(elf): keep compressed storage out of decoded metadata facts

* fix(elf): preserve virtual relocation identity

Keep linked initializer backing and relocation values in their owning virtual
or ET_REL section coordinates. Replace the IL2CPP physical-copy materializer
with compact virtual value facts while preserving file-backed capacity.

Reuse initializer repairs and original regressions from ShuaixinHuang PRs
repair retains independent alias values instead of blanket alias refusal.

Co-authored-by: 帅鑫 Huang <1836656514@qq.com>

* fix(elf): admit compressed string tables the profile does not read

SHF_COMPRESSED string tables are rejected only when they name sections
or symbols. An unreferenced string table is not decoded, so it no longer
makes an otherwise analyzable ELF unsupported.

* fix(il2cpp): admit virtual pointer workspace before retention

* fix(elf): reject null relocation target sections

* fix(il2cpp): avoid decoding unrelated Mach-O words

* fix(il2cpp): preserve uncertainty in candidate scans

* fix(il2cpp): bound uncertain array candidates

* fix(il2cpp): preserve unknown registration candidates

* fix(il2cpp): classify type kinds before bound data

* fix(il2cpp): bind candidate counts to matching names

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: 帅鑫 Huang <1836656514@qq.com>
2026-11-11 18:13:18 +08:00
morluto 3c736dfe11 fix(targets): reject ambiguous native image selections (#9933)
fix(targets): refuse ambiguous slice and file mappings
2026-11-10 22:50:13 -05:00
8bc01b48b4 feat(native): list ELF and Mach-O initializer and finalizer functions (#9574)
* feat(native): list ELF and Mach-O initializer and finalizer functions

inspect_native_initializers and inspect-native-initializers list the
functions an ELF or Mach-O image runs before and after main: ELF
DT_INIT, DT_FINI, preinit, init and fini arrays and .ctors/.dtors, and
Mach-O __mod_init_func, __mod_term_func and __init_offsets, with slot
addresses, resolved targets, symbols where available and relocation
facts for relocatable objects. Nothing is executed. Slot, symbol,
relocation and note budgets are shared across tables, sentinels are
matched at the image width, and target-derived names are bounded and
marked untrusted.

* fix(native): keep ELF initializer slots unresolved when relocation coverage is partial

A skipped, unreadable or over-budget section relocation table now keeps
every slot it could reach unresolved instead of reading the stored word as
raw or dropping a .ctors slot as a sentinel. Dynamic writes that only
partly overlap a slot, or write it twice, leave it unresolved. Linked
images no longer reapply retained non-SHF_ALLOC link-time records.

The dynamic relocation walk now pauses at the shared reader's step
boundaries and observes cancellation there, resolved targets need only
their first byte mapped, and unreadable symbol names make the report
incomplete.

* fix(native): stop reporting unchecked Mach-O initializer words as resolved

Object files now apply their own section relocations: an UNSIGNED entry
against a defined symbol gives symbol_addend, one against an undefined
symbol gives unresolved_import, and any other entry leaves the slot
unresolved. Linked images without a fixup decoder, such as 32-bit ones,
keep pointer slots unresolved when an LC_DYLD_INFO bind stream or
LC_DYSYMTAB external relocations could replace the stored word.

LC_DYLD_INFO rebases now report dyld_info_rebase instead of
chained_fixup, and unreadable symbol names make the report incomplete.
Section headers keep their declared reloff and nreloc for this.

* docs(native): move initializer guide under docs/guides/native

The documentation guide assigns analyst workflows to docs/guides/<domain>/.
Move the guide there, place its navigation and directory entries in the
Native binaries group, and update links from the docs index, CLI guide,
spec and authored skill. The public /native-initializers route is
unchanged.

The guide and spec also describe per-slot relocation coverage, retained
link-time records, Mach-O object relocations, undecoded bind streams,
the dyld_info_rebase resolution and unreadable names.

* fix(native): keep IFUNC and partly relocated ELF initializer slots unresolved

An absolute relocation against an STT_GNU_IFUNC symbol no longer reports
the resolver address as the target. Section relocation records now use
their real write width, so a record that writes only part of a slot,
starts inside it or repeats it leaves the slot unresolved instead of
reading a raw zero or dropping a .ctors slot as a sentinel.

On 32-bit ARM the Thumb bit is cleared when locating a target's section
and file offset, while value_va keeps the stored callable value.

* fix(native): locate Thumb Mach-O initializer targets and reject arm64_32 with a 64-bit header

On CPU_TYPE_ARM the Thumb bit is cleared when locating and naming a
target, since nlist values do not carry it. An arm64_32 image that
declares a 64-bit header is rejected as malformed rather than read with
8-byte slots. The guide and spec describe IFUNC relocations, partly
relocated section slots, Thumb targets and this rejection.

* fix(native): index initializer address lookups and keep ambiguous mappings unknown

ELF and Mach-O initializer lookups now build the shared file mapping
index once per image, so each slot and target lookup is logarithmic in
the number of load segments rather than a scan of every mapping.

An address that load segments map ambiguously no longer falls back to a
section header offset. Its file offset is reported as unknown and the
report is incomplete; only genuinely unmapped spans use the section
fallback.

* fix(native): report Mach-O bind names over the name budget

A bound import name longer than the 1024-byte name budget was dropped
without a trace, although it is the only identity of an unresolved
initializer target. It now counts toward the over-long name limitation
and makes the report incomplete.

* test(native): count mapping lookups instead of timing the load index regression

The load-mapping regression asserted a wall-clock bound, which is
sensitive to machine load. It now spies on the shared mapping module and
requires the same number of mapping scans and index builds for 8 and 64
slots, so a per-slot scan of every load segment fails deterministically
on a small fixture.

* fix(native): yield while decoding legacy rebase runs

* fix(native): preserve initializer mapping and coverage

* fix(native): index legacy fixup spans

* fix(native): preserve relocation uncertainty and bound bind lookup work

* fix(native): validate ELF slot mappings and yield section relocation scans

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-11-09 08:58:12 -05:00
Dhruvilkumar Ashokbhai Chodvadiyaanddhruvac29 85be0f70a6 fix(artifacts): guide retries for symlinked files (#8725)
* fix(go): suggest resolved path for rejected symlinks

* test(go): cover unresolved symlink recovery paths

* fix(go): omit schema recovery for resolved symlinks

* fix(artifacts): share resolved-path recovery across inspectors

* fix(sqlite): retain resolved database path through snapshot reads

* fix(captures): retain symlink retry guidance

* fix(artifacts): preserve retry hints through redaction and selected reads

---------

Co-authored-by: dhruvac29 <dhruvac29@users.noreply.github.com>
2026-11-04 19:58:06 +08:00
gensokyo-dev e18594b247 refactor(composition): unify capability bindings and cleanup ownership (#8441)
Bind typed service creation, observed availability and retryable cleanup in one composition owner. Reuse selected CLI/MCP factories and canonical contract groups without copying provider operation inventories.

Closes #8429. Refs #740.

Validated paired real application workflows, actual local Codex CLI Terra/high use, complete Evidence and Unknown checkpoint parity, compiler-backed import boundaries, SDK schemas and final real mixed routing. Automated review findings were fixed at their producing owners. Existing exact-base CodeQL alerts are documented on the PR under the owner-authorized unrelated-check exception; no global alerts or security rules were changed.

Assisted-by: Suika (gensokyo-skills:suika-scatter-gather-planning)
2026-11-01 13:30:21 +08:00
morluto ef9ab91e42 fix(il2cpp): validate retained declaring type relationships (#7946) 2026-10-29 08:16:57 +08:00
morluto 183e2e2d1e fix(il2cpp): validate structural record extents (#7861) 2026-10-29 01:55:47 +08:00
gensokyo-dev 570abe95f2 feat(android): link native declarations to static JNI candidates (#7472)
Link original DEX native declarations to per-ABI function exports and relocated static JNI table candidates through shared CLI/MCP workflows. Preserve global attribution ambiguity, exact provenance, partial coverage and retained Evidence; default MCP delivery to bounded summaries with filtered/batch pages.

Use one immutable ELF relocation decoder with streaming IL2CPP materialization, cooperative bounded export/version parsing and bounded JNI state. Reuse validated session inventories without loading target libraries or executing JNI code.

Validation: relevant type/lint/build and parser/domain/public CLI/MCP regressions; genuine four-ABI NDK fixtures and independent library/slot oracles; actual JDK/JADX Conscrypt workflows with retained-source removal. Full measurements and limitations are recorded in docs/verification/android-jni-bindings-2026-10-27.md.

Closes #6403.
2026-10-27 18:53:22 +08:00
morluto c7afedc3d2 refactor(macho): consolidate universal image selection 2026-10-27 13:04:22 +08:00
morluto 44310bba32 fix(il2cpp): validate selected FAT slice identity 2026-10-27 12:37:39 +08:00
morluto dd2cbbf1a2 fix(il2cpp): require FAT container identity 2026-10-27 12:31:35 +08:00
morluto a7f50e3386 refactor: consolidate ELF and CLR record interpretation
Share ELF note headers across note inspection, Flutter build IDs, Node SEA,
and recorded-crash source binding. Decode REL/RELA records once for MIPS
shared-load analysis and IL2CPP linking, removing superseded scalar helpers.

Share the CLR header prefix between desktop detection and managed PE parsing
while preserving their distinct read bounds and admission policies. Cover
those differences and ignored R_NONE fields with production-boundary tests.

Validation: 493 focused tests passed, two existing skips; static checks and
test discovery passed. Public managed/desktop CLI and ELF notes CLI/MCP
workflows exercised; no real external analysis providers were run.
2026-10-26 16:50:08 +08:00
morluto 6336fe5bb5 refactor: consolidate binary analysis admission and format ownership
Reuse the existing provider input admission helper across twelve services,
preserving cancellation, schema errors, path policies, and Evidence handling.
Share ELF dynamic records across Dart, MIPS, and IL2CPP readers, and reuse
Mach-O segment and section records for Node SEA location.

Require canonical DOS ownership before GPU PE section discovery so relocation
bytes cannot masquerade as a PE pointer. Cover valid short DOS headers and
the malformed case through both inventory and the public CLI.
2026-10-26 16:44:21 +08:00
morluto b3818bbba2 refactor(il2cpp): share generic container byte decoding 2026-10-26 15:00:41 +08:00
morluto fdf5a33fe2 refactor(tests): keep fixture adapters outside runtime 2026-10-25 08:29:20 +08:00
JANG BYUNGKUNandmorluto 149b43ee61 fix(il2cpp): link arm64 builds whose registrations were inlined (#6989)
* fix(il2cpp): accept arm64 module arrays loaded through adrp/add pairs

A Unity 2022.3 macOS Master (LTO) arm64 build keeps no static CodeRegistration, so the module-array fallback that only decoded x86-64 RIP-relative references reported code-registration-not-found.
The registration owner now also decodes aligned adrp + add pairs in executable ranges and keeps the same exact-module-set and single-reference rules.
A minimal Mach-O fixture failed on the previous reader (47 passed / 1 failed) and passes here with four fail-closed variants (48/48 binary tests).

* fix(il2cpp): name the matched instruction form in inferred module-array limits

The inferred-array limitation always described RIP-relative LEA/MOV, which is wrong for arm64 results.
The provider now names the adrp/add pair on arm64, and the tool contract and docs cover both forms and state that a located array alone does not finish linking a Master build.
The new arm64 provider case failed before the wording change (1 passed / 1 failed) and both cases pass now.

* fix(il2cpp): accept type tables loaded without a static MetadataRegistration

A Unity 2022.3.62f3 macOS Master build inlines MetadataRegistration as well as CodeRegistration, so linking stopped at metadata-registration-not-found after the module array was found. Registration now infers the only field linking reads, the Il2CppType table, from the one run of type-shaped pointers that covers every referenced type index and whose start is loaded by the existing RIP-relative or adrp/add forms; types_field is null and the Evidence is inferred. The new arm64 and x86-64 fixtures failed on the previous reader (52 passed / 2 failed). Four run-selection variants (interior reference, run extended before the loaded address, two loaded runs, run shorter than the referenced indices) keep metadata-registration-not-found; instruction decoding and record-shape checks are not covered by these fixtures.

* test(il2cpp): pin adrp page deltas, register pairing and type-record shape

Every adrp fixture targeted its own 4 KiB page, so dropping the page delta or its sign extension, the add register check, the type-kind bound or the type-definition bound left all binary tests passing. Fixtures now reach a later and an earlier page, pair an add with a different destination or source register, break the type run with an out-of-range kind or type-definition index, and bound type-table candidates when the metadata references few type indices. Each of those five source mutations now fails 1 to 3 of 85 binary and provider tests.

* refactor(il2cpp): share Il2CppType kind decoding and document type-table bounds

The type-table fallback decoded the Il2CppType kind and class/value-type kinds separately from the type namer; both now use the Types owner. Zero and unaligned words are rejected before mapping lookup (Master sample metadata-registration search 92 to 68 ms). Docs and the limitation state that types_count is an upper bound, that a run spanning mappings or a small referenced type range can fail, and credit Cpp2IL StrippedCodeRegSupport and the data-side MetadataRegistration searches of Il2CppDumper and Cpp2IL. Master sample output is unchanged (11,031 code addresses, 37,025 type rows).

* fix(il2cpp): refuse generic instances when the type table was inferred

An inferred type table has no static MetadataRegistration, so the
genericMethodTable it would anchor cannot be located. Report
generic-methods-unsupported instead of reading from a null field.

* fix(il2cpp): fail closed when an inferred type table is not unique

Adversarial review found that the type-table fallback could pick another
type-shaped pointer table when the real one was unloaded or excluded, could
replace a static MetadataRegistration whose counts matched, and accepted a
run cut short by a mapping end. Require exactly one long-enough run in the
image, ending inside its mapping and loaded by code; skip the fallback when a
record's two counts matched; accept only assigned Il2CppTypeEnum kinds; and
look records up through the indexed file mapping so many mappings cannot
multiply the scan. Docs and limitations now describe the run length as at
least every referenced type index rather than an upper bound.

* fix(il2cpp): keep the type-table fallback cheap and its refusals exact

Review follow-ups: check that an address can lie in a mapping before the
throwing indexed lookup, so words pointing into gaps or zero-fill no longer
build an exception each (64 MiB: 74 s to under 2 s); treat a run starting at
its mapping start like one reaching its end; stop at the second long-enough
run instead of a 64-candidate capacity error; ignore ADRP/ADD pairs on
register 31; and say whether a counted MetadataRegistration was unusable or
no code-loaded run was found. Docs no longer generalize from one build or
state tool history they do not source.

* fix(il2cpp): judge type-table slots by their loaded value

The run scan read stored words, so a dyld-bound slot's placeholder could
decide whether a run qualified. Confirm each slot through readSlot and give
a run bounded by a bound or unresolved slot an unknown extent, so the
placeholder no longer changes the choice.

* docs(il2cpp): keep the failure-reason table layout

Shorten the two changed meanings so the table keeps its column widths and the
diff shows only those rows.

* docs(il2cpp): keep the reason table at its formatted width

* fix(il2cpp): read type-table record fields through the loader too

The previous change confirmed table slots through readSlot but still read
each record's kind and definition index from stored bytes. Read them with
readUInt32 and readSlot, and treat a record field the loader binds or leaves
unresolved like an unresolved slot: the run it bounds has an unknown extent.

* perf(il2cpp): share image mappings across loader-aware reads

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-25 04:21:18 +08:00
JANG BYUNGKUNandgensokyo-dev 3ce311757d feat(il2cpp): link generic method instances behind --generic-instances (#5785)
* feat(il2cpp): read generic containers on demand and render method spec names

Generic container indices and records are demand readers on the same metadata snapshot, so links that do not ask for generic instances allocate nothing. Type rendering keeps one graph walk with its workspace, depth and cycle guards; the C#-like names and the Il2CppDumper GetMethodSpecName names are two styles over it.

* feat(il2cpp): link generic method instances with admitted rows and kept issues

generic_instances links every genericMethodTable row through methodSpecs, genericInsts and genericMethodPointers, choosing the one CodeRegistration layout whose counts bound every row. The table is reserved against the report budget before any row is resolved; rows and issues are admitted before retention, and a contradicting row stays unknown with an address-backed issue instead of failing the link. Views page the rows by definition, state, address and name, unrequested and historical collections stay unknown, and Ghidra seeds fold instances after the definitions.

* feat(il2cpp): accept --generic-instances on the CLI and describe it in tool contracts

* docs(il2cpp): describe generic method instances and their limits

* fix(il2cpp): keep issued generic rows unknown and name their row

A method spec that contradicted the metadata still reported its pointer slot as code, while the schema and provider limitation promised unknown. Such rows now keep no address, every issue carries its genericMethodTable row, the domain validator requires unknown exactly on issued rows, and shared specs name one other row instead of all of them. The row-size lower bound moves to the metadata admission owner, the hex helper is shared, and budget wording says checked rather than reserved.

* test(il2cpp): reject ambiguous generic layouts and pin budget, yield and limit paths

* fix(il2cpp): keep unmapped generic slots per row and reject undeclared arguments

Layout selection no longer requires every genericMethodPointers slot to be
mapped; each row reads its own slot, so one unmapped slot leaves only that
row unknown with an issue. Method specs whose class or method argument count
differs from the owner's declared generic container are issued and unnamed.
Fixtures now declare the containers their generic rows fill.

* fix(il2cpp): page generic method issues instead of retaining them in summaries

Summaries keep generic_methods without its issues and count them in
counts.generic_method_issues; the generic_method_issues collection pages
them by rows, indices and fields, as code_gen_modules already does. Docs
also name the method_indices filter the request schema accepts.

* fix(il2cpp): read split generic arguments per slot and method containers on demand

Generic argument arrays may span adjacent loader ranges: admit them with
hasPointerArrayCoverage and read each slot through readPointer, instead of
requiring the whole array in one mapping.

Method generic container indices are read on demand from the method record,
like type containers, so no link path allocates a per-method column. An owner
whose container index is out of range now leaves the method spec unnamed with
an issue instead of naming it unchecked.

* fix(il2cpp): report generic entries past the address space at their row

A damaged methodSpecs or genericMethodPointers pointer could make a spec or
slot address exceed 64 bits. The issue kept that address, which the address
schema rejects, so inspection failed instead of leaving the row unknown.
Check the entry range first and attach the issue to the genericMethodTable
row (or its slot field).

* chore(il2cpp): remove unrelated formatting changes

* fix: restore adb float pattern and mobile fixture from main

The merge commit's lint-staged run rewrote these two main files: oxlint --fix
dropped the escape in [+\-], which is invalid under the RegExp v flag.

* fix(il2cpp): preserve unreadable generic method identities

* docs(il2cpp): record generic-instance workflow verification

* docs(il2cpp): qualify final integration checks

---------

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-24 16:19:05 +08:00
morluto 87745af52a fix(il2cpp): consume resolved ELF program declarations
Retain relevant program facts in the shared native directory and consume them for mappings and relocations. Remove redundant table coordinates and presence flags. This preserves extended program counts so PT_DYNAMIC beyond the raw sentinel remains visible, while load and relocation admission keep their distinct policies.
2026-10-24 09:14:21 +08:00
morluto 4610843efd fix(filesystem): preserve failure provenance across cleanup owners
Carry descriptor outcomes, cancellation, retention and physical origin as named facts so wrappers cannot drop ownership context. Replace raw primary failure unwrapping with provenance facts across artifact consumers, and use Result for Kuna span reads including undefined rejections.

Exercise actual descriptors, rollback, cancellation and cleanup retry; update brittle snapshot and completion fixtures to use their producing boundaries.
2026-10-24 07:43:49 +08:00
morluto 231e458246 fix(native): preserve parsed section and architecture facts
Classify lipo parse failures once for native and artifact consumers, retain valid read-only ELF ranges independently of optional section names, and map IL2CPP reader architecture through the existing CPU identity owner before Mach-O parsing.

Regression-first checks reproduced malformed lipo output, lost unnamed-section compiler paths, and the amd64/x86_64 adapter mismatch. Focused parser, artifact, Rust CLI/MCP, Go, and IL2CPP controls passed; authored fixtures do not establish real-provider behavior.

Fixes #5982

Fixes #3397
2026-10-24 07:28:09 +08:00
morluto 52ca222bd0 fix(il2cpp): preserve loader ownership and ABI field boundaries
Resolve pointer and scalar facts through their shared loader-aware owners before registration search or type rendering. Preserve unresolved names and attributes, read count fields at their declared width, and admit declared zero-fill registration tails without accepting unmapped bytes.

Cover relocation overlap and adjacency, loader-bound fields, ABI padding, nullable names, and CLI/MCP behavior; document format and verification limits.

Fixes #6881
Fixes #6873
Fixes #6871
2026-10-24 04:42:09 +08:00
morluto 8b3902d377 fix(native): own complete metadata mappings and ambiguity
Resolve Go pointer descriptors and strings across complete, consistent file-backed spans, including PE headers and adjacent ELF load ranges. Reuse the canonical image-mapping selection for native exports. Preserve existing gaps, alias, zero-fill and capacity refusals.

Forward parsed zero-fill ownership through IL2CPP relocation tables, destinations and mapped-span checks. Distinguish missing spans from ambiguous ownership in the shared mapping failure: unresolved relocation targets may remain unknown, while ambiguous raw registration bytes cannot be reused as a resolved count.

Validation: parser, provider, service, native-export, IL2CPP and public CLI/MCP regressions cover PE32/PE32+ headers, split ELF descriptors/contents, relocation count conflicts, ordinary unresolved targets and unchanged inputs. Authored carriers establish static parsing, not Windows loading or actual legacy Go linker emission.

Fixes #6831
Fixes #6830
2026-10-24 04:21:56 +08:00
morluto a32d731ed7 fix(providers): share selected-file error classification 2026-10-24 00:54:28 +08:00
morluto 4c5fae5179 fix(il2cpp): decode valid shared-suffix string offsets
Preserve bounds, termination and UTF-8 checks; verify CLI and stdio MCP preserve names and selected artifact identity.

Fixes #6808
2026-10-24 00:27:57 +08:00
morluto 99d2d7ad22 fix(parsers): retain independent facts and boundary identity
Share bounded ELF section-name decoding across native and note readers; retain read-only ranges and coverage reasons when names are unknown. Preserve ELF symbol-version bytes, dyld-bound method uncertainty, partial gRPC-Web trailers, and per-parent model identity checks. Compare GPU signatures as bytes and require a PTX module header. Share selected-path errno classification across EVM and BEAM.

Validation: 397 shared-parser tests passed (one existing skip), 5 MCP schema tests passed, 14 EVM error-mapping tests passed, and 23 protobuf CLI/MCP matrix cases passed across focused runs. Build, typecheck/lint, docs, formatting, and 2134-file discovery passed. Full EVM provider workflow remains locally unverified on Darwin arm64; format controls are synthetic.

Fixes #6738
Fixes #6737
Fixes #6745
Fixes #6740
Fixes #6749
Fixes #6747
Fixes #6739
2026-10-23 22:18:43 +08:00
morluto 5f702dd6cc fix(parsers): preserve format boundaries and query occurrence identity
Normalize parsed facts at their owning boundaries across PE exports and certificates, ELF section names, GPU bundles, IL2CPP generic types, dyld slice selection, source maps, environment replay, and JavaScript mapped arguments. Preserve partial facts and explicit unsupported cases; clarify the corresponding documentation.

Validation: 831 affected tests passed with one existing skip across 23 files; build, typecheck/lint, documentation, formatting, and 2133-file test discovery passed. Format controls are synthetic; real Unity, GPU, and ARM-device execution is unverified.

Fixes #6709
Fixes #6688
Fixes #6719
Fixes #6718
Fixes #6704
Fixes #6703
Fixes #6692
Fixes #6723
Fixes #6687
Fixes #6726
Fixes #6696
Fixes #6691
Fixes #6727
2026-10-23 22:01:16 +08:00
morluto 2bcd7e6d13 refactor(artifacts): centralize completed file outcomes
Project completed values and cancellation from the descriptor owner once across artifact consumers. Preserve completed void outcomes and format-specific validation and cleanup policies.

Keep later aborts from replacing captured APK and SQLite close failures, and retain the exact APK cancellation reason. Exercise real descriptors, public workflows and cleanup retries.
2026-10-23 21:42:40 +08:00
morluto 8cd10d4727 fix(il2cpp): deduplicate aliased metadata registration
Fixes #6715
2026-10-23 21:28:11 +08:00
morluto f40bd0c4fb fix(il2cpp): deduplicate aliased registration fields
Fixes #6715
2026-10-23 21:28:10 +08:00
morluto bdf13a63c4 fix(il2cpp): track unresolved ELF relocation widths
Fixes #6701
2026-10-23 21:28:10 +08:00
morluto d31e42699f fix(il2cpp): deduplicate consistent ELF registration aliases
Fixes #6715
2026-10-23 21:28:10 +08:00
morluto 139fd52477 fix(il2cpp): reject duplicate method tokens per image
Reject duplicate MethodDef row identities within one owning image before publishing native addresses or Ghidra seeds, while retaining cross-image reuse and folded code addresses.

Fixes #6610
2026-10-23 19:20:53 +08:00
Wade 19d975751f fix(il2cpp): name the metadata file when linking finds malformed metadata (#6425) 2026-10-23 17:52:33 +08:00
morluto 667f73aa54 fix(il2cpp): distinguish rank-one array types
Fixes #6534
2026-10-23 17:15:56 +08:00
morluto 3a42a9e356 fix(artifacts): preserve owned file failure and cancellation facts 2026-10-22 18:01:23 +08:00
Abel YagubyanandAbelo9996 2d91e2d578 fix(il2cpp): refuse a seed path under a non-directory as caller input (#6271)
Co-authored-by: Abelo9996 <Abelo9996@users.noreply.github.com>
2026-10-22 17:48:27 +08:00
morluto fa8b87c470 fix(il2cpp): validate generic-container extents before index widths
Validate the fixed 16-byte version-39 records before using their count to select the serialized index width. Reject contradictory count and byte extents while preserving valid zero, one and 300-record controls.

Validation: 89 focused reader/provider/compiled CLI and stdio MCP tests; check:ci; seven reproduced CLI and SDK-validated MCP cases with unchanged fixture hashes. Version-specific source and independent parser evidence distinguish fixed records from compressed indices. Synthetic metadata only; no real-game or target-execution qualification.

Fixes #5751
2026-10-21 12:55:35 +08:00
morluto c19c2d6723 fix(native): separate container facts from Go metadata admission
Move ELF, PE and Mach-O container parsing into a shared native owner. Go alone selects and validates Go build-info sections, so unrelated malformed Go metadata no longer blocks Rust dependency or IL2CPP inspection. Remove the superseded Go-specific container representation and migrate all consumers. Adapted from draft PR #5510 without asserting human PR readiness.

Validation: 51 compiled CLI/MCP acceptance tests across Rust, Go and IL2CPP; 186 shared-reader tests; full check:ci passed. Three public synthetic-file probes reproduce the baseline Rust refusal and validate the fixed SDK-advertised MCP output, artifact digests and unchanged bytes. The exact zero-address nonallocated ELF case now succeeds for Rust while Go still reports invalid_format. No target execution or real compiler-artifact qualification was performed; no performance improvement is claimed.

Closes #3398
2026-10-21 11:58:15 +08:00