From 9b7c35740f06a031961f9a801dd128788dd11b5e Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Mon, 13 Feb 2023 10:22:37 +0100 Subject: [PATCH] Fix PyLong digits access in CPython 3.12. Needed after https://github.com/python/cpython/pull/101292 See https://github.com/cython/cython/issues/5238 --- Cython/Utility/Builtins.c | 2 +- Cython/Utility/Optimize.c | 8 ++++---- Cython/Utility/StringTools.c | 2 +- Cython/Utility/TypeConversion.c | 16 ++++++++++++---- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Cython/Utility/Builtins.c b/Cython/Utility/Builtins.c index 1018eccf55d..b9de4104ca3 100644 --- a/Cython/Utility/Builtins.c +++ b/Cython/Utility/Builtins.c @@ -247,7 +247,7 @@ static PyObject *__Pyx_PyLong_AbsNeg(PyObject *num);/*proto*/ static PyObject *__Pyx_PyLong_AbsNeg(PyObject *n) { if (likely(Py_SIZE(n) == -1)) { // digits are unsigned - return PyLong_FromLong(((PyLongObject*)n)->ob_digit[0]); + return PyLong_FromLong(__Pyx_PyLong_Digits(n)[0]); } #if CYTHON_COMPILING_IN_CPYTHON { diff --git a/Cython/Utility/Optimize.c b/Cython/Utility/Optimize.c index 7a3e3cd3d4e..6e5c6e0c893 100644 --- a/Cython/Utility/Optimize.c +++ b/Cython/Utility/Optimize.c @@ -977,7 +977,7 @@ static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject const Py_ssize_t size = Py_SIZE(exp); // tuned to optimise branch prediction if (likely(size == 1)) { - shiftby = ((PyLongObject*)exp)->ob_digit[0]; + shiftby = __Pyx_PyLong_Digits(exp)[0]; } else if (size == 0) { return PyInt_FromLong(1L); } else if (unlikely(size < 0)) { @@ -1058,7 +1058,7 @@ static CYTHON_INLINE {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject els int unequal; unsigned long uintval; Py_ssize_t size = Py_SIZE({{pyval}}); - const digit* digits = ((PyLongObject*){{pyval}})->ob_digit; + const digit* digits = __Pyx_PyLong_Digits({{pyval}}); if (intval == 0) { // == 0 => Py_SIZE(pyval) == 0 {{return_compare('size', '0', c_op)}} @@ -1237,7 +1237,7 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, long intval, PY_LONG_LONG ll{{ival}}, llx; #endif {{endif}} - const digit* digits = ((PyLongObject*){{pyval}})->ob_digit; + const digit* digits = __Pyx_PyLong_Digits({{pyval}}); const Py_ssize_t size = Py_SIZE({{pyval}}); {{if c_op == '&'}} // special case for &-ing arbitrarily large numbers with known single digit operands @@ -1492,7 +1492,7 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, double floatv if (likely(PyLong_CheckExact({{pyval}}))) { #if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*){{pyval}})->ob_digit; + const digit* digits = __Pyx_PyLong_Digits({{pyval}}); const Py_ssize_t size = Py_SIZE({{pyval}}); switch (size) { case 0: {{fval}} = 0.0; {{zerodiv_check(fval)}} break; diff --git a/Cython/Utility/StringTools.c b/Cython/Utility/StringTools.c index 6b192a1d920..5d757fd35fb 100644 --- a/Cython/Utility/StringTools.c +++ b/Cython/Utility/StringTools.c @@ -1065,7 +1065,7 @@ static CYTHON_INLINE int __Pyx_PyByteArray_AppendObject(PyObject* bytearray, PyO if (Py_SIZE(value) == 0) { ival = 0; } else { - ival = ((PyLongObject*)value)->ob_digit[0]; + ival = __Pyx_PyLong_Digits(value)[0]; if (unlikely(ival > 255)) goto bad_range; } } else diff --git a/Cython/Utility/TypeConversion.c b/Cython/Utility/TypeConversion.c index a4befa79ff3..115e731870b 100644 --- a/Cython/Utility/TypeConversion.c +++ b/Cython/Utility/TypeConversion.c @@ -129,6 +129,14 @@ static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); // __Pyx_PyNumber_Float is now in it's own section since it has dependencies (needed to make // string conversion work the same in all circumstances) +#if CYTHON_USE_PYLONG_INTERNALS + #if PY_VERSION_HEX >= 0x030C00A5 + #define __Pyx_PyLong_Digits(x) (((PyLongObject*)x)->long_value.ob_digit) + #else + #define __Pyx_PyLong_Digits(x) (((PyLongObject*)x)->ob_digit) + #endif +#endif + #if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII static int __Pyx_sys_getdefaultencoding_not_ascii; static int __Pyx_init_sys_getdefaultencoding_params(void) { @@ -405,7 +413,7 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { #endif if (likely(PyLong_CheckExact(b))) { #if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)b)->ob_digit; + const digit* digits = __Pyx_PyLong_Digits(b); const Py_ssize_t size = Py_SIZE(b); // handle most common case first to avoid indirect branch and optimise branch prediction if (likely(__Pyx_sst_abs(size) <= 1)) { @@ -478,7 +486,7 @@ static CYTHON_INLINE PyObject* __Pyx__PyNumber_Float(PyObject* obj) { double val; if (PyLong_CheckExact(obj)) { #if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)obj)->ob_digit; + const digit* digits = __Pyx_PyLong_Digits(obj); switch (Py_SIZE(obj)) { case 0: val = 0.0; @@ -968,7 +976,7 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) { if (likely(PyLong_Check(x))) { if (is_unsigned) { #if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; + const digit* digits = __Pyx_PyLong_Digits(x); switch (Py_SIZE(x)) { case 0: return ({{TYPE}}) 0; case 1: __PYX_VERIFY_RETURN_INT({{TYPE}}, digit, digits[0]) @@ -1009,7 +1017,7 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) { } else { // signed #if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; + const digit* digits = __Pyx_PyLong_Digits(x); switch (Py_SIZE(x)) { case 0: return ({{TYPE}}) 0; case -1: __PYX_VERIFY_RETURN_INT({{TYPE}}, sdigit, (sdigit) (-(sdigit)digits[0]))