Skip to content

Commit 5772d0d

Browse files
committed
fix(exec): 子进程输出按 UTF-8 解码——toString() 用平台默认字符集,GBK 默认字符集的 Windows 上会把 CLI 的 UTF-8 输出解成乱码;附 POSIX printf 八进制转义回归测试
1 parent ef762a2 commit 5772d0d

2 files changed

Lines changed: 17 additions & 4 deletions

File tree

src/main/java/io/github/easy4j/codex/cli/CodexCliExecutor.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ private CodexCliResult runProcess(String stdin, String... args) {
143143
long startNanos = System.nanoTime();
144144
try {
145145
int exitCode = executor.execute(cmd);
146-
String out = stdout.toString().trim();
147-
String err = stderr.toString().trim();
146+
String out = stdout.toString(StandardCharsets.UTF_8).trim();
147+
String err = stderr.toString(StandardCharsets.UTF_8).trim();
148148
log.debug("codex CLI executed: exitCode={}, stdout.len={}", exitCode, out.length());
149149
if (watchdog.killedProcess()) {
150150
return new CodexCliResult(-1, out, "codex CLI timed out after " + timeoutMs + " ms\n" + err);
@@ -157,8 +157,8 @@ private CodexCliResult runProcess(String stdin, String... args) {
157157
// with the real exit code instead of discarding the output. The
158158
// deadline check makes the timeout verdict race-free even when
159159
// {@code watchdog.killedProcess()} has not observed the kill yet.
160-
String out = stdout.toString().trim();
161-
String err = stderr.toString().trim();
160+
String out = stdout.toString(StandardCharsets.UTF_8).trim();
161+
String err = stderr.toString(StandardCharsets.UTF_8).trim();
162162
boolean timedOut = watchdog.killedProcess()
163163
|| System.nanoTime() - startNanos >= timeoutMs * 1_000_000L;
164164
if (timedOut) {

src/test/java/io/github/easy4j/codex/cli/CodexCliExecutorTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,19 @@ void shouldFeedStdinToChildProcess() {
123123
assertEquals("secret-api-key", result.getStdout());
124124
}
125125

126+
@Test
127+
void shouldDecodeChildOutputAsUtf8() {
128+
// The CLIs emit UTF-8 regardless of platform; decoding with the
129+
// platform default charset would mojibake on GBK-default Windows.
130+
// 你 = \344\275\240, 好 = \345\245\275 (POSIX printf octal escapes).
131+
CodexCliExecutor executor = new CodexCliExecutor(configFor("/bin/sh"));
132+
133+
CodexCliResult result = executor.executeWithStdin(null, "-c", "printf '\\344\\275\\240\\345\\245\\275'");
134+
135+
assertEquals("你好", result.getStdout(),
136+
"child output must be decoded as UTF-8, not the platform default charset");
137+
}
138+
126139
@Test
127140
void shouldExecuteWithoutStdinAsBefore() {
128141
CodexCliExecutor executor = new CodexCliExecutor(configFor("/bin/echo"));

0 commit comments

Comments
 (0)