fix(native): coalesce Objective-C class imports by binding identity

Join provider class observations only when selected-image identity and exact import bindings establish equivalence. Preserve distinct observations and unsupported coverage.

Refs #5607
This commit is contained in:
morluto committed 2026-10-21 06:12:21 +08:00
1 parent b231c28cf6
commit 4d7de00d4c
24 files changed
+2287 -100

No files matched your search

@@ -21,10 +21,22 @@ export const inspectNativeDispatch = async (
analysis: AnalysisOperationPort,
maxRecords: number,
signal?: AbortSignal,
objcClassImportAddresses?: readonly string[],
objcClassImportAddressesComplete?: boolean,
): EnhancedResult => {
const input = {
max_records: maxRecords,
...(objcClassImportAddresses === undefined
? {}
: {
objc_class_import_addresses: [...objcClassImportAddresses],
objc_class_import_addresses_complete:
objcClassImportAddressesComplete ?? true,
}),
};
const binaryMetadata = await analysis.execute(
NATIVE_DISPATCH_METADATA_SOURCES.binary,
{ max_records: maxRecords },
input,
signal === undefined ? {} : { signal },
);
if (binaryMetadata.ok)
@@ -59,20 +71,32 @@ export const inspectNativeDispatch = async (
"provider returned an invalid inventory",
),
);
const result = inspectNativeDispatchMetadata(
names.data.map((entry) => ({
address: entry.address,
name: "value" in entry ? entry.value : entry.name,
})),
maxRecords,
);
if (objcClassImportAddresses !== undefined) {
result.objc_class_import_bindings = [];
result.objc_class_import_binding_coverage = {
facet: "objc_class_import_bindings",
status: "unsupported",
reason: "Native Mach-O pointer binding inspection is unavailable.",
examined: 0,
decoded: 0,
};
}
return ok(
jsonValueSchema.parse(
nativeDispatchMetadataResultSchema.parse({
target_sha256: execution.value.subject?.sha256 ?? null,
target_architecture: execution.value.subject?.architecture ?? null,
provider: execution.value.provider,
analysis_profile_digest:
execution.value.analysisProfile?.digest ?? null,
result: inspectNativeDispatchMetadata(
names.data.map((entry) => ({
address: entry.address,
name: "value" in entry ? entry.value : entry.name,
})),
maxRecords,
),
result,
}),
),
);