mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
fix(hopper): preserve unknown relationship completeness
This commit is contained in:
1 parent
ecfac46c8d
commit
23664efdbb
3 files changed
+74
-3
No files matched your search
@@ -219,7 +219,12 @@ Function dossiers and `trace_feature` string matches retain this same string
|
||||
evidence, including decoding uncertainty; procedure matches keep their own
|
||||
named observation fields without invented string qualifications. Native call edges retain
|
||||
Hopper's partial `CallReference` classification and exact endpoints; detailed
|
||||
reference flags remain unavailable rather than being invented.
|
||||
reference flags remain unavailable rather than being invented. Caller and callee
|
||||
procedure inventories come from independent Hopper APIs; REA retains observed
|
||||
relationships but reports their completeness as unknown. In particular, a resolved
|
||||
tail call observed in one direction does not prove that the reverse inventory is
|
||||
complete. An empty Hopper inventory cannot establish that no such call exists.
|
||||
No whole-binary reverse scan is performed.
|
||||
Regex searches use ECMAScript Unicode syntax in a cancellable worker with a
|
||||
matching deadline and a worker old-generation heap. Deadline or cancellation
|
||||
stops matching while leaving the Hopper API available. The deadline is
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { parseConfig } from "../config/parseConfig.js";
|
||||
import { silentLogger } from "../logger.js";
|
||||
import { ok } from "../domain/result.js";
|
||||
import { HopperClient } from "./HopperClient.js";
|
||||
import { HopperProvider } from "./HopperProvider.js";
|
||||
|
||||
describe("Hopper provider capabilities", () => {
|
||||
@@ -86,3 +88,55 @@ describe("Hopper provider capabilities", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Hopper relationship coverage", () => {
|
||||
it.each([
|
||||
["procedure_callers", ["callers"]],
|
||||
["procedure_callees", ["callees"]],
|
||||
["analyze_function", ["callers", "callees"]],
|
||||
] as const)(
|
||||
"retains %s observations without claiming exhaustive relationships",
|
||||
async (operation, directions) => {
|
||||
const config = parseConfig({});
|
||||
if (!config.ok) throw config.error;
|
||||
const source =
|
||||
operation === "analyze_function"
|
||||
? {
|
||||
callers: [],
|
||||
callees: [{ address: "0x2000", name: "tail_target" }],
|
||||
}
|
||||
: operation === "procedure_callees"
|
||||
? ["0x2000"]
|
||||
: [];
|
||||
const callTool = vi
|
||||
.spyOn(HopperClient.prototype, "callTool")
|
||||
.mockResolvedValue(ok(source));
|
||||
const client = new HopperProvider(
|
||||
config.value,
|
||||
silentLogger,
|
||||
{},
|
||||
"linux",
|
||||
).createClient({
|
||||
path: "/tmp/fixture.hop",
|
||||
sha256: "a".repeat(64),
|
||||
kind: "database",
|
||||
format: "analysis-database",
|
||||
});
|
||||
try {
|
||||
const observed = await client.execute(operation, {
|
||||
procedure: "0x1000",
|
||||
});
|
||||
if (!observed.ok) throw observed.error;
|
||||
expect(observed.value.result).toEqual(source);
|
||||
expect(observed.value.relationshipCoverage).toMatchObject({
|
||||
status: "unknown",
|
||||
limited_directions: directions,
|
||||
reason: expect.stringContaining("resolved tail calls"),
|
||||
});
|
||||
} finally {
|
||||
await client.close();
|
||||
callTool.mockRestore();
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
@@ -347,7 +347,19 @@ export class HopperProvider implements AnalysisProviderCandidate {
|
||||
...(operation === "procedure_callers" ||
|
||||
operation === "procedure_callees" ||
|
||||
operation === "analyze_function"
|
||||
? { relationshipCoverage: { status: "complete" as const } }
|
||||
? {
|
||||
relationshipCoverage: {
|
||||
status: "unknown" as const,
|
||||
limited_directions:
|
||||
operation === "procedure_callers"
|
||||
? (["callers"] as const)
|
||||
: operation === "procedure_callees"
|
||||
? (["callees"] as const)
|
||||
: (["callers", "callees"] as const),
|
||||
reason:
|
||||
"Hopper reports caller and callee procedures through independent public API inventories. Their completeness, including resolved tail calls and agreement between reverse and forward relationships, has not been established. Observed relationships are retained.",
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
limitations: [
|
||||
...(target.kind !== "executable"
|
||||
|
||||
Reference in new issue
Block a user