Skip to content

Commit 8e10bd7

Browse files
gh-146587: fix type slot assignment incase of multiple slots for same name (#146593)
1 parent f4d3c61 commit 8e10bd7

File tree

4 files changed

+44
-7
lines changed

4 files changed

+44
-7
lines changed

Lib/test/test_descr.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5361,6 +5361,31 @@ def foo(self):
53615361
with self.assertRaisesRegex(NotImplementedError, "BAR"):
53625362
B().foo
53635363

5364+
def test_gh146587(self):
5365+
# See https://github.com/python/cpython/issues/146587
5366+
5367+
class A:
5368+
def __radd__(self, other): ...
5369+
5370+
class B(tuple): ...
5371+
5372+
self.assertIsNone(() + A())
5373+
self.assertIsNone(B() + A())
5374+
5375+
from typing import NamedTuple
5376+
5377+
class T(NamedTuple):
5378+
x: int
5379+
5380+
class A:
5381+
def __init__(self, *args):
5382+
self.lst = list(args)
5383+
def __radd__(self, other):
5384+
return A(*self.lst, other)
5385+
5386+
self.assertEqual(((1,)+A()).lst, [(1,)])
5387+
self.assertEqual((T(x=1)+A()).lst, [T(x=1)])
5388+
53645389

53655390
class DictProxyTests(unittest.TestCase):
53665391
def setUp(self):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix type slot assignment incase of multiple slots for same name in type object implementation. Patch by Kumar Aditya.

Objects/typeobject.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11601,7 +11601,7 @@ static pytype_slotdef slotdefs[] = {
1160111601
/* Stores the number of times where slotdefs has elements with same name.
1160211602
This counter precalculated by _PyType_InitSlotDefs() when the main
1160311603
interpreter starts. */
11604-
static uint8_t slotdefs_name_counts[Py_ARRAY_LENGTH(slotdefs)];
11604+
static uint8_t slotdefs_dups[Py_ARRAY_LENGTH(slotdefs)][1 + MAX_EQUIV];
1160511605

1160611606
/* Given a type pointer and an offset gotten from a slotdef entry, return a
1160711607
pointer to the actual slot. This is not quite the same as simply adding
@@ -11768,11 +11768,22 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p, pytype_slotdef **next_p,
1176811768
((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_strobj) {
1176911769
void **tptr;
1177011770
size_t index = (p - slotdefs);
11771-
if (slotdefs_name_counts[index] == 1) {
11772-
tptr = slotptr(type, p->offset);
11771+
if (slotdefs_dups[index][0] > 1) {
11772+
tptr = NULL;
11773+
for (size_t i = 1; i <= slotdefs_dups[index][0]; i++) {
11774+
pytype_slotdef *q = &slotdefs[slotdefs_dups[index][i]];
11775+
void **qptr = slotptr(type, q->offset);
11776+
if (qptr == NULL || *qptr == NULL)
11777+
continue;
11778+
if (tptr != NULL) {
11779+
tptr = NULL;
11780+
break;
11781+
}
11782+
tptr = qptr;
11783+
}
1177311784
}
1177411785
else {
11775-
tptr = NULL;
11786+
tptr = slotptr(type, offset);
1177611787
}
1177711788

1177811789
if (tptr == NULL || tptr == ptr)
@@ -12034,7 +12045,7 @@ _PyType_InitSlotDefs(PyInterpreterState *interp)
1203412045
Py_CLEAR(bytearray);
1203512046
}
1203612047

12037-
memset(slotdefs_name_counts, 0, sizeof(slotdefs_name_counts));
12048+
memset(slotdefs_dups, -1, sizeof(slotdefs_dups));
1203812049

1203912050
Py_ssize_t pos = 0;
1204012051
PyObject *key = NULL;
@@ -12044,7 +12055,7 @@ _PyType_InitSlotDefs(PyInterpreterState *interp)
1204412055
uint8_t n = data[0];
1204512056
for (uint8_t i = 0; i < n; i++) {
1204612057
uint8_t idx = data[i + 1];
12047-
slotdefs_name_counts[idx] = n;
12058+
memcpy(&slotdefs_dups[idx], data, sizeof(uint8_t) * (n + 1));
1204812059
}
1204912060
}
1205012061

Tools/c-analyzer/cpython/ignored.tsv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ Objects/obmalloc.c - obmalloc_state_initialized -
351351
Objects/typeobject.c - name_op -
352352
Objects/typeobject.c - slotdefs -
353353
# It initialized only once when main interpeter starts
354-
Objects/typeobject.c - slotdefs_name_counts -
354+
Objects/typeobject.c - slotdefs_dups -
355355
Objects/unicodeobject.c - stripfuncnames -
356356
Objects/unicodeobject.c - utf7_category -
357357
Objects/unicodeobject.c unicode_decode_call_errorhandler_wchar argparse -

0 commit comments

Comments
 (0)