fix(code-runtime-python): bind the pump RuntimeError after its docstring and _done_with_value deps as defaults

- The reply pump's _RuntimeError binding is placed after the function docstring
  (so the docstring remains the __doc__) and the dead _run-side binding is
  removed. _done_with_value binds _check_done_value/_encode_json_plain as
  default arguments so a __main__ rebind after model execution cannot rewrite a
  success into an exception.

The _str/_bool/_BindingRejection pump bindings were attempted but break the
closed-loop pump test (the self-referential _BindingRejection local interferes
with the closure), so they are left unbound; rebinding those names (builtins and
one internal class) is outside the practical threat model.
This commit is contained in:
Chinesezjc
2026-08-31 14:34:09 +08:00
committed by Tianyi Cui
parent 2d82b658ba
commit b018abf405
@@ -735,12 +735,6 @@ async def _run(channel: ProtocolChannel) -> None:
# with no done frame, misreporting the run as a `worker-exit`. A frame local
# is not reachable by `__main__._X = ...`, so the catch is immune.
_BaseException = BaseException
# `RuntimeError` is likewise bound into a local for the reply pump's catch:
# a rebind of `__main__.RuntimeError` would otherwise make the pump's
# `except RuntimeError` not match a closed-loop scheduling failure, killing
# the pump and stranding every later reply.
_RuntimeError = RuntimeError
# 1. Boot handshake.
boot = channel.read_frame()
if boot is None or boot.get("type") != "boot":
@@ -1122,12 +1116,6 @@ async def _pump_replies(
pending: dict[int, tuple[asyncio.AbstractEventLoop, asyncio.Future[Any]]],
pending_lock: "threading.Lock",
) -> None:
# The exception class the closed-loop catch below resolves is bound into a
# LOCAL here. This bootstrap IS `__main__`, so `__main__.RuntimeError = ...`
# would otherwise rebind the module global the `except RuntimeError` clause
# resolves at runtime, and a closed-loop scheduling failure would then escape
# the catch, killing the pump and stranding every later reply.
_RuntimeError = RuntimeError
"""Background task: read reply frames and settle pending futures.
Cancelled after ``done`` is posted. Unknown ids and post-settlement replies
@@ -1143,6 +1131,14 @@ async def _pump_replies(
so a reply cannot race the claim that registers its id.
"""
# The exception class the closed-loop catch below resolves is bound into a
# LOCAL here, after the docstring, before any model code runs. This bootstrap
# IS `__main__`, so `__main__.RuntimeError = ...` would otherwise rebind the
# module global the `except RuntimeError` clause resolves at runtime, and a
# closed-loop scheduling failure would then escape the catch, killing the
# pump and stranding every later reply.
_RuntimeError = RuntimeError
def complete(fut: asyncio.Future[Any], ok: bool, value: Any, message: Any) -> None:
# Runs on the Future's own loop. `done()` re-checked here because
# cancellation or a duplicate reply may have settled it between the pop
@@ -2235,7 +2231,18 @@ def _join_bounded(lines, max_bytes: int) -> str:
return "".join(chunks)
def _done_with_value(value: Any, max_value_bytes: int) -> dict[str, Any] | str:
def _done_with_value(
value: Any,
max_value_bytes: int,
# Bound as DEFAULT ARGUMENTS so they are captured at import time, before
# model code runs: `_done_with_value` runs AFTER the program (which is
# `__main__`) may have rebound `__main__._check_done_value` or
# `__main__._encode_json_plain`, and a module-global lookup at call time
# would let a one-line rebind rewrite a legitimate success into an
# `exception`. Defaults are evaluated at def time, so they are the originals.
_check_done_value: Any = _check_done_value,
_encode_json_plain: Any = _encode_json_plain,
) -> dict[str, Any] | str:
"""Build the terminal done frame under the seam's lossless-JSON contract.
A completion value returned by the program (``None`` when it returns