mirror of
https://github.com/python/cpython.git
synced 2025-11-02 06:31:29 +00:00
[3.11] GH-99257: Check the owner's type when specializing slots (GH-99324)
(cherry picked from commit 9d69284169)
Co-authored-by: Brandt Bucher <brandtbucher@microsoft.com>
This commit is contained in:
parent
1de088ca95
commit
f9a68be673
3 changed files with 78 additions and 0 deletions
|
|
@ -177,6 +177,73 @@ def f():
|
||||||
for _ in range(1025):
|
for _ in range(1025):
|
||||||
self.assertFalse(f())
|
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):
|
class TestLoadMethodCache(unittest.TestCase):
|
||||||
def test_descriptor_added_after_optimization(self):
|
def test_descriptor_added_after_optimization(self):
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -688,6 +688,10 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
|
||||||
PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
|
PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
|
||||||
struct PyMemberDef *dmem = member->d_member;
|
struct PyMemberDef *dmem = member->d_member;
|
||||||
Py_ssize_t offset = dmem->offset;
|
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) {
|
if (dmem->flags & PY_AUDIT_READ) {
|
||||||
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_AUDITED_SLOT);
|
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_AUDITED_SLOT);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -777,6 +781,10 @@ _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
|
||||||
PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
|
PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
|
||||||
struct PyMemberDef *dmem = member->d_member;
|
struct PyMemberDef *dmem = member->d_member;
|
||||||
Py_ssize_t offset = dmem->offset;
|
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) {
|
if (dmem->flags & READONLY) {
|
||||||
SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_READ_ONLY);
|
SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_READ_ONLY);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue