Files
reverse-engineering-anything/src/electron/ElectronFuseFailures.ts
T
morluto a0d9025202 refactor(parsers): report format failures through one ParseFailure algebra (#10593)
* 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): retain malformed range offsets
2026-11-14 14:35:28 -05:00

150 lines
5.3 KiB
TypeScript

import { parseFailureAnalysisError } from "../domain/parseFailureAnalysisError.js";
import { ELECTRON_FUSE_PROVIDER_IDENTITY } from "./ElectronFuseProviderIdentity.js";
import { ArtifactReaderFailure } from "../artifacts/ArtifactReader.js";
import {
ArtifactFileCleanupFailure,
artifactFileCompletion,
artifactFileCancellationCause,
bindArtifactFileCleanup,
} from "../artifacts/ArtifactFileOperation.js";
import { ProviderCleanupError } from "../domain/providerCleanupError.js";
import { analysisErrorWithCleanupFailure } from "../domain/analysisErrorCleanup.js";
import { regularFileCancellation } from "../filesystem/OwnedRegularFile.js";
import { AnalysisError } from "../domain/analysisErrorBase.js";
import {
AnalysisAccessDeniedError,
AnalysisArtifactChangedError,
AnalysisCancelledError,
AnalysisInputError,
AnalysisOutputError,
AnalysisResourceConstraintError,
} from "../domain/analysisErrorCore.js";
import { fixedAllowanceOptions } from "../domain/fixedAllowanceRemediation.js";
import { ProviderAdapterError } from "../domain/providerAdapterError.js";
import { ZodError } from "zod";
import {
RegularFileChangedError,
NonRegularFileReadError,
} from "../filesystem/RegularFile.js";
import { ElectronFusePathFailure } from "./ElectronFusePath.js";
import { ElectronFuseResourceFailure } from "./ElectronFuseReader.js";
const OPERATION = "inspect_electron_fuses";
/** Translate the shared fuse reader without replacing its producing outcome or cleanup owner. */
export const electronFuseFailure = (
cause: unknown,
path: string,
operation = OPERATION,
): AnalysisError => {
if (cause instanceof AnalysisError) return cause;
if (cause instanceof ArtifactReaderFailure && cause.cleanup !== undefined) {
const cleanup = new ProviderCleanupError(
ELECTRON_FUSE_PROVIDER_IDENTITY.id,
cause.cleanup.resources,
{ reason: cause.cleanup.reason },
{ operation, cause },
);
bindArtifactFileCleanup(cause, cleanup);
if (cause instanceof ArtifactFileCleanupFailure) {
const outcome = cause.fileCleanupFailure.outcome;
const cancellation = artifactFileCompletion(cause)?.cancellation;
const primary =
outcome.kind === "failed"
? electronFuseFailure(outcome.cause, path, operation)
: cancellation === undefined
? undefined
: new AnalysisCancelledError(operation, {
cause: cancellation.reason,
});
if (primary !== undefined)
return analysisErrorWithCleanupFailure(
primary,
cleanup,
operation,
).bindCleanupDependencies([primary, cleanup]);
}
return cleanup;
}
if (cause instanceof ArtifactReaderFailure && cause.reason === "cancelled")
return new AnalysisCancelledError(operation, {
cause: artifactFileCancellationCause(cause),
});
const cancellation = regularFileCancellation(cause);
if (cancellation !== undefined)
return new AnalysisCancelledError(operation, {
cause: cancellation.reason,
});
if (cause instanceof ElectronFusePathFailure)
return new AnalysisInputError(operation, { cause }, [
{ path: ["path"], reason: cause.reason, message: cause.message },
]);
if (cause instanceof ElectronFuseResourceFailure)
return new AnalysisResourceConstraintError(
operation,
cause.boundary === "file-size" ? "file-size" : "capacity",
cause.message,
cause.boundary === "file-size"
? { maximum_input_bytes: 1024 * 1024 * 1024 }
: { maximum_sentinels_per_slice: 32 },
{
cause,
...fixedAllowanceOptions(
cause.boundary === "file-size"
? "the 1 GiB Electron fuse input allowance"
: "The Electron fuse sentinel inventory",
cause.boundary === "file-size" ? "input" : "count",
),
},
);
const formatFailure = parseFailureAnalysisError(operation, path, cause);
if (formatFailure !== undefined) return formatFailure;
if (cause instanceof RegularFileChangedError)
return new AnalysisArtifactChangedError(operation, path, cause.message, {
cause,
});
if (cause instanceof NonRegularFileReadError)
return new AnalysisInputError(operation, { cause }, [
{
path: ["path"],
reason: "invalid_format",
message: cause.message,
},
]);
if (cause instanceof ZodError)
return new AnalysisOutputError(
operation,
"Electron fuse reader produced a report outside its schema.",
{ cause },
);
if (cause instanceof Error && "code" in cause) {
if (cause.code === "EACCES" || cause.code === "EPERM")
return new AnalysisAccessDeniedError(operation, path, cause.code, {
cause,
});
if (
["ENOENT", "ENOTDIR", "ELOOP", "ENAMETOOLONG"].includes(
String(cause.code),
)
)
return new AnalysisInputError(operation, { cause }, [
{
path: ["path"],
reason: "invalid_value",
message: `Selected artifact could not be read (${String(cause.code)}): ${path}.`,
},
]);
}
return new ProviderAdapterError(
ELECTRON_FUSE_PROVIDER_IDENTITY.id,
operation,
{
cause,
diagnostics: {
path,
reason: cause instanceof Error ? cause.message : String(cause),
},
},
);
};