From 0e8b607a3aee3074d81de9bddabfa1383199f2ed Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Fri, 24 Jul 2026 16:15:18 +0200 Subject: [PATCH] [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 <97006829+brijkapadia@users.noreply.github.com> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Victor Stinner --- Lib/test/test_decimal.py | 9 +++++++++ .../2026-07-15-21-56-40.gh-issue-146011.nWmHif.rst | 2 ++ Modules/_decimal/_decimal.c | 14 ++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-07-15-21-56-40.gh-issue-146011.nWmHif.rst diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index c621b7ac08c3..7e3896ed34e7 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -4142,6 +4142,15 @@ class ContextFlags: @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 000000000000..0cac0257040b --- /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 a7f12e1b291e..bead9b99309b 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; -- 2.47.3