From 1776e37dc766f7ec20ad020ba75726ba2bb26d2f Mon Sep 17 00:00:00 2001 From: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> Date: Sun, 6 Sep 2026 23:07:45 +0100 Subject: [PATCH 1/3] fix: make runCommand maxBuffer explicit --- plugins/codex/scripts/lib/process.mjs | 5 ++++- tests/process.test.mjs | 24 +++++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/plugins/codex/scripts/lib/process.mjs b/plugins/codex/scripts/lib/process.mjs index dd8fc3751..78bb9a20e 100644 --- a/plugins/codex/scripts/lib/process.mjs +++ b/plugins/codex/scripts/lib/process.mjs @@ -1,13 +1,16 @@ import { spawnSync } from "node:child_process"; import process from "node:process"; +// Git metadata can exceed Node's 1 MiB spawnSync default. Keep a generous explicit bound. +const DEFAULT_MAX_BUFFER = 256 * 1024 * 1024; + export function runCommand(command, args = [], options = {}) { const result = spawnSync(command, args, { cwd: options.cwd, env: options.env, encoding: "utf8", input: options.input, - maxBuffer: options.maxBuffer, + maxBuffer: options.maxBuffer ?? DEFAULT_MAX_BUFFER, stdio: options.stdio ?? "pipe", shell: options.shell ?? (process.platform === "win32" ? (process.env.SHELL || true) : false), windowsHide: true diff --git a/tests/process.test.mjs b/tests/process.test.mjs index 80e0715b0..003a51bd5 100644 --- a/tests/process.test.mjs +++ b/tests/process.test.mjs @@ -1,7 +1,29 @@ import test from "node:test"; import assert from "node:assert/strict"; -import { terminateProcessTree } from "../plugins/codex/scripts/lib/process.mjs"; +import { runCommand, terminateProcessTree } from "../plugins/codex/scripts/lib/process.mjs"; + +test("runCommand allows output larger than Node's default maxBuffer", () => { + const outputBytes = 2 * 1024 * 1024; + const result = runCommand(process.execPath, [ + "-e", + `process.stdout.write("x".repeat(${outputBytes}))` + ]); + + assert.equal(result.error, null); + assert.equal(result.status, 0); + assert.equal(Buffer.byteLength(result.stdout), outputBytes); +}); + +test("runCommand preserves an explicit maxBuffer override", () => { + const result = runCommand( + process.execPath, + ["-e", `process.stdout.write("x".repeat(${2 * 1024}))`], + { maxBuffer: 1024 } + ); + + assert.equal(result.error?.code, "ENOBUFS"); +}); test("terminateProcessTree uses taskkill on Windows", () => { let captured = null; From d2f85dc21939bbd532d59e12738c0753e402c46d Mon Sep 17 00:00:00 2001 From: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> Date: Sat, 7 Nov 2026 10:09:05 +0000 Subject: [PATCH 2/3] Cover large Unicode output on both command streams --- tests/process.test.mjs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/process.test.mjs b/tests/process.test.mjs index 003a51bd5..bcee2a143 100644 --- a/tests/process.test.mjs +++ b/tests/process.test.mjs @@ -75,3 +75,18 @@ test("terminateProcessTree treats missing Windows processes as already stopped", assert.equal(outcome.result.status, 128); assert.match(outcome.result.stdout, /not found/i); }); + + +for (const [stream, character] of [["stdout", "é"], ["stderr", "😀"]]) { + test(`runCommand retains large Unicode ${stream} output`, () => { + const text = character.repeat(600_000); + const result = runCommand(process.execPath, [ + "-e", + `process.${stream}.write(${JSON.stringify(character)}.repeat(600000))` + ]); + assert.equal(result.status, 0); + assert.equal(result.error, null); + assert.equal(result[stream], text); + assert.equal(Buffer.byteLength(result[stream]), Buffer.byteLength(text)); + }); +} From 26e52abed72f0afb25e4727db593949c92aceb57 Mon Sep 17 00:00:00 2001 From: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> Date: Sat, 7 Nov 2026 11:47:05 +0000 Subject: [PATCH 3/3] Keep subprocess buffer tests independent of shell settings --- tests/process.test.mjs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/process.test.mjs b/tests/process.test.mjs index bcee2a143..13e70ecf0 100644 --- a/tests/process.test.mjs +++ b/tests/process.test.mjs @@ -8,7 +8,7 @@ test("runCommand allows output larger than Node's default maxBuffer", () => { const result = runCommand(process.execPath, [ "-e", `process.stdout.write("x".repeat(${outputBytes}))` - ]); + ], { shell: false }); assert.equal(result.error, null); assert.equal(result.status, 0); @@ -19,7 +19,7 @@ test("runCommand preserves an explicit maxBuffer override", () => { const result = runCommand( process.execPath, ["-e", `process.stdout.write("x".repeat(${2 * 1024}))`], - { maxBuffer: 1024 } + { maxBuffer: 1024, shell: false } ); assert.equal(result.error?.code, "ENOBUFS"); @@ -83,7 +83,7 @@ for (const [stream, character] of [["stdout", "é"], ["stderr", "😀"]]) { const result = runCommand(process.execPath, [ "-e", `process.${stream}.write(${JSON.stringify(character)}.repeat(600000))` - ]); + ], { shell: false }); assert.equal(result.status, 0); assert.equal(result.error, null); assert.equal(result[stream], text);