From d23dc631eee68e90444dfabba89a8ee86304ebe8 Mon Sep 17 00:00:00 2001 From: youknowdot Date: Sat, 10 Oct 2026 10:55:52 -0700 Subject: [PATCH] Validate lock timeout range before acquire restrictions (#9061) Preserve CPython signed nanosecond conversion precedence for reentrant and nonblocking acquisition, without changing the platform timeout maximum. Assisted-by: OpenAI Codex:model identifier unavailable --- crates/vm/src/stdlib/_thread.rs | 5 +++++ extra_tests/snippets/builtin_thread.py | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/crates/vm/src/stdlib/_thread.rs b/crates/vm/src/stdlib/_thread.rs index efe4ed302..a2bab628a 100644 --- a/crates/vm/src/stdlib/_thread.rs +++ b/crates/vm/src/stdlib/_thread.rs @@ -106,6 +106,11 @@ pub(crate) mod _thread { fn validate_acquire_args(args: AcquireArgs, vm: &VirtualMachine) -> PyResult<(bool, f64)> { let timeout = args.timeout.to_secs_f64(); + // CPython checks the signed nanosecond range before acquire-specific restrictions. + let timeout_ns = timeout * 1_000_000_000.0; + if !(i64::MIN as f64..-(i64::MIN as f64)).contains(&timeout_ns) { + return Err(vm.new_overflow_error("timestamp out of range for C PyTime_t")); + } if !args.blocking && timeout != -1.0 { return Err(vm.new_value_error("can't specify a timeout for a non-blocking call")); } diff --git a/extra_tests/snippets/builtin_thread.py b/extra_tests/snippets/builtin_thread.py index 3d12e76cc..b98a2a42e 100644 --- a/extra_tests/snippets/builtin_thread.py +++ b/extra_tests/snippets/builtin_thread.py @@ -9,6 +9,16 @@ for error, kwargs in ( (ValueError, {"blocking": False, "timeout": 1}), (ValueError, {"timeout": -2}), (OverflowError, {"timeout": _thread.TIMEOUT_MAX + 1}), + (OverflowError, {"blocking": False, "timeout": 2**63 / 1e9}), + (OverflowError, {"blocking": False, "timeout": -9_223_372_037}), + (OverflowError, {"timeout": -9_223_372_037}), + (OverflowError, {"blocking": False, "timeout": float("inf")}), + (OverflowError, {"timeout": float("inf")}), + (OverflowError, {"blocking": False, "timeout": float("-inf")}), + (OverflowError, {"timeout": float("-inf")}), + (ValueError, {"timeout": -(2**63) / 1e9}), + (ValueError, {"blocking": False, "timeout": 4_294_968}), + (ValueError, {"timeout": -4_294_968}), ): lock = _thread.RLock() assert lock.acquire()