fix(code-runtime-python): bound the load-time budget to the frame parser cap

The review found the 64 MiB parse cap contradicted the load-time budget bound:
maxLogBytes/maxValueBytes could be configured up to ceiling - envelope (~256 MiB),
but the receive path silently dropped any frame past the 64 MiB parser cap, so an
honest child's budget-internal done frame under such a config would be discarded
and the run stranded to the wall clock. The load bound is now parse-cap -
envelope, so a configured budget always fits through the parser; the boundary
test moves to 64 MiB - 64. The >64 MiB model-constructed binding-argument drop
is registered as an accepted residual in the README (en + zh).
This commit is contained in:
Chinesezjc
2026-08-31 14:51:20 +08:00
committed by Tianyi Cui
parent ab40136b02
commit fca41b78ea
5 changed files with 21 additions and 11 deletions
@@ -108,14 +108,17 @@ describe('PythonCodeRuntime — seam descriptors and misuse', () => {
// frame and fails the run as `worker-exit`, inverting the `output-limit`
// the cap describes. Both budgets are metered in already-escaped serialized
// bytes, so a payload occupies at most `cap + envelope` on the wire; the
// bound is `ceiling - envelope`, not `(ceiling - envelope) / 6` (that
// divided in escape expansion the charge already counts).
const admissible = 256 * 1024 * 1024 - 64
// bound is `parse-cap - envelope`, not `(ceiling - envelope) / 6` (that
// divided in escape expansion the charge already counts). The receive path
// drops raw frames past the 64 MiB parse cap before decoding, so a budget
// above it would admit a config whose honest child frames the host then
// silently discards.
const admissible = 64 * 1024 * 1024 - 64
const ctx = new Context()
await expect(ctx.plugin(PythonCodeRuntime, { maxLogBytes: admissible + 1 }))
.rejects.toThrow(/maxLogBytes must not exceed 268435392 .*fd-3 frame ceiling/)
.rejects.toThrow(/maxLogBytes must not exceed 67108800/)
await expect(ctx.plugin(PythonCodeRuntime, { maxValueBytes: admissible + 1 }))
.rejects.toThrow(/maxValueBytes must not exceed 268435392 .*fd-3 frame ceiling/)
.rejects.toThrow(/maxValueBytes must not exceed 67108800/)
// The boundary value itself loads: the bound is the largest cap a frame can
// still carry, not one below it. It needs an address space large enough to
// clear the separate maxValueBytes/addressSpaceMb worst-case gate (the cap