Files
reverse-engineering-anything/src/native/pe/PeLoadConfigProvider.ts
T
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

116 lines
3.9 KiB
TypeScript

import { projectPeBinaryFailure } from "./PeBinaryFailure.js";
import {
projectArtifactCloseFailure,
imageFileSizeRemediation,
} from "../../artifacts/StableArtifactFailure.js";
import {
type StableArtifactSnapshot,
readStableArtifact,
} from "../../artifacts/readStableArtifact.js";
import { assertArtifactReadActive } from "../../artifacts/ArtifactFileOperation.js";
import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js";
import type { PeLoadConfigPort } from "../../application/binaryDiagnostics/PeLoadConfigPort.js";
import type { ExecutionOptions } from "../../application/AnalysisProvider.js";
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
import type { ResourceConstraintRecovery } from "../../domain/analysisErrorCore.js";
import { fixedAllowanceOptions } from "../../domain/fixedAllowanceRemediation.js";
import {
MAX_INSPECT_PE_LOAD_CONFIG_FILE_BYTES,
MAX_INSPECT_PE_LOAD_CONFIG_CALLBACKS,
type InspectPeLoadConfigInput,
} from "../../domain/native/peLoadConfig.js";
import { err, ok } from "../../domain/result.js";
import { PE_LOAD_CONFIG_PROVIDER } from "../../domain/investigationProviders.js";
import {
parsePeLoadConfig,
PeLoadConfigLimitFailure,
type PeLoadConfigLimit,
} from "./PeLoadConfigParser.js";
const OPERATION = "inspect_pe_load_config";
/** Portable TLS/load-config reader over one bounded, identity-checked regular file. */
export class PeLoadConfigProvider implements PeLoadConfigPort {
readonly identity = PE_LOAD_CONFIG_PROVIDER;
readonly #resources = new ArtifactResourceScope();
async close(): Promise<void> {
try {
await this.#resources.close();
} catch (cause: unknown) {
throw projectArtifactCloseFailure(
cause,
PE_LOAD_CONFIG_PROVIDER.id,
OPERATION,
);
}
}
async inspect(input: InspectPeLoadConfigInput, options?: ExecutionOptions) {
let snapshot: StableArtifactSnapshot | undefined;
try {
return await this.#resources.run(async () => {
snapshot = await readStableArtifact(
input.path,
input.max_file_bytes,
options?.signal,
undefined,
this.#resources,
);
assertArtifactReadActive(options?.signal);
const report = await parsePeLoadConfig(
snapshot.bytes,
{
path: input.path,
sha256: snapshot.sha256,
bytes: snapshot.bytes.length,
},
input,
options?.signal,
);
assertArtifactReadActive(options?.signal);
return ok(report);
});
} catch (cause) {
return err(peLoadConfigFailure(cause, input, snapshot));
}
}
}
const limitRecovery = (
limit: PeLoadConfigLimit | null,
input: InspectPeLoadConfigInput,
): ResourceConstraintRecovery =>
limit === "callbacks"
? {
retryable: false,
remediationAction:
input.max_callbacks >= MAX_INSPECT_PE_LOAD_CONFIG_CALLBACKS
? `The image exceeds the ${String(MAX_INSPECT_PE_LOAD_CONFIG_CALLBACKS)}-callback ceiling; select a smaller artifact.`
: `Raise max_callbacks above ${String(input.max_callbacks)} or select a smaller artifact.`,
}
: fixedAllowanceOptions("The PE structural decoding allowance", "parser");
const peLoadConfigFailure = (
cause: unknown,
input: InspectPeLoadConfigInput,
snapshot?: StableArtifactSnapshot,
): AnalysisError =>
projectPeBinaryFailure<PeLoadConfigLimit>(
cause,
input,
{
operation: OPERATION,
providerId: PE_LOAD_CONFIG_PROVIDER.id,
fileSizeRemediation: () =>
imageFileSizeRemediation(
input.max_file_bytes,
MAX_INSPECT_PE_LOAD_CONFIG_FILE_BYTES,
),
limit: (failure) =>
failure instanceof PeLoadConfigLimitFailure ? failure.limit : null,
limitRecovery: (limit) => limitRecovery(limit, input),
},
snapshot,
);