mirror of
https://github.com/morluto/rea.git
synced 2026-11-07 05:56:19 -10:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb35b085d5 | ||
|
|
87c67a5e0c | ||
|
|
4d3ff6e673 |
No files matched your search
@@ -227,7 +227,7 @@ export const BINARY_DIAGNOSTICS_TOOL_CONTRACTS = [
|
||||
...toolContractMetadata("inspect_native_exports"),
|
||||
kind: "native-provider",
|
||||
description:
|
||||
"Inspect one explicit local PE or ELF image's export table without executing it or opening an engine: PE export-directory names, ordinals, addresses and forwarders, or ELF defined default/protected global, weak and unique .dynsym symbols with type, binding and symbol version. Ordinal-only, forwarded and hidden-version exports stay distinct. Portable on any supported host. Coverage is partial when table entries are unreadable and unsupported when ELF dynamic symbols cannot be enumerated from the available section metadata; an empty complete inventory means the image declares no exports. Mach-O exports use inspect_macho. Omitted/complete detail preserves inline delivery. Select detail summary to retain complete Evidence and return identity, counts and source coverage. Query inspect_analysis_view kind native-exports, collection exports or issues, with exact names/original indices, fields and matching-row pagination. Names return every version or alias; source_index is scoped to the parent Evidence. ELF name projections keep raw-byte and encoding qualifications.",
|
||||
"Inspect one explicit local PE or ELF image's export table without executing it or opening an engine: PE export-directory names, ordinals, addresses and forwarders, or ELF defined default/protected global, weak and unique .dynsym symbols with type, binding, visibility and symbol version. Visibility does not establish a runtime binding; omission in older Evidence means unrecorded. Ordinal-only, forwarded and hidden-version exports stay distinct. Portable on any supported host. Coverage is partial when table entries are unreadable and unsupported when ELF dynamic symbols cannot be enumerated from the available section metadata; an empty complete inventory means the image declares no exports. Mach-O exports use inspect_macho. Omitted/complete detail preserves inline delivery. Select detail summary to retain complete Evidence and return identity, counts and source coverage. Query inspect_analysis_view kind native-exports, collection exports or issues, with exact names/original indices, fields and matching-row pagination. Names return every version or alias; source_index is scoped to the parent Evidence. ELF name projections keep raw-byte and encoding qualifications.",
|
||||
inputSchema: inspectNativeExportsRequestSchema,
|
||||
outputSchema: analysisDetailOutputSchemaOf(
|
||||
nativeExportsSchema,
|
||||
|
||||
@@ -247,6 +247,14 @@ export const projectNativeExportsView = (
|
||||
: row.name !== null && names.has(row.name))),
|
||||
projectRow,
|
||||
);
|
||||
if (
|
||||
report.format === "elf" &&
|
||||
columns.has("visibility") &&
|
||||
selected.rows.some((row) => !("visibility" in row))
|
||||
)
|
||||
shared.unknowns.push(
|
||||
"ELF symbol visibility was not recorded for some selected rows; omission means unknown.",
|
||||
);
|
||||
return ok({
|
||||
...shared,
|
||||
kind: "native-exports" as const,
|
||||
|
||||
@@ -72,6 +72,12 @@ const elfExportSchema = z.strictObject({
|
||||
size: z.string().regex(/^[0-9]+$/u),
|
||||
type: z.enum(["function", "ifunc", "object", "tls", "other"]),
|
||||
binding: z.enum(["global", "weak", "unique"]),
|
||||
visibility: z
|
||||
.enum(["default", "protected"])
|
||||
.exactOptional()
|
||||
.describe(
|
||||
"ELF symbol visibility as recorded in st_other. Omission means visibility was not recorded; it is not evidence of default visibility or a runtime binding.",
|
||||
),
|
||||
version: z.union([
|
||||
z.null(),
|
||||
z.literal("unknown"),
|
||||
|
||||
@@ -742,6 +742,7 @@ function* parseElfExports(
|
||||
size: symbol.size.toString(),
|
||||
type: ELF_TYPES[symbol.type] ?? "other",
|
||||
binding,
|
||||
visibility: visibility === 0 ? "default" : "protected",
|
||||
version,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,9 +4,13 @@ import { expect } from "vitest";
|
||||
import { z } from "zod";
|
||||
import { readEvidenceBundle } from "../../../src/application/EvidenceBundleFiles.js";
|
||||
import { toolContract } from "../../../src/contracts/toolContracts.js";
|
||||
import { evidenceSchema } from "../../../src/domain/evidence.js";
|
||||
import {
|
||||
createEvidence,
|
||||
evidenceSchema,
|
||||
} from "../../../src/domain/evidence.js";
|
||||
import { digestCanonicalValue } from "../../../src/domain/canonicalDigest.js";
|
||||
import { analysisViewResultSchema } from "../../../src/domain/analysisView/analysisView.js";
|
||||
import { nativeExportsSchema } from "../../../src/domain/native/nativeExports.js";
|
||||
import { connectLocalToolsMcp } from "../../fixtures/localToolsMcp.js";
|
||||
import {
|
||||
elfExportImage,
|
||||
@@ -18,6 +22,54 @@ import { cliTest } from "../../support/cli/cliFixture.js";
|
||||
const exportsContract = toolContract("inspect_native_exports");
|
||||
const viewContract = toolContract("inspect_analysis_view");
|
||||
|
||||
const checkElfVisibility = async (
|
||||
call: Awaited<ReturnType<typeof connectLocalToolsMcp>>["call"],
|
||||
parent: z.infer<typeof evidenceSchema>,
|
||||
) => {
|
||||
const view = {
|
||||
kind: "native-exports",
|
||||
collection: "exports",
|
||||
names: ["selected"],
|
||||
fields: ["visibility"],
|
||||
offset: 1,
|
||||
limit: 1,
|
||||
};
|
||||
const visibility = await call("inspect_analysis_view", {
|
||||
source: { kind: "retained-evidence", evidence_id: parent.evidence_id },
|
||||
view,
|
||||
});
|
||||
expect(visibility.isError).not.toBe(true);
|
||||
expect(
|
||||
viewContract.outputSchema.parse(visibility.structuredContent)
|
||||
.normalized_result,
|
||||
).toMatchObject({
|
||||
items: [{ source_index: 1, visibility: "protected" }],
|
||||
unknowns: [],
|
||||
});
|
||||
const report = nativeExportsSchema.parse(parent.normalized_result);
|
||||
if (report.format !== "elf") throw new Error("Expected ELF report");
|
||||
const historical = createEvidence(undefined, parent.provider, {
|
||||
operation: "inspect_native_exports",
|
||||
parameters: {},
|
||||
result: {
|
||||
...report,
|
||||
exports: report.exports.map(({ visibility: _visibility, ...row }) => row),
|
||||
},
|
||||
});
|
||||
const oldView = await call("inspect_analysis_view", {
|
||||
source: { kind: "inline", evidence: historical },
|
||||
view,
|
||||
});
|
||||
expect(oldView.isError).not.toBe(true);
|
||||
const oldResult = viewContract.outputSchema.parse(
|
||||
oldView.structuredContent,
|
||||
).normalized_result;
|
||||
expect(oldResult).toHaveProperty("items", [{ source_index: 1 }]);
|
||||
expect(oldResult).toMatchObject({
|
||||
unknowns: [expect.stringContaining("visibility was not recorded")],
|
||||
});
|
||||
};
|
||||
|
||||
cliTest.for(["pe", "elf"] as const)(
|
||||
"queries retained %s exports through CLI and actual stdio MCP after the source is deleted",
|
||||
{ timeout: 60_000 },
|
||||
@@ -36,7 +88,7 @@ cliTest.for(["pe", "elf"] as const)(
|
||||
: elfExportImage({
|
||||
symbols: [
|
||||
{ name: "selected", version: 2 },
|
||||
{ name: "selected", version: 0x8002 },
|
||||
{ name: "selected", version: 0x8002, visibility: 3 },
|
||||
],
|
||||
versionDefinitions: ["fixture", "V1"],
|
||||
});
|
||||
@@ -47,6 +99,14 @@ cliTest.for(["pe", "elf"] as const)(
|
||||
});
|
||||
expect(complete.exitCode, complete.stderr).toBe(0);
|
||||
const parent = exportsContract.outputSchema.parse(complete.json);
|
||||
if (format === "elf") {
|
||||
const exports = nativeExportsSchema.parse(parent.normalized_result);
|
||||
expect(exports.format).toBe("elf");
|
||||
expect(exports.exports).toMatchObject([
|
||||
{ visibility: "default" },
|
||||
{ visibility: "protected" },
|
||||
]);
|
||||
}
|
||||
const bundle = join(root, "complete.bundle.json");
|
||||
const summarized = await run({
|
||||
arguments: [
|
||||
@@ -144,6 +204,7 @@ cliTest.for(["pe", "elf"] as const)(
|
||||
]);
|
||||
const { view_digest, ...content } = projectedView;
|
||||
expect(view_digest).toBe(digestCanonicalValue(content, "Analysis view"));
|
||||
if (format === "elf") await checkElfVisibility(call, parent);
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
Reference in new issue
Block a user