fix(verifiers): propagate session assertion failures synchronously

Remove the redundant async declaration from the Ghidra session assertion helper so its existing callers receive assertion failures within their synchronous error boundary. Keep call order unchanged.

Validation: a public-helper Node subprocess accepts authored valid handshake facts and rejects incomplete analysis and a target-digest mismatch. The regression failed for the original async declaration with Missing expected exception, then passed with the fix. No installed Ghidra execution was performed.
This commit is contained in:
morluto committed 2026-10-25 07:56:26 +08:00
1 parent 475f09d5ca
commit ed86f9c3bb
2 files changed
+69 -5

No files matched your search

+1 -5
View File
@@ -245,11 +245,7 @@ export function dossierSummary(dossier) {
};
}
export async function assertSession(
session,
expectedDigest,
expectedTargetSha256,
) {
export function assertSession(session, expectedDigest, expectedTargetSha256) {
if (
session.provider.id !== "ghidra" ||
session.provider.version !== SUPPORTED_GHIDRA_VERSION ||
@@ -0,0 +1,68 @@
import { expect } from "vitest";
import { processTest } from "../../support/process/processFixture.js";
processTest(
"Ghidra verifier session assertions fail within the caller's synchronous error boundary",
async ({ processes }) => {
const assertionsUrl = new URL(
"../../../scripts/verify-real-ghidra-assertions.mjs",
import.meta.url,
).href;
const valuesUrl = new URL(
"../../../dist/ghidra/GhidraSessionValues.js",
import.meta.url,
).href;
const policyUrl = new URL(
"../../../dist/ghidra/GhidraReleasePolicy.js",
import.meta.url,
).href;
// Authored handshake facts exercise the verifier, not a running provider.
const source = `
import assert from "node:assert/strict";
import { assertSession } from ${JSON.stringify(assertionsUrl)};
import { GHIDRA_SESSION_CAPABILITIES } from ${JSON.stringify(valuesUrl)};
import { SUPPORTED_GHIDRA_VERSION } from ${JSON.stringify(policyUrl)};
const profileDigest = "a".repeat(64);
const targetSha256 = "b".repeat(64);
const session = {
name: "REA Ghidra bridge",
run_id: "d6fcbb66-e829-4ff6-a535-0035aec63139",
profile_digest: profileDigest,
provider: { id: "ghidra", version: SUPPORTED_GHIDRA_VERSION },
read_only: false,
analysis_complete: true,
analysis_timed_out: false,
capabilities: [...GHIDRA_SESSION_CAPABILITIES],
target: {
name: "fixture.bin",
language_id: "x86:LE:64:default",
compiler_spec_id: "gcc",
image_base: "0x401000",
default_address_space: "ram",
sha256: targetSha256,
},
};
assert.doesNotThrow(() => assertSession(session, profileDigest, targetSha256));
assert.throws(
() => assertSession(
{ ...session, analysis_complete: false }, profileDigest, targetSha256,
),
/Ghidra session commitment drifted/,
);
assert.throws(
() => assertSession(session, profileDigest, "c".repeat(64)),
/Ghidra session commitment drifted/,
);
`;
const result = await processes.run(
process.execPath,
["--input-type=module", "--eval", source],
{ timeoutMs: 10_000 },
);
expect(result.signal, result.stderr).toBeNull();
expect(result.exitCode, result.stderr).toBe(0);
},
);