[Python-checkins] [3.11] GH-99257: Check the owner's type when specializing slots (GH-99324)
brandtbucher
webhook-mailer at python.org
Thu Nov 10 11:45:14 EST 2022
https://github.com/python/cpython/commit/f9a68be6733fba8b5003119445b08dedace9367e
commit: f9a68be6733fba8b5003119445b08dedace9367e
branch: 3.11
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: brandtbucher <brandtbucher at gmail.com>
date: 2022-11-10T08:44:49-08:00
summary:
[3.11] GH-99257: Check the owner's type when specializing slots (GH-99324)
(cherry picked from commit 9d692841691590c25e6cf5b2250a594d3bf54825)
Co-authored-by: Brandt Bucher <brandtbucher at microsoft.com>
files:
A Misc/NEWS.d/next/Core and Builtins/2022-10-21-11-28-53.gh-issue-99257.nmcuf-.rst
M Lib/test/test_opcache.py
M Python/specialize.c
diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py
index 5c032d59b13f..e39b72606248 100644
--- a/Lib/test/test_opcache.py
+++ b/Lib/test/test_opcache.py
@@ -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):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-10-21-11-28-53.gh-issue-99257.nmcuf-.rst b/Misc/NEWS.d/next/Core and Builtins/2022-10-21-11-28-53.gh-issue-99257.nmcuf-.rst
new file mode 100644
index 000000000000..e8de568e8528
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-10-21-11-28-53.gh-issue-99257.nmcuf-.rst
@@ -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.
diff --git a/Python/specialize.c b/Python/specialize.c
index b318cb5742fa..08ce2f5caa6b 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -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;
@@ -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;
More information about the Python-checkins
mailing list