Skip to content

Commit

Permalink
[3.11] GH-99257: Check the owner's type when specializing slots (GH-9…
Browse files Browse the repository at this point in the history
…9324)

(cherry picked from commit 9d69284)

Co-authored-by: Brandt Bucher <brandtbucher@microsoft.com>
  • Loading branch information
miss-islington and brandtbucher committed Nov 10, 2022
1 parent 1de088c commit f9a68be
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 0 deletions.
67 changes: 67 additions & 0 deletions Lib/test/test_opcache.py
Expand Up @@ -177,6 +177,73 @@ def f():
for _ in range(1025):
self.assertFalse(f())

def test_load_shadowing_slot_should_raise_type_error(self):
class Class:
__slots__ = ("slot",)

class Sneaky:
__slots__ = ("shadowed",)
shadowing = Class.slot

def f(o):
o.shadowing

o = Sneaky()
o.shadowed = 42

for _ in range(1025):
with self.assertRaises(TypeError):
f(o)

def test_store_shadowing_slot_should_raise_type_error(self):
class Class:
__slots__ = ("slot",)

class Sneaky:
__slots__ = ("shadowed",)
shadowing = Class.slot

def f(o):
o.shadowing = 42

o = Sneaky()

for _ in range(1025):
with self.assertRaises(TypeError):
f(o)

def test_load_borrowed_slot_should_not_crash(self):
class Class:
__slots__ = ("slot",)

class Sneaky:
borrowed = Class.slot

def f(o):
o.borrowed

o = Sneaky()

for _ in range(1025):
with self.assertRaises(TypeError):
f(o)

def test_store_borrowed_slot_should_not_crash(self):
class Class:
__slots__ = ("slot",)

class Sneaky:
borrowed = Class.slot

def f(o):
o.borrowed = 42

o = Sneaky()

for _ in range(1025):
with self.assertRaises(TypeError):
f(o)


class TestLoadMethodCache(unittest.TestCase):
def test_descriptor_added_after_optimization(self):
Expand Down
@@ -0,0 +1,3 @@
Fix an issue where member descriptors (such as those for
:attr:`~object.__slots__`) could behave incorrectly or crash instead of
raising a :exc:`TypeError` when accessed via an instance of an invalid type.
8 changes: 8 additions & 0 deletions Python/specialize.c
Expand Up @@ -688,6 +688,10 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
struct PyMemberDef *dmem = member->d_member;
Py_ssize_t offset = dmem->offset;
if (!PyObject_TypeCheck(owner, member->d_common.d_type)) {
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
goto fail;
}
if (dmem->flags & PY_AUDIT_READ) {
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_AUDITED_SLOT);
goto fail;
Expand Down Expand Up @@ -777,6 +781,10 @@ _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
struct PyMemberDef *dmem = member->d_member;
Py_ssize_t offset = dmem->offset;
if (!PyObject_TypeCheck(owner, member->d_common.d_type)) {
SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_EXPECTED_ERROR);
goto fail;
}
if (dmem->flags & READONLY) {
SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_READ_ONLY);
goto fail;
Expand Down

0 comments on commit f9a68be

Please sign in to comment.