From 3e0055edaffa51a18c036ee0f11a8f9beb52032b Mon Sep 17 00:00:00 2001 From: Chinesezjc Date: Wed, 26 Aug 2026 03:24:12 +0800 Subject: [PATCH] test(code-runtime-python): cover the boot-ack gate's re-entry guard and run-write failure The review rejected the v8-ignore defense for the ack gate: a forged second boot-ack is deterministically constructible (one os.write on fd 3) and the run-write failure is deterministically constructible with the boot-write-failure mock pattern. A program that forges an extra boot-ack asserts the run still completes once (the gate does not re-send the run frame); a mocked child whose fd-3 pipe accepts the boot frame but rejects the run write resolves a worker-exit. --- .../tests/boot-write-failure.spec.ts | 40 +++++++++++++++++++ .../code-runtime-python/tests/runtime.spec.ts | 21 ++++++++++ 2 files changed, 61 insertions(+) diff --git a/packages/code-runtime/code-runtime-python/tests/boot-write-failure.spec.ts b/packages/code-runtime/code-runtime-python/tests/boot-write-failure.spec.ts index 359bcc33ec..c87fa72989 100644 --- a/packages/code-runtime/code-runtime-python/tests/boot-write-failure.spec.ts +++ b/packages/code-runtime/code-runtime-python/tests/boot-write-failure.spec.ts @@ -47,6 +47,30 @@ afterEach(() => { spawnMock.mockReset() }) +/** A child whose fd-3 pipe accepts the boot write, then rejects the run write. */ +function fakeChildWithAckThenThrowingFd3(): EventEmitter { + const child = new EventEmitter() as EventEmitter & { + pid?: number + stdout: PassThrough + stderr: PassThrough + stdio: unknown[] + } + child.stdout = new PassThrough() + child.stderr = new PassThrough() + const proto = new PassThrough() + let writes = 0 + proto.write = () => { + writes += 1 + if (writes === 1) return true // The boot frame goes out. + throw Object.assign(new Error('EPIPE: broken pipe, write'), { code: 'EPIPE' }) + } + child.stdio = [new PassThrough(), child.stdout, child.stderr, proto] + // Emit the boot-ack after the boot write, so the run-frame write fires and + // hits the throwing pipe. + setImmediate(() => proto.emit('data', Buffer.from('{"type":"boot-ack"}\n'))) + return child +} + describe('PythonCodeRuntime — boot-write failure', () => { it('resolves a worker-exit when the fd-3 boot write throws (no TDZ ReferenceError)', async () => { // Before the fix, the boot-write block ran BEFORE `wallTimer`, `onAbort`, @@ -98,4 +122,20 @@ describe('PythonCodeRuntime — boot-write failure', () => { expect(existsSync(dirname(stagedBootstrap as string))).toBe(false) await fiber.dispose() }) + + it('resolves a worker-exit when the run write after boot-ack throws', async () => { + // The run frame goes out from the boot-ack handler; a pipe that accepts + // the boot frame but rejects the run write must settle the run as a + // worker-exit rather than reject run() or leave it hanging. + spawnMock.mockImplementation(() => fakeChildWithAckThenThrowingFd3()) + const ctx = new Context() + const fiber = await ctx.plugin(PythonCodeRuntime) + const runtime = ctx.codeRuntime as InstanceType + + const result = await runtime.run({ program: 'return 1', bindings: [] }) + + expect(result.error?.kind).toBe('worker-exit') + expect(result.error?.message).toContain('failed to boot python subprocess') + await fiber.dispose() + }) }) diff --git a/packages/code-runtime/code-runtime-python/tests/runtime.spec.ts b/packages/code-runtime/code-runtime-python/tests/runtime.spec.ts index 61f2d68a5e..cffeee3108 100644 --- a/packages/code-runtime/code-runtime-python/tests/runtime.spec.ts +++ b/packages/code-runtime/code-runtime-python/tests/runtime.spec.ts @@ -164,6 +164,27 @@ describe('PythonCodeRuntime — seam descriptors and misuse', () => { } }, 45_000) + it('ignores a forged second boot-ack without re-sending the run frame', async () => { + // The run frame is sent once, from the first boot-ack; a program that + // forges an extra boot-ack frame on fd 3 must not re-enter the gate (a + // second run frame would confuse the child's frame reader). The honest + // child sends exactly one ack; the forged one exercises the re-entry + // guard. + const { runtime } = await setup() + const result = await runtime.run({ + program: [ + 'import os', + // One forged boot-ack after the program starts; the run already went + // out on the real ack. + "os.write(3, b'{\"type\":\"boot-ack\"}\\n')", + 'return "done"', + ].join('\n'), + bindings: [], + }) + expect(result.error).toBeUndefined() + expect(result.value).toBe('done') + }, 15_000) + it('skips a PATH entry that is an executable DIRECTORY named like the interpreter', async () => { // accessSync(X_OK) succeeds on directories, so without the isFile guard a // PATH entry like a `python3` directory would be chosen over a later real