diff --git a/src/application/binaryDiagnostics/PeCertificatesService.ts b/src/application/binaryDiagnostics/PeCertificatesService.ts index 2a37994e4c..d39c80afca 100644 --- a/src/application/binaryDiagnostics/PeCertificatesService.ts +++ b/src/application/binaryDiagnostics/PeCertificatesService.ts @@ -14,11 +14,7 @@ import { type PeCertificates, } from "../../domain/native/peCertificates.js"; import { analysisInputErrorFromIssues } from "../../domain/inputIssueProjection.js"; -import { - decodePeMachine, - peOptionalHeaderMagic, - type PeArchitecture, -} from "../../domain/peMachine.js"; +import { peSubjectArchitecture } from "../../domain/peMachine.js"; import { err, ok, type Result } from "../../domain/result.js"; import { completeProviderEvidence } from "../ProviderOperationExecution.js"; @@ -76,7 +72,7 @@ export class PeCertificatesService { ), ); const value = report.data; - const architecture = subjectArchitecture(value); + const architecture = peSubjectArchitecture(value.machine, value.format); const locations = [ { kind: "artifact-path" as const, path: value.artifact.path }, ...(value.table === null @@ -112,17 +108,6 @@ export class PeCertificatesService { } } -const subjectArchitecture = ( - report: PeCertificates, -): PeArchitecture | undefined => { - const machine = decodePeMachine(report.machine); - if (machine === undefined || machine.nativeOsOverride) return undefined; - const magic = report.format === "pe32-plus" ? 0x20b : 0x10b; - return magic === peOptionalHeaderMagic(machine.architecture) - ? machine.architecture - : undefined; -}; - const validReport = ( report: PeCertificates, maxEntries: number, diff --git a/src/application/binaryDiagnostics/PeImportsService.ts b/src/application/binaryDiagnostics/PeImportsService.ts index eaad73f967..2a485334e3 100644 --- a/src/application/binaryDiagnostics/PeImportsService.ts +++ b/src/application/binaryDiagnostics/PeImportsService.ts @@ -14,11 +14,7 @@ import { type PeImports, } from "../../domain/native/peImports.js"; import { analysisInputErrorFromIssues } from "../../domain/inputIssueProjection.js"; -import { - decodePeMachine, - peOptionalHeaderMagic, - type PeArchitecture, -} from "../../domain/peMachine.js"; +import { peSubjectArchitecture } from "../../domain/peMachine.js"; import { err, type Result } from "../../domain/result.js"; import { completeProviderEvidence } from "../ProviderOperationExecution.js"; @@ -72,7 +68,7 @@ export class PeImportsService { ), ); const value = report.data; - const architecture = subjectArchitecture(value); + const architecture = peSubjectArchitecture(value.machine, value.format); const locations = [ { kind: "artifact-path" as const, path: value.artifact.path }, ...fileRange(value.import_directory), @@ -101,15 +97,6 @@ export class PeImportsService { } } -const subjectArchitecture = (report: PeImports): PeArchitecture | undefined => { - const machine = decodePeMachine(report.machine); - if (machine === undefined || machine.nativeOsOverride) return undefined; - const magic = report.format === "pe32-plus" ? 0x20b : 0x10b; - return magic === peOptionalHeaderMagic(machine.architecture) - ? machine.architecture - : undefined; -}; - const fileRange = ( directory: PeImports["import_directory"], ): readonly { diff --git a/src/application/binaryDiagnostics/PeLoadConfigService.ts b/src/application/binaryDiagnostics/PeLoadConfigService.ts index 30e19f688a..7137a35d59 100644 --- a/src/application/binaryDiagnostics/PeLoadConfigService.ts +++ b/src/application/binaryDiagnostics/PeLoadConfigService.ts @@ -14,11 +14,7 @@ import { type PeLoadConfig, } from "../../domain/native/peLoadConfig.js"; import { analysisInputErrorFromIssues } from "../../domain/inputIssueProjection.js"; -import { - decodePeMachine, - peOptionalHeaderMagic, - type PeArchitecture, -} from "../../domain/peMachine.js"; +import { peSubjectArchitecture } from "../../domain/peMachine.js"; import { err, type Result } from "../../domain/result.js"; import { completeProviderEvidence } from "../ProviderOperationExecution.js"; @@ -72,7 +68,7 @@ export class PeLoadConfigService { ), ); const value = report.data; - const architecture = subjectArchitecture(value); + const architecture = peSubjectArchitecture(value.machine, value.format); const locations = [ { kind: "artifact-path" as const, path: value.artifact.path }, ...fileRange(value.tls?.directory ?? null), @@ -109,17 +105,6 @@ export class PeLoadConfigService { } } -const subjectArchitecture = ( - report: PeLoadConfig, -): PeArchitecture | undefined => { - const machine = decodePeMachine(report.machine); - if (machine === undefined || machine.nativeOsOverride) return undefined; - const magic = report.format === "pe32-plus" ? 0x20b : 0x10b; - return magic === peOptionalHeaderMagic(machine.architecture) - ? machine.architecture - : undefined; -}; - const fileRange = ( directory: { file_offset: number; size: number } | null, ): { kind: "file-offset-range"; start: number; end: number }[] => diff --git a/src/application/binaryDiagnostics/PeResourcesService.ts b/src/application/binaryDiagnostics/PeResourcesService.ts index b297e80e03..c3f45e05b9 100644 --- a/src/application/binaryDiagnostics/PeResourcesService.ts +++ b/src/application/binaryDiagnostics/PeResourcesService.ts @@ -13,11 +13,7 @@ import { type PeResourceIdentity, } from "../../domain/native/peResources.js"; import { analysisInputErrorFromIssues } from "../../domain/inputIssueProjection.js"; -import { - decodePeMachine, - peOptionalHeaderMagic, - type PeArchitecture, -} from "../../domain/peMachine.js"; +import { peSubjectArchitecture } from "../../domain/peMachine.js"; import { err, ok, type Result } from "../../domain/result.js"; import { completeProviderEvidence } from "../ProviderOperationExecution.js"; @@ -64,7 +60,7 @@ export class PeResourcesService { ), ); const value = report.data; - const architecture = subjectArchitecture(value); + const architecture = peSubjectArchitecture(value.machine, value.format); return completeProviderEvidence( createEvidence( { @@ -88,23 +84,6 @@ export class PeResourcesService { } } -/** - * Name the subject architecture from the reported COFF machine. The resource - * reader does not inspect the CLI header, so a ReadyToRun OS-override machine - * needs separate proof. An optional-header magic that contradicts the machine - * is observed conflicting evidence. Both stay unknown. - */ -const subjectArchitecture = ( - report: PeResources, -): PeArchitecture | undefined => { - const machine = decodePeMachine(report.machine); - if (machine === undefined || machine.nativeOsOverride) return undefined; - const magic = report.format === "pe32-plus" ? 0x20b : 0x10b; - return magic === peOptionalHeaderMagic(machine.architecture) - ? machine.architecture - : undefined; -}; - /** Check cross-field invariants before provider output becomes public Evidence. */ const validReport = ( report: PeResources, diff --git a/src/domain/peMachine.ts b/src/domain/peMachine.ts index eafaf904fd..a08432d2f5 100644 --- a/src/domain/peMachine.ts +++ b/src/domain/peMachine.ts @@ -56,6 +56,23 @@ export const decodePeMachine = (machine: number): PeMachine | undefined => { return undefined; }; +/** + * Name a subject only when a direct COFF machine agrees with its declared PE + * format. OS overrides need managed-header proof that these report facts lack; + * unknown machines and conflicting optional-header widths also stay unknown. + */ +export const peSubjectArchitecture = ( + machineType: number, + format: "pe32" | "pe32-plus", +): PeArchitecture | undefined => { + const machine = decodePeMachine(machineType); + if (machine === undefined || machine.nativeOsOverride) return undefined; + const magic = format === "pe32-plus" ? 0x20b : 0x10b; + return magic === peOptionalHeaderMagic(machine.architecture) + ? machine.architecture + : undefined; +}; + /** Optional-header facts shared by admission and native metadata readers. */ export interface PeOptionalHeaderFacts { readonly bits: 32 | 64; diff --git a/src/native/exports/NativeExportParser.ts b/src/native/exports/NativeExportParser.ts index bd42733960..dfe49d776b 100644 --- a/src/native/exports/NativeExportParser.ts +++ b/src/native/exports/NativeExportParser.ts @@ -10,7 +10,7 @@ import { architectureForElfMachine } from "../metadata/ElfImage.js"; import { isUtf8 } from "node:buffer"; import { readElfStringBytes, readElfSymbol } from "../metadata/ElfSymbol.js"; import { - readNativeDirectoryFromBuffer, + readElfDirectoryFromBuffer, type NativeSection, } from "../metadata/NativeSectionDirectory.js"; import { readPeImage } from "../metadata/PeImage.js"; @@ -449,7 +449,7 @@ const readVersionNames = ( /** Read defined exported entries of `.dynsym` with their symbol versions. */ const parseElfExports = (bytes: Buffer, artifact: Artifact): NativeExports => { - const directory = readNativeDirectoryFromBuffer(bytes, "elf"); + const directory = readElfDirectoryFromBuffer(bytes); const reader = new BinaryReader(bytes, directory.little); const result = { artifact, diff --git a/src/native/metadata/ElfImage.ts b/src/native/metadata/ElfImage.ts index 0b56fe291d..82e1209479 100644 --- a/src/native/metadata/ElfImage.ts +++ b/src/native/metadata/ElfImage.ts @@ -10,11 +10,11 @@ import { type ZeroFillMapping, } from "./BinaryContainer.js"; import { elfArchitecture } from "../../domain/elfFixedHeader.js"; -import { readNativeDirectoryFromBuffer } from "./NativeSectionDirectory.js"; +import { readElfDirectoryFromBuffer } from "./NativeSectionDirectory.js"; /** Read ELF sections and file-backed program mappings without interpreting language metadata. */ export const readElfImage = (bytes: Buffer): BinaryContainer => { - const directory = readNativeDirectoryFromBuffer(bytes, "elf"); + const directory = readElfDirectoryFromBuffer(bytes); const { bits } = directory; const reader = new BinaryReader(bytes, directory.little); const mappings: FileMapping[] = []; diff --git a/src/native/metadata/NativeSectionDirectory.ts b/src/native/metadata/NativeSectionDirectory.ts index 1bae3fba3a..6bff184571 100644 --- a/src/native/metadata/NativeSectionDirectory.ts +++ b/src/native/metadata/NativeSectionDirectory.ts @@ -343,15 +343,11 @@ export function* readPeSectionDirectory( }; } -/** Synchronous driver borrows bytes; file drivers satisfy the identical requests without loading payloads. */ -export const readNativeDirectoryFromBuffer = ( +/** Borrow ELF bytes; file drivers satisfy the identical requests without loading payloads. */ +export const readElfDirectoryFromBuffer = ( bytes: Buffer, - format: "elf" | "pe", ): NativeSectionDirectory => { - const steps = - format === "elf" - ? readElfSectionDirectory(bytes.length) - : readPeSectionDirectory(bytes.length); + const steps = readElfSectionDirectory(bytes.length); let next = steps.next(); while (!next.done) { const { offset, size } = next.value;