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}; 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..ddddb3c9e25 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,54 @@ 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 +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) + +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