fix(rizin): default one-shot output to plain presentation (#5269)
Default native one-shot Rizin presentation to plain text before collection while preserving caller colour overrides, literal output, recorded argv and shared CLI/MCP Evidence. Fixes #4488 Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
This commit is contained in:
1 parent
0e62094b69
commit
2dd5effe2a
4 files changed
+27
-24
No files matched your search
@@ -53,7 +53,7 @@ Persistent command Evidence retains the caller-selected and resolved startup pat
|
||||
rea debug-with-rizin --inferior-tty /dev/pts/7 ./program dr
|
||||
```
|
||||
|
||||
`execute_rizin_command` and `rea execute-rizin-command` run one selected command against a local artifact. The one-shot profile uses `-N -q -c`, suppressing user settings and scripts while leaving plugins available. Commands and plugins run with the REA process user's security context and may access files, the network, or perform other actions. REA preserves raw output and does not claim that command-specific JSON has one universal schema.
|
||||
`execute_rizin_command` and `rea execute-rizin-command` run one selected command against a local artifact. The one-shot profile uses `-N -q -e scr.color=0 -c`, suppressing user settings and scripts while leaving plugins available. Native terminal presentation defaults to plain text; the caller can explicitly enable colour with `e scr.color=1` in the selected command. REA preserves raw output, including literal ANSI bytes, and does not claim that command-specific JSON has one universal schema. Commands and plugins run with the REA process user's security context and may access files, the network, or perform other actions.
|
||||
|
||||
```sh
|
||||
rea execute-rizin-command ./program iI
|
||||
|
||||
@@ -7,10 +7,12 @@ export const RIZIN_PROVIDER_IDENTITY = {
|
||||
version: null,
|
||||
} as const;
|
||||
|
||||
/** Build a one-shot rz-pipe compatible command while retaining plugin availability. */
|
||||
/** Default one-shot presentation to plain text while retaining plugin availability. */
|
||||
export const rizinCommand = (input: RizinInput): readonly string[] => [
|
||||
"-N",
|
||||
"-q",
|
||||
"-e",
|
||||
"scr.color=0",
|
||||
"-c",
|
||||
input.command,
|
||||
absoluteCallerPath(input.path),
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
stopFakeNoInferior,
|
||||
rizinTestInferiorTty,
|
||||
} from "./RizinTestInferiorTty.js";
|
||||
import { rizinCommand } from "../../../src/rizin/RizinCommand.js";
|
||||
import * as providerProcess from "../../../src/process/ProviderProcess.js";
|
||||
import type { SpawnedOwnedProviderProcess } from "../../../src/process/ProviderProcess.js";
|
||||
import {
|
||||
@@ -26,19 +25,6 @@ const {
|
||||
} = createRizinCoverageHarness();
|
||||
afterEach(cleanup);
|
||||
|
||||
it.skipIf(process.platform === "win32")(
|
||||
"builds the one-shot command with the caller's path and command",
|
||||
() => {
|
||||
expect(rizinCommand({ path: "./sample file", command: "izz" })).toEqual([
|
||||
"-N",
|
||||
"-q",
|
||||
"-c",
|
||||
"izz",
|
||||
expect.stringMatching(/sample file/u),
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
||||
it.skipIf(process.platform === "win32")(
|
||||
"rejects unsupported, pre-cancelled, and failed startup requests",
|
||||
async () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createHash } from "node:crypto";
|
||||
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { isAbsolute, join, relative } from "node:path";
|
||||
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
@@ -274,9 +274,10 @@ it("marks signal-terminated provider commands as unknown completion", async () =
|
||||
});
|
||||
|
||||
describe("Rizin command service", () => {
|
||||
it("runs Rizin with user scripts suppressed while retaining plugins and preserves nonzero output", async () => {
|
||||
it("defaults Rizin to plain presentation and preserves caller-selected colour on nonzero exits", async () => {
|
||||
const directory = await mkdtemp(join(tmpdir(), "rea-rizin-"));
|
||||
const path = join(directory, "fixture.bin");
|
||||
const path = join(directory, "fixture with spaces.bin");
|
||||
const callerPath = relative(process.cwd(), path);
|
||||
await writeFile(path, "fixture");
|
||||
const calls: { command: string; args: readonly string[] }[] = [];
|
||||
const service = new ReverseEngineeringService({
|
||||
@@ -291,7 +292,7 @@ describe("Rizin command service", () => {
|
||||
killed: boolean;
|
||||
};
|
||||
Object.assign(failure, {
|
||||
stdout: "partial data",
|
||||
stdout: "\u001b[31mpartial data\u001b[0m\n",
|
||||
stderr: "command error",
|
||||
code: 2,
|
||||
signal: null,
|
||||
@@ -302,17 +303,26 @@ describe("Rizin command service", () => {
|
||||
});
|
||||
|
||||
try {
|
||||
const result = await service.executeRizinCommand({ path, command: "iI" });
|
||||
const command = "e scr.color=1;pd 1";
|
||||
const result = await service.executeRizinCommand({
|
||||
path: callerPath,
|
||||
command,
|
||||
});
|
||||
expect(result.ok).toBe(true);
|
||||
if (!result.ok) return;
|
||||
const lookupPath = result.value.subject?.local_path;
|
||||
expect(isAbsolute(lookupPath ?? "")).toBe(true);
|
||||
expect(result.value.subject?.digest.sha256).toBe(
|
||||
createHash("sha256").update("fixture").digest("hex"),
|
||||
);
|
||||
expect(calls).toEqual([
|
||||
{
|
||||
command: "/tools/rizin",
|
||||
args: ["-N", "-q", "-c", "iI", path],
|
||||
args: ["-N", "-q", "-e", "scr.color=0", "-c", command, lookupPath],
|
||||
},
|
||||
]);
|
||||
expect(result.value.raw_result).toMatchObject({
|
||||
stdout: "partial data",
|
||||
stdout: "\u001b[31mpartial data\u001b[0m\n",
|
||||
stderr: "command error",
|
||||
exit_code: 2,
|
||||
completion_status: "complete",
|
||||
@@ -320,14 +330,19 @@ describe("Rizin command service", () => {
|
||||
expect(result.value.limitations.join(" ")).not.toContain(
|
||||
"terminated by signal",
|
||||
);
|
||||
expect(result.value.normalized_result).toMatchObject({
|
||||
stdout: "\u001b[31mpartial data\u001b[0m\n",
|
||||
});
|
||||
expect(result.value.limitations).toContain(
|
||||
"Rizin commands and retained plugins may read files or access network resources outside the selected artifact; those external inputs are not bound to Evidence.",
|
||||
);
|
||||
expect(result.value.limitations).toHaveLength(4);
|
||||
expect(result.value.parameters).toMatchObject({
|
||||
command: "iI",
|
||||
path: callerPath,
|
||||
command,
|
||||
provider_executable: "/tools/rizin",
|
||||
});
|
||||
expect(result.value.parameters.command_arguments).toEqual(calls[0]?.args);
|
||||
expect(result.value.provider.id).toBe("rizin");
|
||||
} finally {
|
||||
await rm(directory, { recursive: true, force: true });
|
||||
|
||||
Reference in new issue
Block a user