Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-Cython for openSUSE:Factory checked in at 2026-08-01 18:28:24 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-Cython (Old) and /work/SRC/openSUSE:Factory/.python-Cython.new.16738 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-Cython" Sat Aug 1 18:28:24 2026 rev:93 rq:1368882 version:3.2.9 Changes: -------- --- /work/SRC/openSUSE:Factory/python-Cython/python-Cython.changes 2026-07-22 19:01:00.664632027 +0200 +++ /work/SRC/openSUSE:Factory/.python-Cython.new.16738/python-Cython.changes 2026-08-01 18:29:02.915196200 +0200 @@ -1,0 +2,23 @@ +Fri Jul 31 17:20:49 UTC 2026 - Dirk Müller <[email protected]> + +- update to 3.2.9: + * Indexing into freshly created lists with an out-of-bounds + index could crash. (Github issue :issue:`7793`) + * Function arguments with default values could end up + uninitialised in closures, leading to crashes. Patch by + Anthony Donlon. (Github issue :issue:`7782`) + * bytearray.append(None) could crash. The optimised code was + also lacking concurrency guards. (Github issue :issue:`7796`) + * Some rare corner cases when concatenating text strings were + resolved. (Github issue :issue:`7799`) + * Assignments of builtin string types to typedefs of object + could erroneously be rejected. (Github issue :issue:`7789`) + * Subscripting type failed with a TypeError. (Github issue + :issue:`5563`) + * Manually disabling CYTHON_VECTORCALL in CPython could lead to + invalid C code. Patch by Florent Gallaire. (Github issue + :issue:`7807`) + * Some internal Limited API version checks for Py3.12 were + corrected. (Github issue :issue:`7845`) + +------------------------------------------------------------------- Old: ---- cython-3.2.8.tar.gz New: ---- cython-3.2.9.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-Cython.spec ++++++ --- /var/tmp/diff_new_pack.sDJfc7/_old 2026-08-01 18:29:03.531217188 +0200 +++ /var/tmp/diff_new_pack.sDJfc7/_new 2026-08-01 18:29:03.531217188 +0200 @@ -24,7 +24,7 @@ %endif %{?sle15_python_module_pythons} Name: python-Cython -Version: 3.2.8 +Version: 3.2.9 Release: 0 Summary: The Cython compiler for writing C extensions for the Python language License: Apache-2.0 ++++++ cython-3.2.8.tar.gz -> cython-3.2.9.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/.gitrev new/cython-3.2.9/.gitrev --- old/cython-3.2.8/.gitrev 2026-06-30 08:39:03.477812800 +0200 +++ new/cython-3.2.9/.gitrev 2026-07-24 06:49:25.742120500 +0200 @@ -1 +1 @@ -fee6fd61250fa0df1ff2ff9cd7f6f50d203391f8 +58b8e6adc51c99c8cd5dd75db720e4aa7c051cb6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/CHANGES.rst new/cython-3.2.9/CHANGES.rst --- old/cython-3.2.8/CHANGES.rst 2026-06-30 08:38:54.475277700 +0200 +++ new/cython-3.2.9/CHANGES.rst 2026-07-24 06:49:15.587098800 +0200 @@ -2,6 +2,37 @@ Cython Changelog ================ +3.2.9 (2026-07-23) +================== + +Bugs fixed +---------- + +* Indexing into freshly created lists with an out-of-bounds index could crash. + (Github issue :issue:`7793`) + +* Function arguments with default values could end up uninitialised in closures, leading to crashes. + Patch by Anthony Donlon. (Github issue :issue:`7782`) + +* ``bytearray.append(None)`` could crash. The optimised code was also lacking concurrency guards. + (Github issue :issue:`7796`) + +* Some rare corner cases when concatenating text strings were resolved. + (Github issue :issue:`7799`) + +* Assignments of builtin string types to typedefs of `object` could erroneously be rejected. + (Github issue :issue:`7789`) + +* Subscripting ``type`` failed with a ``TypeError``. + (Github issue :issue:`5563`) + +* Manually disabling ``CYTHON_VECTORCALL`` in CPython could lead to invalid C code. + Patch by Florent Gallaire. (Github issue :issue:`7807`) + +* Some internal Limited API version checks for Py3.12 were corrected. + (Github issue :issue:`7845`) + + 3.2.8 (2026-06-30) ================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/Cython/Compiler/ExprNodes.py new/cython-3.2.9/Cython/Compiler/ExprNodes.py --- old/cython-3.2.8/Cython/Compiler/ExprNodes.py 2026-06-30 08:38:54.481277700 +0200 +++ new/cython-3.2.9/Cython/Compiler/ExprNodes.py 2026-07-24 06:49:15.593098900 +0200 @@ -640,15 +640,16 @@ # If it's a refcounted variable, we hold a reference to it. Therefore, if # the reference count is 1, we trust that we're the unique owner. return "__Pyx_ReferenceSharing_OwnStrongReference" - if not hasattr(self, "entry") or self.entry is None: + entry = getattr(self, "entry", None) + if entry is None: return "__Pyx_ReferenceSharing_SharedReference" # Not sure if we can reason about it - if self.entry.is_arg: + if entry.is_arg: # Arguments are a little hard to reason about so need an extra level of check return "__Pyx_ReferenceSharing_FunctionArgument" - if (self.entry.scope.is_local_scope and + if (entry.scope.is_local_scope and # TODO - in principle a generator closure should be "non shared" because # only one thread can run the generator at once. - not self.entry.in_closure and not self.entry.from_closure): + not entry.in_closure and not entry.from_closure): return "__Pyx_ReferenceSharing_OwnStrongReference" # Most likely a global, or a class attribute return "__Pyx_ReferenceSharing_SharedReference" @@ -1804,7 +1805,7 @@ node = BytesNode(self.pos, value=self.value, constant_result=self.constant_result) if dst_type.is_pyobject: - if dst_type in (py_object_type, Builtin.bytes_type): + if dst_type.resolve() in (py_object_type, Builtin.bytes_type): node.type = Builtin.bytes_type else: self.check_for_coercion_error(dst_type, env, fail=True) @@ -1918,7 +1919,7 @@ "Unicode literals do not support coercion to C types other " "than Py_UCS4/Py_UNICODE (for characters), Py_UNICODE* " "(for strings) or char*/void* (for auto-encoded strings).") - elif dst_type is not py_object_type: + elif dst_type.resolve() is not py_object_type: self.check_for_coercion_error(dst_type, env, fail=True) return self @@ -3249,7 +3250,7 @@ if test_name == 'List': code.putln( - f"{result_name} = __Pyx_PyList_GetItemRefFast(" + f"{result_name} = __Pyx_PyList_GET_ITEM_REF(" f"{self.py_result()}, {self.counter_cname}, {self.may_be_unsafe_shared()});") else: # Tuple code.putln("#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS") @@ -8719,10 +8720,10 @@ # unpack items from list/tuple in unrolled loop (can't fail) if len(sequence_types) == 2: code.putln("if (likely(Py%s_CheckExact(sequence))) {" % sequence_types[0]) + sequence_sharing_status = self.may_be_unsafe_shared() if 'List' in sequence_types else 'UNUSED' for i, item in enumerate(self.unpacked_items): if sequence_types[0] == "List": - code.putln(f"{item.result()} = __Pyx_PyList_GetItemRefFast" - f"(sequence, {i}, {self.may_be_unsafe_shared()});") + code.putln(f"{item.result()} = __Pyx_PyList_GET_ITEM_REF(sequence, {i}, {sequence_sharing_status});") code.putln(code.error_goto_if_null(item.result(), self.pos)) code.put_xgotref(item.result(), item.ctype()) else: # Tuple @@ -8730,14 +8731,11 @@ code.put_incref(item.result(), item.ctype()) if len(sequence_types) == 2: code.putln("} else {") + assert sequence_types[1] == 'List', sequence_types for i, item in enumerate(self.unpacked_items): - if sequence_types[1] == "List": - code.putln(f"{item.result()} = __Pyx_PyList_GetItemRefFast(sequence, {i}, {self.may_be_unsafe_shared()});") - code.putln(code.error_goto_if_null(item.result(), self.pos)) - code.put_xgotref(item.result(), item.ctype()) - else: # Tuple - code.putln(f"{item.result()} = PyTuple_GET_ITEM(sequence, {i});") - code.put_incref(item.result(), item.ctype()) + code.putln(f"{item.result()} = __Pyx_PyList_GET_ITEM_REF(sequence, {i}, {sequence_sharing_status});") + code.putln(code.error_goto_if_null(item.result(), self.pos)) + code.put_xgotref(item.result(), item.ctype()) code.putln("}") code.putln("#else") @@ -12665,7 +12663,7 @@ if self.inplace or self.operand1.result_in_temp(): code.globalstate.use_utility_code( UtilityCode.load_cached("UnicodeConcatInPlace", "ObjectHandling.c")) - func += self.may_be_unsafe_shared() + func += self.operand1.may_be_unsafe_shared() if func: # any necessary utility code will be got by "NumberAdd" in generate_evaluation_code diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/Cython/Compiler/Nodes.py new/cython-3.2.9/Cython/Compiler/Nodes.py --- old/cython-3.2.8/Cython/Compiler/Nodes.py 2026-06-30 08:38:54.484277700 +0200 +++ new/cython-3.2.9/Cython/Compiler/Nodes.py 2026-07-24 06:49:15.596099000 +0200 @@ -3039,7 +3039,7 @@ # Move arguments into closure if required def put_into_closure(entry): - if entry.in_closure and not arg.default: + if entry.in_closure: code.putln('%s = %s;' % (entry.cname, entry.original_cname)) if entry.type.is_memoryviewslice: entry.type.generate_incref_memoryviewslice(code, entry.cname, True) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/Cython/Compiler/Optimize.py new/cython-3.2.9/Cython/Compiler/Optimize.py --- old/cython-3.2.8/Cython/Compiler/Optimize.py 2026-06-30 08:38:54.485277700 +0200 +++ new/cython-3.2.9/Cython/Compiler/Optimize.py 2026-07-24 06:49:15.596099000 +0200 @@ -3183,9 +3183,14 @@ else: return node + ba_obj = args[0].as_none_safe_node( + "'NoneType' object has no attribute '%.30s'", + error="PyExc_AttributeError", + format_args=['append']) + new_node = ExprNodes.PythonCapiCallNode( node.pos, func_name, func_type, - args=[args[0], value], + args=[ba_obj, value], may_return_none=False, is_temp=node.is_temp, utility_code=utility_code, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/Cython/Shadow.py new/cython-3.2.9/Cython/Shadow.py --- old/cython-3.2.8/Cython/Shadow.py 2026-06-30 08:38:54.498816500 +0200 +++ new/cython-3.2.9/Cython/Shadow.py 2026-07-24 06:49:15.611288500 +0200 @@ -1,7 +1,7 @@ # cython.* namespace for pure mode. # Possible version formats: "3.1.0", "3.1.0a1", "3.1.0a1.dev0" -__version__ = "3.2.8" +__version__ = "3.2.9" # BEGIN shameless copy from Cython/minivect/minitypes.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/Cython/Utility/Exceptions.c new/cython-3.2.9/Cython/Utility/Exceptions.c --- old/cython-3.2.8/Cython/Utility/Exceptions.c 2026-06-30 08:38:54.501277700 +0200 +++ new/cython-3.2.9/Cython/Utility/Exceptions.c 2026-07-24 06:49:15.612570300 +0200 @@ -419,13 +419,13 @@ tstate->curexc_value = 0; tstate->curexc_traceback = 0; #endif -#elif __PYX_LIMITED_VERSION_HEX > 0x030C0000 +#elif __PYX_LIMITED_VERSION_HEX >= 0x030C0000 local_value = PyErr_GetRaisedException(); #else PyErr_Fetch(&local_type, &local_value, &local_tb); #endif -#if __PYX_LIMITED_VERSION_HEX > 0x030C0000 +#if __PYX_LIMITED_VERSION_HEX >= 0x030C0000 if (likely(local_value)) { local_type = (PyObject*) Py_TYPE(local_value); Py_INCREF(local_type); @@ -446,7 +446,7 @@ if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) goto bad; } -#endif // __PYX_LIMITED_VERSION_HEX > 0x030C0000 +#endif // __PYX_LIMITED_VERSION_HEX >= 0x030C0000 // traceback may be NULL for freshly raised exceptions Py_XINCREF(local_tb); @@ -503,7 +503,7 @@ return 0; -#if __PYX_LIMITED_VERSION_HEX <= 0x030C0000 +#if __PYX_LIMITED_VERSION_HEX < 0x030C0000 bad: *type = 0; *value = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/Cython/Utility/FunctionArguments.c new/cython-3.2.9/Cython/Utility/FunctionArguments.c --- old/cython-3.2.8/Cython/Utility/FunctionArguments.c 2026-06-30 08:38:54.501277700 +0200 +++ new/cython-3.2.9/Cython/Utility/FunctionArguments.c 2026-07-24 06:49:15.613098900 +0200 @@ -960,10 +960,10 @@ #define __Pyx_ArgsSlice_VARARGS(args, start, stop) PyTuple_GetSlice(args, start, stop) -#if CYTHON_METH_FASTCALL || (CYTHON_COMPILING_IN_CPYTHON && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS) +#if CYTHON_METH_FASTCALL #define __Pyx_ArgsSlice_FASTCALL(args, start, stop) __Pyx_PyTuple_FromArray(args + start, stop - start) #else -#define __Pyx_ArgsSlice_FASTCALL(args, start, stop) PyTuple_GetSlice(args, start, stop) +#define __Pyx_ArgsSlice_FASTCALL __Pyx_ArgsSlice_VARARGS #endif /////////////// fastcall /////////////// diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/Cython/Utility/ModuleSetupCode.c new/cython-3.2.9/Cython/Utility/ModuleSetupCode.c --- old/cython-3.2.8/Cython/Utility/ModuleSetupCode.c 2026-06-30 08:38:54.502277600 +0200 +++ new/cython-3.2.9/Cython/Utility/ModuleSetupCode.c 2026-07-24 06:49:15.614099000 +0200 @@ -1092,30 +1092,42 @@ #endif -#if CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS - #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 - #define __Pyx_PyList_GetItemRef(o, i) PyList_GetItemRef(o, i) - #elif CYTHON_COMPILING_IN_LIMITED_API || !CYTHON_ASSUME_SAFE_MACROS +// __Pyx_PyList_GetItemRef(): return safely owned reference, bounds checking, no wraparound +#if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + #define __Pyx_PyList_GetItemRef(o, i) PyList_GetItemRef(o, i) +#elif CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS + #if CYTHON_COMPILING_IN_LIMITED_API || !CYTHON_ASSUME_SAFE_MACROS #define __Pyx_PyList_GetItemRef(o, i) (likely((i) >= 0) ? PySequence_GetItem(o, i) : (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) #else #define __Pyx_PyList_GetItemRef(o, i) PySequence_ITEM(o, i) #endif -#elif CYTHON_COMPILING_IN_LIMITED_API || !CYTHON_ASSUME_SAFE_MACROS - #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 - #define __Pyx_PyList_GetItemRef(o, i) PyList_GetItemRef(o, i) - #else - #define __Pyx_PyList_GetItemRef(o, i) __Pyx_XNewRef(PyList_GetItem(o, i)) - #endif +#elif CYTHON_COMPILING_IN_LIMITED_API || !(CYTHON_ASSUME_SAFE_MACROS && CYTHON_ASSUME_SAFE_SIZE) + #define __Pyx_PyList_GetItemRef(o, i) __Pyx_XNewRef(PyList_GetItem(o, i)) #else - #define __Pyx_PyList_GetItemRef(o, i) __Pyx_NewRef(PyList_GET_ITEM(o, i)) + #define __Pyx_PyList_GetItemRef(o, i) (likely(__Pyx_is_valid_index(i, PyList_GET_SIZE(o))) ? \ + __Pyx_NewRef(PyList_GET_ITEM(o, i)) : (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) #endif - -#if CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS && !CYTHON_COMPILING_IN_LIMITED_API && CYTHON_ASSUME_SAFE_MACROS - #define __Pyx_PyList_GetItemRefFast(o, i, unsafe_shared) (__Pyx_IS_UNIQUELY_REFERENCED(o, unsafe_shared) ? \ - __Pyx_NewRef(PyList_GET_ITEM(o, i)) : __Pyx_PyList_GetItemRef(o, i)) +// __Pyx_PyList_GET_ITEM_REF(): return safely owned reference, no bounds checking (if avoidable), no wraparound +#if CYTHON_AVOID_BORROWED_REFS || CYTHON_COMPILING_IN_LIMITED_API + #define __Pyx_PyList_GET_ITEM_REF(o, i, unsafe_shared) ((void)(unsafe_shared), \ + __Pyx_PyList_GetItemRef(o, i)) +#elif CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS + #if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PyList_GET_ITEM_REF(o, i, unsafe_shared) ( \ + __Pyx_IS_UNIQUELY_REFERENCED(o, unsafe_shared) ? \ + __Pyx_NewRef(PyList_GET_ITEM(o, i)) : __Pyx_PyList_GetItemRef(o, i)) + #else + #define __Pyx_PyList_GET_ITEM_REF(o, i, unsafe_shared) ( \ + __Pyx_IS_UNIQUELY_REFERENCED(o, unsafe_shared) ? \ + __Pyx_XNewRef(PyList_GetItem(o, i)) : __Pyx_PyList_GetItemRef(o, i)) + #endif +#elif CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PyList_GET_ITEM_REF(o, i, unsafe_shared) ((void)(unsafe_shared), \ + __Pyx_NewRef(PyList_GET_ITEM(o, i))) #else - #define __Pyx_PyList_GetItemRefFast(o, i, unsafe_shared) __Pyx_PyList_GetItemRef(o, i) + #define __Pyx_PyList_GET_ITEM_REF(o, i, unsafe_shared) ((void)(unsafe_shared), \ + __Pyx_XNewRef(PyList_GetItem(o, i))) #endif #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 @@ -1159,6 +1171,7 @@ #define __Pyx_PyList_SET_ITEM(o, i, v) (PyList_SET_ITEM(o, i, v), (0)) #define __Pyx_PyList_GET_ITEM(o, i) PyList_GET_ITEM(o, i) #else + // NOTE: implements wrap-around #define __Pyx_PySequence_ITEM(o, i) PySequence_GetItem(o, i) // NOTE: might fail with exception => check for -1 #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/Cython/Utility/ObjectHandling.c new/cython-3.2.9/Cython/Utility/ObjectHandling.c --- old/cython-3.2.8/Cython/Utility/ObjectHandling.c 2026-06-30 08:38:54.502277600 +0200 +++ new/cython-3.2.9/Cython/Utility/ObjectHandling.c 2026-07-24 06:49:15.614099000 +0200 @@ -361,6 +361,12 @@ __Pyx_TypeName obj_type_name; // Handles less common slow-path checks for GetItem if (likely(PyType_Check(obj))) { + #if __PYX_LIMITED_VERSION_HEX >= 0x03090000 + if ((PyTypeObject*)obj == &PyType_Type) { + return Py_GenericAlias(obj, key); + } + #endif + PyObject *meth = __Pyx_PyObject_GetAttrStrNoError(obj, PYIDENT("__class_getitem__")); if (!meth) { PyErr_Clear(); @@ -464,26 +470,57 @@ return r; } +static PyObject *__Pyx_GetItemInt_Generic_size(PyObject *o, Py_ssize_t i) { + return __Pyx_GetItemInt_Generic(o, PyLong_FromSsize_t(i)); +} + {{for type in ['List', 'Tuple']}} static CYTHON_INLINE PyObject *__Pyx_GetItemInt_{{type}}_Fast(PyObject *o, Py_ssize_t i, int wraparound, int boundscheck, int unsafe_shared) { CYTHON_MAYBE_UNUSED_VAR(unsafe_shared); -#if CYTHON_ASSUME_SAFE_SIZE{{if type == 'Tuple'}} && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS{{endif}} +#if CYTHON_AVOID_BORROWED_REFS + CYTHON_UNUSED_VAR(boundscheck); Py_ssize_t wrapped_i = i; if (wraparound & unlikely(i < 0)) { - wrapped_i += Py{{type}}_GET_SIZE(o); + Py_ssize_t size = __Pyx_Py{{type}}_GET_SIZE(o); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely(size < 0)) return NULL; + #endif + wrapped_i += size; } {{if type == 'List'}} - if ((CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS || !CYTHON_ASSUME_SAFE_MACROS)) { + return __Pyx_PyList_GetItemRef(o, wrapped_i); + + {{else}} + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_COMPILING_IN_LIMITED_API + return PySequence_ITEM(o, wrapped_i); + #else + // PySequence_GetItem() handles wrap-around, but we already did above. + if (unlikely(wrapped_i < 0)) { + PyErr_SetString(PyExc_IndexError, "tuple index out of range"); + return NULL; + } + return PySequence_GetItem(o, wrapped_i); + #endif + {{endif}} + +#elif CYTHON_ASSUME_SAFE_SIZE && CYTHON_ASSUME_SAFE_MACROS + Py_ssize_t wrapped_i = i; + Py_ssize_t size = (wraparound | boundscheck) ? Py{{type}}_GET_SIZE(o) : -1; + if (wraparound & unlikely(i < 0)) { + wrapped_i += size; + } + if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, size))) { + {{if type == 'List'}} // Note that there's a minor thread-safety issue where the size for wraparound may change before we use it. // CPython doesn't worry about it and serious violations will be caught by boundschecking anyway. - return __Pyx_PyList_GetItemRefFast(o, wrapped_i, unsafe_shared); - } else - {{endif}} - if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, Py{{type}}_GET_SIZE(o)))) { - return __Pyx_NewRef(Py{{type}}_GET_ITEM(o, wrapped_i)); + return __Pyx_PyList_GET_ITEM_REF(o, wrapped_i, unsafe_shared); + {{else}} + return __Pyx_NewRef(__Pyx_PyTuple_GET_ITEM(o, wrapped_i)); + {{endif}} } - return __Pyx_GetItemInt_Generic(o, PyLong_FromSsize_t(i)); + return __Pyx_GetItemInt_Generic_size(o, i); + #else (void)wraparound; (void)boundscheck; @@ -501,11 +538,7 @@ // and using the size because Python itself doesn't either. If we have boundschecking on they'll // be caught eventually. Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); - if ((CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS)) { - return __Pyx_PyList_GetItemRefFast(o, n, unsafe_shared); - } else if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) { - return __Pyx_NewRef(PyList_GET_ITEM(o, n)); - } + return boundscheck ? __Pyx_PyList_GetItemRef(o, n) : __Pyx_PyList_GET_ITEM_REF(o, n, unsafe_shared); } else #if !CYTHON_AVOID_BORROWED_REFS if (PyTuple_CheckExact(o)) { @@ -515,6 +548,10 @@ } } else #endif +#else + if ((!wraparound || i >= 0) & PyList_CheckExact(o)) { + return boundscheck ? __Pyx_PyList_GetItemRef(o, i) : __Pyx_PyList_GET_ITEM_REF(o, i, unsafe_shared); + } else #endif #if CYTHON_USE_TYPE_SLOTS && !CYTHON_COMPILING_IN_PYPY { @@ -552,7 +589,7 @@ #endif (void)wraparound; (void)boundscheck; - return __Pyx_GetItemInt_Generic(o, PyLong_FromSsize_t(i)); + return __Pyx_GetItemInt_Generic_size(o, i); } /////////////// SetItemInt.proto /////////////// @@ -2180,7 +2217,7 @@ static CYTHON_INLINE vectorcallfunc __Pyx_PyVectorcall_Function(PyObject *callable) { PyTypeObject *tp = Py_TYPE(callable); - #if defined(__Pyx_CyFunction_USED) + #if defined(__Pyx_CyFunction_USED) && CYTHON_METH_FASTCALL if (__Pyx_CyFunction_CheckExact(callable)) { return __Pyx_CyFunction_func_vectorcall(callable); } @@ -2848,7 +2885,7 @@ #endif #define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_DefinitelyUniqueInPlace(left, right) __Pyx_PyUnicode_ConcatInPlace(left, right, __Pyx_ReferenceSharing_DefinitelyUnique) #define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_OwnStrongReferenceInPlace(left, right) __Pyx_PyUnicode_ConcatInPlace(left, right, __Pyx_ReferenceSharing_OwnStrongReference) - #define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_FunctionArgumentInPlace(left, right) __Pyx_PyUnicode_ConcatInPlace(left, right, __Pyx_ReferenceSharing_DefinitelyUnique) + #define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_FunctionArgumentInPlace(left, right) __Pyx_PyUnicode_ConcatInPlace(left, right, __Pyx_ReferenceSharing_FunctionArgument) #define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_SharedReferenceInPlace(left, right) __Pyx_PyUnicode_ConcatInPlace(left, right, __Pyx_ReferenceSharing_SharedReference) // __Pyx_PyUnicode_ConcatInPlace is slightly odd because it has the potential to modify the input // argument (but only in cases where no user should notice). Therefore, it needs to keep Cython's @@ -2932,7 +2969,8 @@ } new_len = left_len + right_len; - if (__Pyx_unicode_modifiable(left, unsafe_shared) + if (left != right + && __Pyx_unicode_modifiable(left, unsafe_shared) && PyUnicode_CheckExact(right) && PyUnicode_KIND(right) <= PyUnicode_KIND(left) // Don't resize for ascii += latin1. Convert ascii to latin1 requires diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/Cython/Utility/Optimize.c new/cython-3.2.9/Cython/Utility/Optimize.c --- old/cython-3.2.8/Cython/Utility/Optimize.c 2026-06-30 08:38:54.503277800 +0200 +++ new/cython-3.2.9/Cython/Utility/Optimize.c 2026-07-24 06:49:15.614099000 +0200 @@ -454,7 +454,7 @@ #endif if (unlikely(pos >= list_size)) return 0; *ppos = pos + 1; - next_item = __Pyx_PyList_GetItemRef(iter_obj, pos); + next_item = __Pyx_PyList_GET_ITEM_REF(iter_obj, pos, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!next_item)) return -1; } else #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/Cython/Utility/StringTools.c new/cython-3.2.9/Cython/Utility/StringTools.c --- old/cython-3.2.8/Cython/Utility/StringTools.c 2026-06-30 08:38:54.503277800 +0200 +++ new/cython-3.2.9/Cython/Utility/StringTools.c 2026-07-24 06:49:15.615099000 +0200 @@ -1232,6 +1232,7 @@ } } return __Pyx_PyByteArray_Append(bytearray, (int) ival); + bad_range: PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); return -1; @@ -1244,31 +1245,42 @@ //////////////////// ByteArrayAppend //////////////////// //@requires: ObjectHandling.c::PyObjectCallMethod1 -static CYTHON_INLINE int __Pyx_PyByteArray_Append(PyObject* bytearray, int value) { +static int __Pyx_PyByteArray_Append_fallback(PyObject* bytearray, int value) { PyObject *pyval, *retval; + pyval = PyLong_FromLong(value); + if (unlikely(!pyval)) + return -1; + retval = __Pyx_PyObject_CallMethod1(bytearray, PYIDENT("append"), pyval); + Py_DECREF(pyval); + if (unlikely(!retval)) + return -1; + Py_DECREF(retval); + return 0; +} + +static CYTHON_INLINE int __Pyx_PyByteArray_Append(PyObject* bytearray, int value) { #if CYTHON_COMPILING_IN_CPYTHON if (likely(__Pyx_is_valid_index(value, 256))) { + int retval = 1; + __Pyx_BEGIN_CRITICAL_SECTION(bytearray); Py_ssize_t n = Py_SIZE(bytearray); if (likely(n != PY_SSIZE_T_MAX)) { - if (unlikely(PyByteArray_Resize(bytearray, n + 1) < 0)) - return -1; - PyByteArray_AS_STRING(bytearray)[n] = (char) (unsigned char) value; - return 0; + retval = PyByteArray_Resize(bytearray, n + 1); + if (likely(retval == 0)) { + PyByteArray_AS_STRING(bytearray)[n] = (char) (unsigned char) value; + } + } + __Pyx_END_CRITICAL_SECTION(); + if (likely(retval != 1)) { + return retval; } } else { PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); return -1; } #endif - pyval = PyLong_FromLong(value); - if (unlikely(!pyval)) - return -1; - retval = __Pyx_PyObject_CallMethod1(bytearray, PYIDENT("append"), pyval); - Py_DECREF(pyval); - if (unlikely(!retval)) - return -1; - Py_DECREF(retval); - return 0; + + return __Pyx_PyByteArray_Append_fallback(bytearray, value); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/PKG-INFO new/cython-3.2.9/PKG-INFO --- old/cython-3.2.8/PKG-INFO 2026-06-30 08:39:03.858988500 +0200 +++ new/cython-3.2.9/PKG-INFO 2026-07-24 06:49:26.189941600 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: Cython -Version: 3.2.8 +Version: 3.2.9 Summary: The Cython compiler for writing C extensions in the Python language. Home-page: https://cython.org/ Author: Robert Bradshaw, Stefan Behnel, David Woods, Greg Ewing, et al. @@ -64,21 +64,32 @@ .. _Pyrex: https://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/ -3.2.8 (2026-06-30) +3.2.9 (2026-07-23) ================== Bugs fixed ---------- -* Assigning a Python 3.14+ ``.__annotate__`` function to a Cython compiled function no longer - evaluates annotations eagerly. Fixes a regression with ``@functools.wraps()`` in Cython 3.2.6. - Patch by Jelle Zijlstra. (Github issue https://github.com/cython/cython/issues/7767) - -* In freethreading Python, the necessary object keep-alive while executing user code in - ``.__dealloc__()`` uses a safer scheme. - Patch by Yaxing Cai. (Github issue https://github.com/cython/cython/issues/7769) +* Indexing into freshly created lists with an out-of-bounds index could crash. + (Github issue https://github.com/cython/cython/issues/7793) -* The local function state used by ``sys.monitoring`` read from uninitialised memory. - (Github issue https://github.com/cython/cython/issues/7774) +* Function arguments with default values could end up uninitialised in closures, leading to crashes. + Patch by Anthony Donlon. (Github issue https://github.com/cython/cython/issues/7782) -* The ``.ag_running`` flag attribute of async generators was always false on big-endian systems. +* ``bytearray.append(None)`` could crash. The optimised code was also lacking concurrency guards. + (Github issue https://github.com/cython/cython/issues/7796) + +* Some rare corner cases when concatenating text strings were resolved. + (Github issue https://github.com/cython/cython/issues/7799) + +* Assignments of builtin string types to typedefs of `object` could erroneously be rejected. + (Github issue https://github.com/cython/cython/issues/7789) + +* Subscripting ``type`` failed with a ``TypeError``. + (Github issue https://github.com/cython/cython/issues/5563) + +* Manually disabling ``CYTHON_VECTORCALL`` in CPython could lead to invalid C code. + Patch by Florent Gallaire. (Github issue https://github.com/cython/cython/issues/7807) + +* Some internal Limited API version checks for Py3.12 were corrected. + (Github issue https://github.com/cython/cython/issues/7845) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/tests/errors/string_assignments.pyx new/cython-3.2.9/tests/errors/string_assignments.pyx --- old/cython-3.2.8/tests/errors/string_assignments.pyx 2026-06-30 08:38:54.552277600 +0200 +++ new/cython-3.2.9/tests/errors/string_assignments.pyx 2026-07-24 06:49:15.668099000 +0200 @@ -89,6 +89,12 @@ voidptr_func(b"abc") voidptr_func(u"abc") +ctypedef object MyObject + +cdef MyObject my_obj1 = "abc" +cdef MyObject my_obj2 = b"abc" +cdef MyObject my_obj3 = u"abc" + _ERRORS = u""" 36:20: Unicode literals do not support coercion to C types other than Py_UCS4/Py_UNICODE (for characters), Py_UNICODE* (for strings) or char*/void* (for auto-encoded strings). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/tests/run/builtin_type.pyx new/cython-3.2.9/tests/run/builtin_type.pyx --- old/cython-3.2.8/tests/run/builtin_type.pyx 2026-06-30 08:38:54.559277500 +0200 +++ new/cython-3.2.9/tests/run/builtin_type.pyx 2026-07-24 06:49:15.675099000 +0200 @@ -1,5 +1,8 @@ cimport cython +import sys + + @cython.test_assert_path_exists( '//PythonCapiCallNode/PythonCapiFunctionNode[@cname="Py_TYPE"]') def get_type_of(a): @@ -51,3 +54,86 @@ TypeError: Argument 'x' has incorrect type (expected type, got object) """ return x + + +def test_exact_type_getitem(val): + """ + >>> test_exact_type_getitem(int) + type[int] + >>> test_exact_type_getitem(float) + type[float] + >>> test_exact_type_getitem(1) + type[1] + """ + return type[val] + +if sys.version_info < (3,9): + test_exact_type_getitem.__doc__ = None + + +def test_exact_type_instance_getitem1(val): + """ + >>> test_exact_type_instance_getitem1(int) # doctest: +ELLIPSIS + Traceback (most recent call last): + ... + TypeError: ... is not subscriptable + """ + return str[val] + +if sys.version_info < (3,9): + test_exact_type_instance_getitem1.__doc__ = None + + +def test_exact_type_instance_getitem2(val): + """ + >>> test_exact_type_instance_getitem2(int) + list[int] + >>> test_exact_type_instance_getitem2(1) + list[1] + """ + return list[val] + +if sys.version_info < (3,9): + test_exact_type_instance_getitem2.__doc__ = None + + +def test_maybe_type_getitem(tp, val): + """ + >>> test_maybe_type_getitem(type, int) + type[int] + >>> test_maybe_type_getitem(type, float) + type[float] + >>> test_maybe_type_getitem(type, 1) + type[1] + >>> test_maybe_type_getitem(list, int) + list[int] + >>> test_maybe_type_getitem(str, int) # doctest: +ELLIPSIS + Traceback (most recent call last): + ... + TypeError: ... is not subscriptable + """ + return tp[val] + +if sys.version_info < (3,9): + test_maybe_type_getitem.__doc__ = None + + +def test_typed_type_getitem(tp: type, val): + """ + >>> test_typed_type_getitem(type, int) + type[int] + >>> test_typed_type_getitem(type, float) + type[float] + >>> test_typed_type_getitem(type, 1) + type[1] + >>> test_typed_type_getitem(list, int) + list[int] + >>> test_typed_type_getitem(str, int) # doctest: +ELLIPSIS + Traceback (most recent call last): + ... + TypeError: ... is not subscriptable + """ + return tp[val] + +if sys.version_info < (3,9): + test_typed_type_getitem.__doc__ = None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/tests/run/bytearraymethods.pyx new/cython-3.2.9/tests/run/bytearraymethods.pyx --- old/cython-3.2.8/tests/run/bytearraymethods.pyx 2026-06-30 08:38:54.559277500 +0200 +++ new/cython-3.2.9/tests/run/bytearraymethods.pyx 2026-07-24 06:49:15.676098800 +0200 @@ -269,6 +269,17 @@ ValueError: ... >>> print(b.decode('ascii')) abcX@xy + + >>> b = bytearray(b'abc') + >>> b = bytearray_append(b, ord('x'), ord('y'), None) # doctest: +ELLIPSIS + Traceback (most recent call last): + TypeError: ... + >>> print(b.decode('ascii')) + abcX@xy + + >>> b = bytearray_append(None, ord('x'), ord('y'), b'x') # doctest: +ELLIPSIS + Traceback (most recent call last): + AttributeError: 'NoneType' object has no attribute 'append' """ assert b.append('X') is None b.append(64) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/tests/run/cdef_optional_arg_closure.pyx new/cython-3.2.9/tests/run/cdef_optional_arg_closure.pyx --- old/cython-3.2.8/tests/run/cdef_optional_arg_closure.pyx 1970-01-01 01:00:00.000000000 +0100 +++ new/cython-3.2.9/tests/run/cdef_optional_arg_closure.pyx 2026-07-24 06:49:15.678099000 +0200 @@ -0,0 +1,83 @@ +# mode: run +# tag: closures, optional_args + +# An optional (defaulted) argument of a cdef function that is captured by an +# inner function (closure) must be moved into the closure scope, just like a +# non-optional argument. Previously it was unpacked only into a C local while +# the body and the closure read the (uninitialised) scope field, which returned +# the wrong value or crashed (NULL dereference on the freelist allocation path). + + +cdef test(object register=None, object length=None): + # `length` is captured by `_on_done`, so it lives in the closure scope. + def _on_done(): + return length + return length, _on_done() + + +def run_default(): + """ + >>> run_default() + (None, None) + """ + return test(0) + + +def run_passed(): + """ + >>> run_passed() + (196883, 196883) + """ + return test(0, 196883) + + +cdef test_ctype(int register=7): + def inner(): + return (register) + return register, inner() + + +def run_ctype_default(): + """ + >>> run_ctype_default() + (7, 7) + """ + return test_ctype(7) + + +def run_ctype_passed(): + """ + >>> run_ctype_passed() + (17, 17) + """ + return test_ctype(17) + + +cdef test_multi(object device_index, object register=2, object tdi_data=3): + def inner(): + return (device_index, register, tdi_data) + return inner() + + +def run_multi_defaults(): + """ + >>> run_multi_defaults() + (1, 2, 3) + """ + return test_multi(1) + + +def run_multi_partial(): + """ + >>> run_multi_partial() + (1, 20, 3) + """ + return test_multi(1, 20) + + +def run_multi_all(): + """ + >>> run_multi_all() + (1, 20, 30) + """ + return test_multi(1, 20, 30) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/tests/run/freethreaded_list_indexing.pyx new/cython-3.2.9/tests/run/freethreaded_list_indexing.pyx --- old/cython-3.2.8/tests/run/freethreaded_list_indexing.pyx 2026-06-30 08:38:54.578277600 +0200 +++ new/cython-3.2.9/tests/run/freethreaded_list_indexing.pyx 2026-07-24 06:49:15.695098900 +0200 @@ -16,7 +16,7 @@ int wraparound, int boundscheck, int unsafe_shared); static PyObject *Call_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, int wraparound, int boundscheck, int unsafe_shared) { - int unique = (unsafe_shared == __Pyx_ReferenceSharing_DefinitelyUnique) || + int unique = (unsafe_shared == __Pyx_ReferenceSharing_DefinitelyUnique) || (unsafe_shared == __Pyx_ReferenceSharing_OwnStrongReference); unsafe_shared_set = !unique; return __Pyx_GetItemInt_List_Fast(o, i, wraparound, boundscheck, unsafe_shared); @@ -105,3 +105,27 @@ def dummy_func2(): # abuse cname feature to undefine our override to allow the utility code to be generated undef_getitemint_list_fast() + + +def temp_list_subscript(create): + """ + >>> temp_list_subscript([1,2,3].copy) + 2 + + >>> temp_list_subscript(list) # empty list, out of range + Traceback (most recent call last): + IndexError: list index out of range + """ + return create()[1] + + +def temp_list_subscript_wraparound(create): + """ + >>> temp_list_subscript_wraparound([1,2,3].copy) + 3 + + >>> temp_list_subscript_wraparound(list) # empty list, out of range + Traceback (most recent call last): + IndexError: list index out of range + """ + return create()[-1] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cython-3.2.8/tests/run/inplace.pyx new/cython-3.2.9/tests/run/inplace.pyx --- old/cython-3.2.8/tests/run/inplace.pyx 2026-06-30 08:38:54.582277500 +0200 +++ new/cython-3.2.9/tests/run/inplace.pyx 2026-07-24 06:49:15.699686300 +0200 @@ -254,3 +254,143 @@ """ value += a if condition else b return value + + +# Unicode inplace concatenation is special because it attempts to do a +# resize for uniquely referenced objects + +def unicode_concat_local(a: unicode): + """ + >>> s = "123" + >>> unicode_concat_local(s) + '123abc' + >>> s + '123' + >>> unicode_concat_local("123456") + '123456abc' + """ + local = a + local += 'abc' + return local + +def unicode_concat_unique_local(deuniquify): + """ + >>> unicode_concat_unique_local(True) + 'some string?' + >>> unicode_concat_unique_local(False) + 'some string?' + """ + a = "some string" + if deuniquify: + b = a + a += "?" + return a + + +def unicode_concat_arg(a: unicode): + """ + >>> s = "an argument" + >>> unicode_concat_arg(s) + 'an argument with some extra stuff' + >>> s + 'an argument' + >>> unicode_concat_arg('another argument') + 'another argument with some extra stuff' + """ + a += ' with some extra stuff' + return a + +def unicode_concat_arg_self(a: unicode): + """ + >>> unicode_concat_arg_self('babababababa') + 'babababababababababababa' + >>> s = '0987654321' + >>> unicode_concat_arg_self(s) + '09876543210987654321' + >>> s + '0987654321' + """ + a += a + return a + +cdef unicode global_unicode = "glglgl" + +def get_global_unicode(): + return global_unicode + +def reset_global_unicode(): + global global_unicode + global_unicode = "glglgl" + +def unicode_concat_global(): + """ + >>> unicode_concat_global() + 'glglgl xxxx' + >>> get_global_unicode() + 'glglgl xxxx' + """ + global global_unicode + global_unicode += ' xxxx' + return global_unicode + +cdef class UnicodeAttr: + cdef public unicode u + def do_concat(self): + """ + >>> inst = UnicodeAttr() + >>> inst.u = 'attr_string' + >>> inst.do_concat() + >>> inst.u + 'attr_string!' + >>> old = inst.u + >>> inst.do_concat() + >>> inst.u + 'attr_string!!' + >>> old + 'attr_string!' + """ + self.u += "!" + + def do_concat_self(self): + """ + >>> inst = UnicodeAttr() + >>> inst.u = 'attr_string' + >>> inst.do_concat_self() + >>> inst.u + 'attr_stringattr_string' + >>> old = inst.u + >>> inst.do_concat_self() + >>> inst.u + 'attr_stringattr_stringattr_stringattr_string' + >>> old + 'attr_stringattr_string' + """ + self.u += self.u + +def unicode_concat_closure(): + """ + >>> reset_global_unicode() + >>> f = unicode_concat_closure() + >>> f('get') + 'hmmmmm' + >>> f('concat') + 'hmmmmm?' + >>> f('concat') + 'hmmmmm??' + >>> f('get') + 'hmmmmm??' + >>> f = unicode_concat_closure() + >>> (old := f('get')) + 'hmmmmm' + >>> f('concat') + 'hmmmmm?' + >>> old + 'hmmmmm' + """ + s = "hmmmmm" + def cl(op): + nonlocal s + if op == 'concat': + s += '?' + return s + return cl
