Skip to content

Commit

Permalink
gh-91051: fix segfault when using all 8 type watchers (#107853)
Browse files Browse the repository at this point in the history
  • Loading branch information
carljm authored Aug 11, 2023
1 parent 04cc014 commit 66e4edd
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 4 deletions.
4 changes: 2 additions & 2 deletions Doc/c-api/typeobj.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion Doc/includes/typestruct.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
2 changes: 1 addition & 1 deletion Include/cpython/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions Lib/test/test_capi/test_watchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,18 @@ class C2: pass
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"):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix abort / segfault when using all eight type watcher slots, on platforms
where ``char`` is signed by default.

0 comments on commit 66e4edd

Please sign in to comment.