gh-102304: Fix Py_INCREF() stable ABI in debug mode (#104763)

When Python is built in debug mode (if the Py_REF_DEBUG macro is
defined), the Py_INCREF() and Py_DECREF() function are now always
implemented as opaque functions to avoid leaking implementation
details like the "_Py_RefTotal" variable or the
_Py_DecRefTotal_DO_NOT_USE_THIS() function.

* Remove _Py_IncRefTotal_DO_NOT_USE_THIS() and
  _Py_DecRefTotal_DO_NOT_USE_THIS() from the stable ABI.
* Remove _Py_NegativeRefcount() from limited C API.
This commit is contained in:
Victor Stinner 2023-06-06 11:15:09 +02:00 committed by GitHub
parent bae415ad02
commit 92022d8416
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 17 additions and 27 deletions

View File

@ -343,6 +343,15 @@ Build Changes
:file:`!configure`. :file:`!configure`.
(Contributed by Christian Heimes in :gh:`89886`.) (Contributed by Christian Heimes in :gh:`89886`.)
* C extensions built with the :ref:`limited C API <limited-c-api>`
on :ref:`Python build in debug mode <debug-build>` no longer support Python
3.9 and older. In this configuration, :c:func:`Py_INCREF` and
:c:func:`Py_DECREF` are now always implemented as opaque function calls,
but the called functions were added to Python 3.10. Build C extensions
with a release build of Python or with Python 3.12 and older, to keep support
for Python 3.9 and older.
(Contributed by Victor Stinner in :gh:`102304`.)
C API Changes C API Changes
============= =============

View File

@ -585,20 +585,14 @@ decision that's up to the implementer of each new type so if you want,
you can count such references to the type object.) you can count such references to the type object.)
*/ */
#ifdef Py_REF_DEBUG #if defined(Py_REF_DEBUG) && !defined(Py_LIMITED_API)
# if defined(Py_LIMITED_API) && Py_LIMITED_API+0 < 0x030A0000 PyAPI_FUNC(void) _Py_NegativeRefcount(const char *filename, int lineno,
extern Py_ssize_t _Py_RefTotal; PyObject *op);
# define _Py_INC_REFTOTAL() _Py_RefTotal++
# define _Py_DEC_REFTOTAL() _Py_RefTotal--
# elif !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030C0000
PyAPI_FUNC(void) _Py_IncRefTotal_DO_NOT_USE_THIS(void); PyAPI_FUNC(void) _Py_IncRefTotal_DO_NOT_USE_THIS(void);
PyAPI_FUNC(void) _Py_DecRefTotal_DO_NOT_USE_THIS(void); PyAPI_FUNC(void) _Py_DecRefTotal_DO_NOT_USE_THIS(void);
# define _Py_INC_REFTOTAL() _Py_IncRefTotal_DO_NOT_USE_THIS() # define _Py_INC_REFTOTAL() _Py_IncRefTotal_DO_NOT_USE_THIS()
# define _Py_DEC_REFTOTAL() _Py_DecRefTotal_DO_NOT_USE_THIS() # define _Py_DEC_REFTOTAL() _Py_DecRefTotal_DO_NOT_USE_THIS()
# endif #endif // Py_REF_DEBUG && !Py_LIMITED_API
PyAPI_FUNC(void) _Py_NegativeRefcount(const char *filename, int lineno,
PyObject *op);
#endif /* Py_REF_DEBUG */
PyAPI_FUNC(void) _Py_Dealloc(PyObject *); PyAPI_FUNC(void) _Py_Dealloc(PyObject *);
@ -616,8 +610,8 @@ PyAPI_FUNC(void) _Py_DecRef(PyObject *);
static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op) static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
{ {
#if defined(Py_REF_DEBUG) && defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000 #if defined(Py_REF_DEBUG) && defined(Py_LIMITED_API)
// Stable ABI for Python 3.10 built in debug mode. // Stable ABI for Python built in debug mode
_Py_IncRef(op); _Py_IncRef(op);
#else #else
// Non-limited C API and limited C API for Python 3.9 and older access // Non-limited C API and limited C API for Python 3.9 and older access
@ -647,8 +641,8 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
# define Py_INCREF(op) Py_INCREF(_PyObject_CAST(op)) # define Py_INCREF(op) Py_INCREF(_PyObject_CAST(op))
#endif #endif
#if defined(Py_REF_DEBUG) && defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000 #if defined(Py_REF_DEBUG) && defined(Py_LIMITED_API)
// Stable ABI for limited C API version 3.10 of Python debug build // Stable ABI for Python built in debug mode
static inline void Py_DECREF(PyObject *op) { static inline void Py_DECREF(PyObject *op) {
_Py_DecRef(op); _Py_DecRef(op);
} }

View File

@ -917,8 +917,6 @@ if feature_macros['PY_HAVE_THREAD_NATIVE_ID']:
) )
if feature_macros['Py_REF_DEBUG']: if feature_macros['Py_REF_DEBUG']:
SYMBOL_NAMES += ( SYMBOL_NAMES += (
'_Py_DecRefTotal_DO_NOT_USE_THIS',
'_Py_IncRefTotal_DO_NOT_USE_THIS',
'_Py_NegativeRefcount', '_Py_NegativeRefcount',
'_Py_RefTotal', '_Py_RefTotal',
) )

View File

@ -2428,12 +2428,3 @@
added = '3.12' added = '3.12'
[const.Py_TPFLAGS_ITEMS_AT_END] [const.Py_TPFLAGS_ITEMS_AT_END]
added = '3.12' added = '3.12'
[function._Py_IncRefTotal_DO_NOT_USE_THIS]
added = '3.12'
ifdef = 'Py_REF_DEBUG'
abi_only = true
[function._Py_DecRefTotal_DO_NOT_USE_THIS]
added = '3.12'
ifdef = 'Py_REF_DEBUG'
abi_only = true

2
PC/python3dll.c generated
View File

@ -17,9 +17,7 @@ EXPORT_FUNC(_Py_BuildValue_SizeT)
EXPORT_FUNC(_Py_CheckRecursiveCall) EXPORT_FUNC(_Py_CheckRecursiveCall)
EXPORT_FUNC(_Py_Dealloc) EXPORT_FUNC(_Py_Dealloc)
EXPORT_FUNC(_Py_DecRef) EXPORT_FUNC(_Py_DecRef)
EXPORT_FUNC(_Py_DecRefTotal_DO_NOT_USE_THIS)
EXPORT_FUNC(_Py_IncRef) EXPORT_FUNC(_Py_IncRef)
EXPORT_FUNC(_Py_IncRefTotal_DO_NOT_USE_THIS)
EXPORT_FUNC(_Py_NegativeRefcount) EXPORT_FUNC(_Py_NegativeRefcount)
EXPORT_FUNC(_Py_VaBuildValue_SizeT) EXPORT_FUNC(_Py_VaBuildValue_SizeT)
EXPORT_FUNC(_PyArg_Parse_SizeT) EXPORT_FUNC(_PyArg_Parse_SizeT)