mirror of
https://github.com/morluto/rea.git
synced 2026-11-13 18:22:42 +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
@@ -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