mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
fix(ghidra): bound the Java version probe output (#2361)
The Java version probe captured its output with maxBuffer set to Infinity, so a chatty or hostile JVM selected as the Ghidra launcher could grow the captured stdout/stderr without limit and exhaust REA's memory during installation discovery. Bound the capture to 1 MiB, matching the budget already used for other Java listings. A probe that exceeds the budget yields no observation and is reported through the existing failed-probe path, the same one the Java check already uses whenever the probe cannot produce an observation. Co-authored-by: Claude Code <noreply@anthropic.com>
This commit is contained in:
1 parent
8e6f37e2a0
commit
e0bd31c18c
2 files changed
+50
-1
No files matched your search
@@ -72,6 +72,15 @@ const NATIVE_ARCHITECTURES: readonly {
|
||||
/** Bound installation discovery reads; larger headers remain unknown. */
|
||||
const EXECUTABLE_HEADER_PROBE_BYTES = 4096;
|
||||
|
||||
/**
|
||||
* Bound the Java version probe so a chatty or hostile JVM cannot force an
|
||||
* unbounded in-memory capture. Well-behaved JVMs print a few kilobytes for
|
||||
* `-XshowSettings:properties`; the same 1 MiB budget used for other Java
|
||||
* listings leaves ample headroom. A probe that exceeds the budget yields no
|
||||
* observation and is reported through the existing failed-probe path.
|
||||
*/
|
||||
const JAVA_PROBE_MAX_OUTPUT_BYTES = 1024 * 1024;
|
||||
|
||||
/** Compatibility of one present native decompiler with the inspected host. */
|
||||
type NativeDecompilerCompatibility =
|
||||
| {
|
||||
@@ -763,7 +772,7 @@ const systemGhidraInstallationHost = (): GhidraInstallationHost => ({
|
||||
encoding: "utf8",
|
||||
env: environment,
|
||||
timeout: 5_000,
|
||||
maxBuffer: Number.POSITIVE_INFINITY,
|
||||
maxBuffer: JAVA_PROBE_MAX_OUTPUT_BYTES,
|
||||
windowsHide: true,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -87,3 +87,43 @@ it.each([
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
it("bounds the Java version probe and reports an over-budget probe as a failed Java check", async () => {
|
||||
const root = await createTestTempDirectory("rea-java-probe-bound-");
|
||||
const configuredHome = join(root, "selected-jdk");
|
||||
const installDir = join(root, "ghidra");
|
||||
await mkdir(join(installDir, "Ghidra"), { recursive: true });
|
||||
await writeFile(
|
||||
join(installDir, "Ghidra", "application.properties"),
|
||||
`application.version=${SUPPORTED_GHIDRA_VERSION}\napplication.java.min=17\n`,
|
||||
);
|
||||
// A chatty or hostile JVM that overruns the capture budget: spawnSync reports
|
||||
// ENOBUFS, which the probe already treats as a failed observation.
|
||||
mockSpawnSync.mockReturnValue({
|
||||
stdout: "",
|
||||
stderr: "java.version = 21.0.11\n",
|
||||
status: null,
|
||||
error: Object.assign(new Error("spawnSync /java ENOBUFS"), {
|
||||
code: "ENOBUFS",
|
||||
}),
|
||||
});
|
||||
|
||||
const inspection = inspectGhidraInstallation({
|
||||
environment: {},
|
||||
installDir,
|
||||
javaHome: configuredHome,
|
||||
});
|
||||
|
||||
const [, , options] = mockSpawnSync.mock.calls[0] as [
|
||||
string,
|
||||
readonly string[],
|
||||
{ readonly maxBuffer?: number },
|
||||
];
|
||||
expect(options.maxBuffer).toBe(1024 * 1024);
|
||||
expect(inspection.javaVersion).toBeNull();
|
||||
expect(inspection.javaHome).toBe(configuredHome);
|
||||
expect(inspection.checks.find(({ name }) => name === "java")).toMatchObject({
|
||||
status: "failed",
|
||||
code: "runtime_missing",
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user