Skip to content

Commit 29f6dc6

Browse files
authored
pythonGH-133932: Tagged ints are heap safe (pythonGH-134244)
1 parent 1f0a294 commit 29f6dc6

File tree

1 file changed

+7
-13
lines changed

1 file changed

+7
-13
lines changed

Include/internal/pycore_stackref.h

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ PyStackRef_IsNullOrInt(_PyStackRef ref);
238238
#else
239239

240240
#define Py_INT_TAG 3
241+
#define Py_TAG_REFCNT 1
241242

242243
static inline bool
243244
PyStackRef_IsTaggedInt(_PyStackRef i)
@@ -263,7 +264,7 @@ PyStackRef_UntagInt(_PyStackRef i)
263264

264265
#ifdef Py_GIL_DISABLED
265266

266-
#define Py_TAG_DEFERRED (1)
267+
#define Py_TAG_DEFERRED Py_TAG_REFCNT
267268

268269
#define Py_TAG_PTR ((uintptr_t)0)
269270
#define Py_TAG_BITS ((uintptr_t)1)
@@ -441,14 +442,13 @@ PyStackRef_AsStrongReference(_PyStackRef stackref)
441442
/* References to immortal objects always have their tag bit set to Py_TAG_REFCNT
442443
* as they can (must) have their reclamation deferred */
443444

444-
#define Py_TAG_BITS 1
445-
#define Py_TAG_REFCNT 1
445+
#define Py_TAG_BITS 3
446446
#if _Py_IMMORTAL_FLAGS != Py_TAG_REFCNT
447447
# error "_Py_IMMORTAL_FLAGS != Py_TAG_REFCNT"
448448
#endif
449449

450450
#define BITS_TO_PTR(REF) ((PyObject *)((REF).bits))
451-
#define BITS_TO_PTR_MASKED(REF) ((PyObject *)(((REF).bits) & (~Py_TAG_BITS)))
451+
#define BITS_TO_PTR_MASKED(REF) ((PyObject *)(((REF).bits) & (~Py_TAG_REFCNT)))
452452

453453
#define PyStackRef_NULL_BITS Py_TAG_REFCNT
454454
static const _PyStackRef PyStackRef_NULL = { .bits = PyStackRef_NULL_BITS };
@@ -528,7 +528,7 @@ PyStackRef_FromPyObjectSteal(PyObject *obj)
528528
{
529529
assert(obj != NULL);
530530
#if SIZEOF_VOID_P > 4
531-
unsigned int tag = obj->ob_flags & Py_TAG_BITS;
531+
unsigned int tag = obj->ob_flags & Py_TAG_REFCNT;
532532
#else
533533
unsigned int tag = _Py_IsImmortal(obj) ? Py_TAG_REFCNT : 0;
534534
#endif
@@ -547,12 +547,6 @@ PyStackRef_FromPyObjectStealMortal(PyObject *obj)
547547
return ref;
548548
}
549549

550-
// Check if a stackref is exactly the same as another stackref, including the
551-
// the deferred bit. This can only be used safely if you know that the deferred
552-
// bits of `a` and `b` match.
553-
#define PyStackRef_IsExactly(a, b) \
554-
(assert(((a).bits & Py_TAG_BITS) == ((b).bits & Py_TAG_BITS)), (a).bits == (b).bits)
555-
556550
static inline _PyStackRef
557551
_PyStackRef_FromPyObjectNew(PyObject *obj)
558552
{
@@ -604,7 +598,7 @@ PyStackRef_DUP(_PyStackRef ref)
604598
static inline bool
605599
PyStackRef_IsHeapSafe(_PyStackRef ref)
606600
{
607-
return (ref.bits & Py_TAG_BITS) == 0 || ref.bits == PyStackRef_NULL_BITS || _Py_IsImmortal(BITS_TO_PTR_MASKED(ref));
601+
return (ref.bits & Py_TAG_BITS) != Py_TAG_REFCNT || ref.bits == PyStackRef_NULL_BITS || _Py_IsImmortal(BITS_TO_PTR_MASKED(ref));
608602
}
609603

610604
static inline _PyStackRef
@@ -679,7 +673,7 @@ PyStackRef_XCLOSE(_PyStackRef ref)
679673

680674
// Note: this is a macro because MSVC (Windows) has trouble inlining it.
681675

682-
#define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_BITS)) == ((b).bits & (~Py_TAG_BITS)))
676+
#define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_REFCNT)) == ((b).bits & (~Py_TAG_REFCNT)))
683677

684678

685679
#endif // !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy