summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarl Meyer <carl@oddbird.net>2023-08-11 18:42:26 (GMT)
committerGitHub <noreply@github.com>2023-08-11 18:42:26 (GMT)
commit66e4edd7346b1cd65ddff6da890a0d725e325116 (patch)
treec26d1da58d8aafa684603980090cba4c74cb329e
parent04cc01453db2f0af72a06440831637f8bf512daf (diff)
downloadcpython-66e4edd7346b1cd65ddff6da890a0d725e325116.zip
cpython-66e4edd7346b1cd65ddff6da890a0d725e325116.tar.gz
cpython-66e4edd7346b1cd65ddff6da890a0d725e325116.tar.bz2
gh-91051: fix segfault when using all 8 type watchers (#107853)
-rw-r--r--Doc/c-api/typeobj.rst4
-rw-r--r--Doc/includes/typestruct.h2
-rw-r--r--Include/cpython/object.h2
-rw-r--r--Lib/test/test_capi/test_watchers.py12
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-08-10-17-36-27.gh-issue-91051.LfaeNW.rst2
5 files changed, 18 insertions, 4 deletions
diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst
index 221a05b..faa183e 100644
--- a/Doc/c-api/typeobj.rst
+++ b/Doc/c-api/typeobj.rst
@@ -147,7 +147,7 @@ Quick Reference
+------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
| :c:member:`~PyTypeObject.tp_vectorcall` | :c:type:`vectorcallfunc` | | | | | |
+------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
- | [:c:member:`~PyTypeObject.tp_watched`] | char | | | | | |
+ | [:c:member:`~PyTypeObject.tp_watched`] | unsigned char | | | | | |
+------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
.. [#slots]
@@ -2141,7 +2141,7 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. versionadded:: 3.9 (the field exists since 3.8 but it's only used since 3.9)
-.. c:member:: char PyTypeObject.tp_watched
+.. c:member:: unsigned char PyTypeObject.tp_watched
Internal. Do not use.
diff --git a/Doc/includes/typestruct.h b/Doc/includes/typestruct.h
index f0ad1e4..ec939c2 100644
--- a/Doc/includes/typestruct.h
+++ b/Doc/includes/typestruct.h
@@ -82,5 +82,5 @@ typedef struct _typeobject {
vectorcallfunc tp_vectorcall;
/* bitset of which type-watchers care about this type */
- char tp_watched;
+ unsigned char tp_watched;
} PyTypeObject;
diff --git a/Include/cpython/object.h b/Include/cpython/object.h
index fd45fa5..5f8b1f7 100644
--- a/Include/cpython/object.h
+++ b/Include/cpython/object.h
@@ -227,7 +227,7 @@ struct _typeobject {
vectorcallfunc tp_vectorcall;
/* bitset of which type-watchers care about this type */
- char tp_watched;
+ unsigned char tp_watched;
};
/* This struct is used by the specializer
diff --git a/Lib/test/test_capi/test_watchers.py b/Lib/test/test_capi/test_watchers.py
index 93f6ef7..10b76e1 100644
--- a/Lib/test/test_capi/test_watchers.py
+++ b/Lib/test/test_capi/test_watchers.py
@@ -294,6 +294,18 @@ class TestTypeWatchers(unittest.TestCase):
C2.hmm = "baz"
self.assert_events([C1, [C2]])
+ def test_all_watchers(self):
+ class C: pass
+ with ExitStack() as stack:
+ last_wid = -1
+ # don't make assumptions about how many watchers are already
+ # registered, just go until we reach the max ID
+ while last_wid < self.TYPE_MAX_WATCHERS - 1:
+ last_wid = stack.enter_context(self.watcher())
+ self.watch(last_wid, C)
+ C.foo = "bar"
+ self.assert_events([C])
+
def test_watch_non_type(self):
with self.watcher() as wid:
with self.assertRaisesRegex(ValueError, r"Cannot watch non-type"):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-08-10-17-36-27.gh-issue-91051.LfaeNW.rst b/Misc/NEWS.d/next/Core and Builtins/2023-08-10-17-36-27.gh-issue-91051.LfaeNW.rst
new file mode 100644
index 0000000..b4b90ad
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-08-10-17-36-27.gh-issue-91051.LfaeNW.rst
@@ -0,0 +1,2 @@
+Fix abort / segfault when using all eight type watcher slots, on platforms
+where ``char`` is signed by default.