From d14c22982753a7d48d5b38308bf135f7a943f0de Mon Sep 17 00:00:00 2001 From: Brij <97006829+brijkapadia@users.noreply.github.com> Date: Wed, 15 Jul 2026 17:48:48 -0400 Subject: [PATCH 1/3] gh-146011: Fix use-after-free in `signaldict_repr` after deletion --- Lib/test/test_decimal.py | 9 +++++++++ Modules/_decimal/_decimal.c | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index a04ed0c83c07c4a..e261fee4d875d7d 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -4147,6 +4147,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.assertRaises(ValueError): + repr(mapping) + class PyContextFlags(ContextFlags, unittest.TestCase): decimal = P diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index dc1b3c06bed9521..2fce263cf107e3c 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -1499,6 +1499,10 @@ static int context_clear(PyObject *op) { PyDecContextObject *self = _PyDecContextObject_CAST(op); + PyDecSignalDictObject *traps = _PyDecSignalDictObject_CAST(self->traps); + PyDecSignalDictObject *flags = _PyDecSignalDictObject_CAST(self->flags); + traps->flags = NULL; + flags->flags = NULL; Py_CLEAR(self->traps); Py_CLEAR(self->flags); return 0; From 423628a03a6e86a27cdfbc5d415e4ed9aa190b17 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 21:56:42 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2026-07-15-21-56-40.gh-issue-146011.nWmHif.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-07-15-21-56-40.gh-issue-146011.nWmHif.rst 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..88f4e39011baa75 --- /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`. From 35185dcb507726514fbf77871946e741043094e4 Mon Sep 17 00:00:00 2001 From: Brij <97006829+brijkapadia@users.noreply.github.com> Date: Wed, 15 Jul 2026 18:08:37 -0400 Subject: [PATCH 3/3] fix segv --- .../2026-07-15-21-56-40.gh-issue-146011.nWmHif.rst | 2 +- Modules/_decimal/_decimal.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) 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 index 88f4e39011baa75..0cac0257040bd6b 100644 --- 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 @@ -1,2 +1,2 @@ -Fix a heap-use-after-free in the C implementation of :mod:`decimal` +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 2fce263cf107e3c..05d00acfe89bc72 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -1501,8 +1501,14 @@ context_clear(PyObject *op) PyDecContextObject *self = _PyDecContextObject_CAST(op); PyDecSignalDictObject *traps = _PyDecSignalDictObject_CAST(self->traps); PyDecSignalDictObject *flags = _PyDecSignalDictObject_CAST(self->flags); - traps->flags = NULL; - flags->flags = NULL; + + if (traps != NULL) { + traps->flags = NULL; + } + if (flags != NULL) { + flags->flags = NULL; + } + Py_CLEAR(self->traps); Py_CLEAR(self->flags); return 0;