mirror of
https://github.com/morluto/rea.git
synced 2026-11-05 22:36:08 +00:00
fix(native)!: preserve value-flow absence semantics (#8785)
* fix(native)!: preserve value-flow absence semantics * test(native): compare value-flow reasons with their owners Stop freezing the unrecorded and Kuna unavailable sentences. Assert the procedure-scoped unknown and that an explicit provider reason is preserved. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This commit is contained in:
1 parent
dd4b83c220
commit
1ff5a655bc
8 files changed
+81
-8
No files matched your search
@@ -466,8 +466,10 @@ resources it owns stops the trace: the result is that provider's own
|
||||
`cleanup_incomplete` failure with its resources and any bound cleanup retry, and the work
|
||||
admitted before the stop is retained as partial Evidence with a located unknown
|
||||
at the stopping read. A successful seed without a native def-use
|
||||
model still returns its procedure and an explicit coverage unknown. A new trace
|
||||
can retry failed selectors.
|
||||
model still returns its procedure and an explicit coverage unknown. An unrecorded
|
||||
facet stays unknown; when the provider explicitly reports unavailability, the trace
|
||||
retains its reason. REA's Kuna provider explicitly reports that it does not supply
|
||||
native def-use observations. A new trace can retry failed selectors.
|
||||
|
||||
Paging and traversal completeness are separate facts. `page_truncated` means the
|
||||
page omits retained nodes, and the edges they source, before `offset` or after
|
||||
|
||||
@@ -13,6 +13,9 @@ export const workflowAnalysisProfile = (
|
||||
createAnalysisProfile(REA_WORKFLOW_PROVIDER, {
|
||||
upstream_analysis_profile: upstream,
|
||||
source_limitations: "provider-operation-caveats-v1",
|
||||
...(operation === "trace_native_values"
|
||||
? { value_flow_absence: "recorded-versus-unavailable-v1" }
|
||||
: {}),
|
||||
...(operation === "binary_overview"
|
||||
? { workflow_revision: 5 }
|
||||
: operation === "batch_decompile"
|
||||
|
||||
@@ -1357,3 +1357,15 @@ it("revises the trace_feature workflow profile so earlier results are not replay
|
||||
"other workflows keep their profile",
|
||||
).toEqual(workflowAnalysisProfile(profile));
|
||||
});
|
||||
|
||||
it("binds native value-trace absence semantics without changing other workflows", () => {
|
||||
const profile = ANALYSIS_SNAPSHOT_PROFILE;
|
||||
const valueTrace = workflowAnalysisProfile(profile, "trace_native_values");
|
||||
expect(valueTrace.parameters.value_flow_absence).toBe(
|
||||
"recorded-versus-unavailable-v1",
|
||||
);
|
||||
expect(valueTrace.digest).not.toBe(workflowAnalysisProfile(profile).digest);
|
||||
expect(workflowAnalysisProfile(profile, "trace_call_path")).toEqual(
|
||||
workflowAnalysisProfile(profile),
|
||||
);
|
||||
});
|
||||
@@ -1,6 +1,9 @@
|
||||
import { createAnalysisExecutionEvidence } from "../../domain/analysisObservation.js";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { traceNativeValues as traceNativeValuesCore } from "./NativeValueTrace.js";
|
||||
import {
|
||||
traceNativeValues as traceNativeValuesCore,
|
||||
UNRECORDED_NATIVE_VALUE_FLOW,
|
||||
} from "./NativeValueTrace.js";
|
||||
import { executeComposedWorkflow } from "../WorkflowEvidence.js";
|
||||
import {
|
||||
createAnalysisExecution,
|
||||
@@ -190,12 +193,47 @@ describe("native value trace seed admission", () => {
|
||||
expect.objectContaining({ address: base.procedure.address }),
|
||||
],
|
||||
unknowns: [
|
||||
expect.objectContaining({
|
||||
reason: "Provider has no native def-use model",
|
||||
}),
|
||||
{
|
||||
procedure: base.procedure.address,
|
||||
address: null,
|
||||
reason: UNRECORDED_NATIVE_VALUE_FLOW,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("preserves an explicit unavailable reason for that procedure", async () => {
|
||||
const base = functionDossierSchema.parse(ghidraFunctionDossier());
|
||||
const providerReason = "selected procedure has no p-code model";
|
||||
const result = await traceNativeValues(
|
||||
{
|
||||
execute: async () =>
|
||||
ok(
|
||||
createAnalysisExecution(
|
||||
{
|
||||
...base,
|
||||
native_value_flow: {
|
||||
available: false,
|
||||
reason: providerReason,
|
||||
limitations: [],
|
||||
},
|
||||
},
|
||||
provider,
|
||||
{ subject },
|
||||
),
|
||||
),
|
||||
},
|
||||
{ procedure: base.procedure.address },
|
||||
);
|
||||
if (!result.ok) throw result.error;
|
||||
expect(nativeValueTraceSchema.parse(result.value).unknowns).toEqual([
|
||||
{
|
||||
procedure: base.procedure.address,
|
||||
address: null,
|
||||
reason: providerReason,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("native value parameter-use node membership", () => {
|
||||
|
||||
@@ -28,6 +28,10 @@ import { createValueTraceBudget } from "./NativeValueTraceBudget.js";
|
||||
export const CLEANUP_STOPPED_VALUE_TRACE =
|
||||
"Trace stopped because the provider did not confirm cleanup of resources it owns";
|
||||
|
||||
/** Fallback when a dossier has no native value-flow facet for this procedure. */
|
||||
export const UNRECORDED_NATIVE_VALUE_FLOW =
|
||||
"Native def-use was not recorded for this procedure.";
|
||||
|
||||
/** Compose bounded high-p-code def-use graphs across exactly referenced call destinations. */
|
||||
export const traceNativeValues = async (
|
||||
analysis: AnalysisOperationPort,
|
||||
@@ -181,7 +185,7 @@ export const traceNativeValues = async (
|
||||
unknowns.push({
|
||||
procedure: address,
|
||||
address: null,
|
||||
reason: flow?.reason ?? "Provider has no native def-use model",
|
||||
reason: flow?.reason ?? UNRECORDED_NATIVE_VALUE_FLOW,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -281,6 +281,7 @@ export class KunaProvider implements AnalysisProviderCandidate {
|
||||
termination: "any",
|
||||
xrefs: false,
|
||||
},
|
||||
value_flow: "explicitly-unavailable-v1",
|
||||
cache_policy: "live",
|
||||
},
|
||||
),
|
||||
|
||||
@@ -298,6 +298,10 @@ const kunaVerificationLimitations = (
|
||||
/** Kuna names a procedure by its inventory entry or by an exact entry address. */
|
||||
const procedureSelectorSchema = z.string().min(1);
|
||||
|
||||
/** REA's Kuna integration does not supply a def-use model for any procedure. */
|
||||
export const KUNA_NATIVE_VALUE_FLOW_UNAVAILABLE =
|
||||
"REA's Kuna provider does not report native def-use observations.";
|
||||
|
||||
/**
|
||||
* One Kuna analysis session for one target.
|
||||
*
|
||||
@@ -1523,7 +1527,11 @@ export class KunaSessionClient implements AnalysisClient {
|
||||
referenced_names: [],
|
||||
basic_blocks: [],
|
||||
native_api: null,
|
||||
native_value_flow: null,
|
||||
native_value_flow: {
|
||||
available: false,
|
||||
reason: KUNA_NATIVE_VALUE_FLOW_UNAVAILABLE,
|
||||
limitations: [],
|
||||
},
|
||||
facet_availability: {
|
||||
pseudocode:
|
||||
text === null
|
||||
|
||||
@@ -20,6 +20,7 @@ import { OwnedFileHandle } from "../../../../src/filesystem/OwnedFileHandle.js";
|
||||
import { AnalysisProviderRegistry } from "../../../../src/application/binary/AnalysisProviderRegistry.js";
|
||||
import { composeBinarySession } from "../../../../src/application/binary/BinarySessionComposition.js";
|
||||
import { projectAnalysisError } from "../../../../src/domain/analysisErrorProjection.js";
|
||||
import { KUNA_NATIVE_VALUE_FLOW_UNAVAILABLE } from "../../../../src/kuna/KunaSessionClient.js";
|
||||
import { KunaProvider } from "../../../../src/kuna/KunaProvider.js";
|
||||
import { KUNA_FUNCTION_TEXT_BYTES } from "../../../../src/kuna/KunaLimits.js";
|
||||
import { KunaProjectCache } from "../../../../src/kuna/KunaProjectCache.js";
|
||||
@@ -509,6 +510,10 @@ it("builds a dossier with text and call relationships, leaving unsupported facet
|
||||
},
|
||||
pseudocode: "int main(void)\n{\n return 0;\n}",
|
||||
assembly: ["main: ; 0x1000", " 00001000: c3 RET"],
|
||||
native_value_flow: {
|
||||
available: false,
|
||||
reason: KUNA_NATIVE_VALUE_FLOW_UNAVAILABLE,
|
||||
},
|
||||
facet_availability: {
|
||||
pseudocode: { available: true },
|
||||
assembly: { available: true },
|
||||
|
||||
Reference in new issue
Block a user