From b018abf405fc7efebeaeb9b542e1e79238b4deac Mon Sep 17 00:00:00 2001 From: Chinesezjc Date: Fri, 21 Aug 2026 09:00:36 +0800 Subject: [PATCH] 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. --- .../code-runtime-python/py/bootstrap.py | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/packages/code-runtime/code-runtime-python/py/bootstrap.py b/packages/code-runtime/code-runtime-python/py/bootstrap.py index 90f108b4e2..1995ba0ad2 100644 --- a/packages/code-runtime/code-runtime-python/py/bootstrap.py +++ b/packages/code-runtime/code-runtime-python/py/bootstrap.py @@ -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