From c1fc7e84b4e0b207f957d384e1f317ed5c198ad8 Mon Sep 17 00:00:00 2001 From: youknowdot Date: Fri, 16 Oct 2026 13:00:12 +0900 Subject: [PATCH 1/3] Fix closerange empty ranges before unsigned conversion Return for equal bounds after clamping the lower bound. Retain subprocess-isolated Python regressions for empty, reversed, negative, and one-descriptor ranges. CPython builds with HAVE_CLOSE_RANGE retain the reference defect; do not weaken the regression. Assisted-by: OpenAI Codex:model version unavailable --- crates/host_env/src/crt_fd.rs | 2 +- extra_tests/snippets/stdlib_os.py | 35 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/crates/host_env/src/crt_fd.rs b/crates/host_env/src/crt_fd.rs index 5b2cf685be1..6a8cc1987f9 100644 --- a/crates/host_env/src/crt_fd.rs +++ b/crates/host_env/src/crt_fd.rs @@ -370,7 +370,7 @@ pub fn closerange(fd_low: Raw, fd_high: Raw) { // CPython clamps low to 0. let fd_low = fd_low.max(0); // close_range(2) is [low, high] whereas CPython's is [low, high). - if fd_high < fd_low { + if fd_high <= fd_low { return; } let high = fd_high - 1; diff --git a/extra_tests/snippets/stdlib_os.py b/extra_tests/snippets/stdlib_os.py index cc845adafe0..61457a711b9 100644 --- a/extra_tests/snippets/stdlib_os.py +++ b/extra_tests/snippets/stdlib_os.py @@ -1,6 +1,7 @@ import itertools import os import stat +import subprocess import sys import time @@ -113,6 +114,40 @@ def __index__(self): chmod_supports_directory_descriptors() +# Run in a child: a broken empty-range implementation can close every descriptor. +subprocess.run( + [ + sys.executable, + "-c", + """ +import errno +import os + +sentinel = os.open(os.devnull, os.O_RDONLY) +for low, high in ((0, 0), (-1, 0), (sentinel, sentinel), + (sentinel + 1, sentinel), (-2, -1)): + os.closerange(low, high) + os.fstat(sentinel) + +target = os.open(os.devnull, os.O_RDONLY) +other = os.open(os.devnull, os.O_RDONLY) +os.closerange(target, target + 1) +os.fstat(sentinel) +os.fstat(other) +try: + os.fstat(target) +except OSError as exc: + assert exc.errno == errno.EBADF +else: + raise AssertionError("closerange did not close its single descriptor") +os.close(other) +os.close(sentinel) +""", + ], + check=True, +) + + fd = os.open("README.md", os.O_RDONLY) assert fd > 0 From 5067bb3d935d825c9bb6c2e3c8947812dafce07f Mon Sep 17 00:00:00 2001 From: youknowdot Date: Fri, 16 Oct 2026 13:00:13 +0900 Subject: [PATCH 2/3] Fix deprecated PyO3 code input import in benchmarks Import PyCodeInput from the types module, the canonical location in PyO3 0.30. The old ffi re-export is deprecated and fails Clippy with warnings denied. Assisted-by: OpenAI Codex:model version unavailable --- benches/execution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benches/execution.rs b/benches/execution.rs index a09ab9c7890..c0c783f24ed 100644 --- a/benches/execution.rs +++ b/benches/execution.rs @@ -7,7 +7,7 @@ use criterion::{ Bencher, BenchmarkGroup, BenchmarkId, Criterion, Throughput, criterion_group, criterion_main, measurement::WallTime, }; -use pyo3::types::{PyCode, PyCodeInput, PyCodeMethods, PyDict, PyDictMethods}; +use pyo3::types::{PyCode, PyCodeMethods, PyDict, PyDictMethods, code::PyCodeInput}; use rustpython_compiler::Mode; use rustpython_vm::{Interpreter, PyResult, Settings}; use std::{collections::HashMap, path::Path}; From 5bc1814470459db99366b67e855c71d58d2f414c Mon Sep 17 00:00:00 2001 From: youknowdot Date: Fri, 16 Oct 2026 13:03:14 +0900 Subject: [PATCH 3/3] Scope closerange reference exclusion to affected CPython build Keep every RustPython closerange regression active. Exclude only the three documented negative or zero-upper-bound cases on CPython 3.15.0 final Linux builds with HAVE_CLOSE_RANGE, pending python/cpython#159183 for issue #159182. Positive empty, reversed and one-descriptor reference cases remain active; later versions run all cases. Assisted-by: OpenAI Codex:model version unavailable --- extra_tests/snippets/stdlib_os.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/extra_tests/snippets/stdlib_os.py b/extra_tests/snippets/stdlib_os.py index 61457a711b9..ddddb3c9e25 100644 --- a/extra_tests/snippets/stdlib_os.py +++ b/extra_tests/snippets/stdlib_os.py @@ -122,10 +122,24 @@ def __index__(self): """ import errno import os +import sys + +known_reference_bug = ( + sys.implementation.name == "cpython" + and sys.platform == "linux" + and sys.version_info == (3, 15, 0, "final", 0) +) +if known_reference_bug: + import sysconfig + known_reference_bug = bool(sysconfig.get_config_var("HAVE_CLOSE_RANGE")) sentinel = os.open(os.devnull, os.O_RDONLY) for low, high in ((0, 0), (-1, 0), (sentinel, sentinel), (sentinel + 1, sentinel), (-2, -1)): + # TODO: remove once the reference includes python/cpython#159183. + # https://github.com/python/cpython/issues/159182 + if known_reference_bug and (low, high) in ((0, 0), (-1, 0), (-2, -1)): + continue os.closerange(low, high) os.fstat(sentinel)