fix vectorcall argument handling (#4104)

Fixes #4093

- Make PY_VECTORCALL_ARGUMENTS_OFFSET a size_t like on CPython
- Remove the assert in PyVectorcall_NARGS and use checked cast
This commit is contained in:
Georg Brandl 2024-04-22 10:56:39 +02:00 committed by GitHub
parent da2d1aa8b4
commit c2ac9a98e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 8 additions and 9 deletions

View File

@ -0,0 +1 @@
Changes definitions of `PY_VECTORCALL_ARGUMENTS_OFFSET` and `PyVectorcall_NARGS` to fix a false-positive assertion.

View File

@ -4,8 +4,6 @@ use std::os::raw::{c_char, c_int};
#[cfg(not(Py_3_11))] #[cfg(not(Py_3_11))]
use crate::Py_buffer; use crate::Py_buffer;
#[cfg(Py_3_8)]
use crate::pyport::PY_SSIZE_T_MAX;
#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
use crate::{ use crate::{
vectorcallfunc, PyCallable_Check, PyThreadState, PyThreadState_GET, PyTuple_Check, vectorcallfunc, PyCallable_Check, PyThreadState, PyThreadState_GET, PyTuple_Check,
@ -42,14 +40,14 @@ extern "C" {
} }
#[cfg(Py_3_8)] #[cfg(Py_3_8)]
const PY_VECTORCALL_ARGUMENTS_OFFSET: Py_ssize_t = const PY_VECTORCALL_ARGUMENTS_OFFSET: size_t =
1 << (8 * std::mem::size_of::<Py_ssize_t>() as Py_ssize_t - 1); 1 << (8 * std::mem::size_of::<size_t>() as size_t - 1);
#[cfg(Py_3_8)] #[cfg(Py_3_8)]
#[inline(always)] #[inline(always)]
pub unsafe fn PyVectorcall_NARGS(n: size_t) -> Py_ssize_t { pub unsafe fn PyVectorcall_NARGS(n: size_t) -> Py_ssize_t {
assert!(n <= (PY_SSIZE_T_MAX as size_t)); let n = n & !PY_VECTORCALL_ARGUMENTS_OFFSET;
(n as Py_ssize_t) & !PY_VECTORCALL_ARGUMENTS_OFFSET n.try_into().expect("cannot fail due to mask")
} }
#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
@ -184,7 +182,7 @@ pub unsafe fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *m
let args = args_array.as_ptr().offset(1); // For PY_VECTORCALL_ARGUMENTS_OFFSET let args = args_array.as_ptr().offset(1); // For PY_VECTORCALL_ARGUMENTS_OFFSET
let tstate = PyThreadState_GET(); let tstate = PyThreadState_GET();
let nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET; let nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;
_PyObject_VectorcallTstate(tstate, func, args, nargsf as size_t, std::ptr::null_mut()) _PyObject_VectorcallTstate(tstate, func, args, nargsf, std::ptr::null_mut())
} }
extern "C" { extern "C" {
@ -206,7 +204,7 @@ pub unsafe fn PyObject_CallMethodNoArgs(
PyObject_VectorcallMethod( PyObject_VectorcallMethod(
name, name,
&self_, &self_,
1 | PY_VECTORCALL_ARGUMENTS_OFFSET as size_t, 1 | PY_VECTORCALL_ARGUMENTS_OFFSET,
std::ptr::null_mut(), std::ptr::null_mut(),
) )
} }
@ -223,7 +221,7 @@ pub unsafe fn PyObject_CallMethodOneArg(
PyObject_VectorcallMethod( PyObject_VectorcallMethod(
name, name,
args.as_ptr(), args.as_ptr(),
2 | PY_VECTORCALL_ARGUMENTS_OFFSET as size_t, 2 | PY_VECTORCALL_ARGUMENTS_OFFSET,
std::ptr::null_mut(), std::ptr::null_mut(),
) )
} }