From 28f5e80cde9fd16f30f120c300d893bfb4a33ff8 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Thu, 5 Nov 2026 11:57:25 +0300 Subject: [PATCH 1/3] gh-161389: Fix crash when passing invalid `flags` and `traps` to `decimal.Context` --- Lib/test/test_decimal.py | 14 ++++++++++++++ .../2026-11-05-11-56-50.gh-issue-161389.EIl2E6.rst | 2 ++ Modules/_decimal/_decimal.c | 6 ++++++ 3 files changed, 22 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-11-05-11-56-50.gh-issue-161389.EIl2E6.rst diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index d049646d6e8b55a..e81953ddd8c5874 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -3763,6 +3763,20 @@ def test_to_integral_value(self): self.assertRaises(TypeError, c.to_integral_value, '10') self.assertRaises(TypeError, c.to_integral_value, 10, 'x') + def test_invalid_signal_dict_flags(self): + # gh-161389 + Context = self.decimal.Context + SignalDict = type(Context().traps) + with self.assertRaisesRegex((KeyError, ValueError), "signal dict"): + Context(traps=SignalDict()) + + def test_invalid_signal_dict_flags(self): + # gh-161389 + Context = self.decimal.Context + SignalDict = type(Context().flags) + with self.assertRaisesRegex((KeyError, ValueError), "signal dict"): + Context(flags=SignalDict()) + @requires_cdecimal class CContextAPItests(ContextAPItests, unittest.TestCase): decimal = C diff --git a/Misc/NEWS.d/next/Library/2026-11-05-11-56-50.gh-issue-161389.EIl2E6.rst b/Misc/NEWS.d/next/Library/2026-11-05-11-56-50.gh-issue-161389.EIl2E6.rst new file mode 100644 index 000000000000000..62fd6fe712f6dfc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-11-05-11-56-50.gh-issue-161389.EIl2E6.rst @@ -0,0 +1,2 @@ +Fixes a crash in :class:`decimal.Context` when passing invalid signaling +dicts as *flags* and *traps*. diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 4849b447e277bfc..098522b130ec874 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -1162,6 +1162,9 @@ context_settraps_dict(PyObject *self, PyObject *value) decimal_state *state = get_module_state_from_ctx(self); if (PyDecSignalDict_Check(state, value)) { + if (SdFlagAddr(value) == NULL) { + return value_error_int(INVALID_SIGNALDICT_ERROR_MSG); + } flags = SdFlags(value); } else { @@ -1228,6 +1231,9 @@ context_setstatus_dict(PyObject *self, PyObject *value) decimal_state *state = get_module_state_from_ctx(self); if (PyDecSignalDict_Check(state, value)) { + if (SdFlagAddr(value) == NULL) { + return value_error_int(INVALID_SIGNALDICT_ERROR_MSG); + } flags = SdFlags(value); } else { From 39ddbb09567a542fb68c44f75ce3fdcdecb2b9f9 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Thu, 5 Nov 2026 12:36:25 +0300 Subject: [PATCH 2/3] Fix CI --- Lib/test/test_decimal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index e81953ddd8c5874..a66010c6d052707 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -3763,14 +3763,14 @@ def test_to_integral_value(self): self.assertRaises(TypeError, c.to_integral_value, '10') self.assertRaises(TypeError, c.to_integral_value, 10, 'x') - def test_invalid_signal_dict_flags(self): + def test_crashing_signal_dict_flags(self): # gh-161389 Context = self.decimal.Context SignalDict = type(Context().traps) with self.assertRaisesRegex((KeyError, ValueError), "signal dict"): Context(traps=SignalDict()) - def test_invalid_signal_dict_flags(self): + def test_crashing_signal_dict_flags(self): # gh-161389 Context = self.decimal.Context SignalDict = type(Context().flags) From 4aaf4d4943bdb836fd726582c1b6c16ae615457e Mon Sep 17 00:00:00 2001 From: sobolevn Date: Thu, 5 Nov 2026 12:42:16 +0300 Subject: [PATCH 3/3] Fix CI --- Lib/test/test_decimal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index a66010c6d052707..c4b24617af7c433 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -3763,7 +3763,7 @@ def test_to_integral_value(self): self.assertRaises(TypeError, c.to_integral_value, '10') self.assertRaises(TypeError, c.to_integral_value, 10, 'x') - def test_crashing_signal_dict_flags(self): + def test_crashing_signal_dict_traps(self): # gh-161389 Context = self.decimal.Context SignalDict = type(Context().traps)