https://github.com/python/cpython/commit/0e8b607a3aee3074d81de9bddabfa1383199f2ed
commit: 0e8b607a3aee3074d81de9bddabfa1383199f2ed
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: vstinner <[email protected]>
date: 2026-07-24T14:15:18Z
summary:

[3.14] gh-146011: Fix use-after-free in `signaldict_repr` after deletion 
(GH-153784) (#154600)

gh-146011: Fix use-after-free in `signaldict_repr` after deletion (GH-153784)
(cherry picked from commit 41a087acc2d04c5bc3db93b5367456f05ae400a4)

Co-authored-by: Brij Kapadia <[email protected]>
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Victor Stinner <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-07-15-21-56-40.gh-issue-146011.nWmHif.rst
M Lib/test/test_decimal.py
M Modules/_decimal/_decimal.c

diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py
index c621b7ac08c3ac0..7e3896ed34e7bae 100644
--- a/Lib/test/test_decimal.py
+++ b/Lib/test/test_decimal.py
@@ -4142,6 +4142,15 @@ def test_float_operation_default(self):
 @requires_cdecimal
 class CContextFlags(ContextFlags, unittest.TestCase):
     decimal = C
+
+    def test_signaldict_repr(self):
+        Context = self.decimal.Context
+        ctx = Context(prec=7)
+        mapping = ctx.flags
+        del ctx
+        with self.assertRaisesRegex(ValueError, 'invalid signal dict'):
+            repr(mapping)
+
 class PyContextFlags(ContextFlags, unittest.TestCase):
     decimal = P
 
diff --git 
a/Misc/NEWS.d/next/Library/2026-07-15-21-56-40.gh-issue-146011.nWmHif.rst 
b/Misc/NEWS.d/next/Library/2026-07-15-21-56-40.gh-issue-146011.nWmHif.rst
new file mode 100644
index 000000000000000..0cac0257040bd6b
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-07-15-21-56-40.gh-issue-146011.nWmHif.rst
@@ -0,0 +1,2 @@
+Fix a heap-use-after-free in the C implementation of :mod:`decimal`
+when calling :func:`repr` after deleting the :class:`~decimal.Context`.
diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c
index a7f12e1b291e0ec..bead9b99309bddf 100644
--- a/Modules/_decimal/_decimal.c
+++ b/Modules/_decimal/_decimal.c
@@ -1452,6 +1452,20 @@ static int
 context_clear(PyObject *op)
 {
     PyDecContextObject *self = _PyDecContextObject_CAST(op);
+    /* Since traps and flags hold a borrowed reference to the
+       flags stored in the context object, these references need
+       to be cleared when the context object is deallocated
+       because traps and flags can survive. See gh-146011. */
+    PyDecSignalDictObject *traps = _PyDecSignalDictObject_CAST(self->traps);
+    PyDecSignalDictObject *flags = _PyDecSignalDictObject_CAST(self->flags);
+
+    if (traps != NULL) {
+        traps->flags = NULL;
+    }
+    if (flags != NULL) {
+        flags->flags = NULL;
+    }
+
     Py_CLEAR(self->traps);
     Py_CLEAR(self->flags);
     return 0;

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to