From 21c6868e10470d78c86f11464a7e99719aee3383 Mon Sep 17 00:00:00 2001 From: Charlie Zhao Date: Sun, 30 Jul 2023 16:28:54 +0800 Subject: [PATCH 1/2] gh-106263: Fix segfault in `signaldict_repr` in `_decimal` module (#106270) Co-authored-by: sunmy2019 <59365878+sunmy2019@users.noreply.github.com> (cherry picked from commit 3979150a0d406707f6d253d7c15fb32c1e005a77) --- Lib/test/test_decimal.py | 30 +++++++++++++++++++ ...-06-30-16-42-44.gh-issue-106263.tk-t93.rst | 2 ++ Modules/_decimal/_decimal.c | 30 +++++++++++++++++-- Tools/c-analyzer/cpython/ignored.tsv | 1 + 4 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-06-30-16-42-44.gh-issue-106263.tk-t93.rst diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index 749496e3e9455e..d0ba34803c21e6 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -5682,6 +5682,36 @@ def test_maxcontext_exact_arith(self): self.assertEqual(Decimal(400) ** -1, Decimal('0.0025')) + def test_c_signaldict_segfault(self): + # See gh-106263 for details. + SignalDict = type(C.Context().flags) + sd = SignalDict() + err_msg = "invalid signal dict" + + with self.assertRaisesRegex(ValueError, err_msg): + len(sd) + + with self.assertRaisesRegex(ValueError, err_msg): + iter(sd) + + with self.assertRaisesRegex(ValueError, err_msg): + repr(sd) + + with self.assertRaisesRegex(ValueError, err_msg): + sd[C.InvalidOperation] = True + + with self.assertRaisesRegex(ValueError, err_msg): + sd[C.InvalidOperation] + + with self.assertRaisesRegex(ValueError, err_msg): + sd == C.Context().flags + + with self.assertRaisesRegex(ValueError, err_msg): + C.Context().flags == sd + + with self.assertRaisesRegex(ValueError, err_msg): + sd.copy() + @requires_docstrings @requires_cdecimal class SignatureTest(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2023-06-30-16-42-44.gh-issue-106263.tk-t93.rst b/Misc/NEWS.d/next/Library/2023-06-30-16-42-44.gh-issue-106263.tk-t93.rst new file mode 100644 index 00000000000000..23763818d84ba5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-06-30-16-42-44.gh-issue-106263.tk-t93.rst @@ -0,0 +1,2 @@ +Fix crash when calling ``repr`` with a manually constructed SignalDict object. +Patch by Charlie Zhao. \ No newline at end of file diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 5cacdca3f44baa..a97490d48c90ac 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -247,14 +247,12 @@ value_error_int(const char *mesg) return -1; } -#ifdef CONFIG_32 static PyObject * value_error_ptr(const char *mesg) { PyErr_SetString(PyExc_ValueError, mesg); return NULL; } -#endif static int type_error_int(const char *mesg) @@ -541,6 +539,8 @@ getround(PyObject *v) initialized to new SignalDicts. Once a SignalDict is tied to a context, it cannot be deleted. */ +static const char *INVALID_SIGNALDICT_ERROR_MSG = "invalid signal dict"; + static int signaldict_init(PyObject *self, PyObject *args UNUSED, PyObject *kwds UNUSED) { @@ -549,8 +549,11 @@ signaldict_init(PyObject *self, PyObject *args UNUSED, PyObject *kwds UNUSED) } static Py_ssize_t -signaldict_len(PyObject *self UNUSED) +signaldict_len(PyObject *self) { + if (SdFlagAddr(self) == NULL) { + return value_error_int(INVALID_SIGNALDICT_ERROR_MSG); + } return SIGNAL_MAP_LEN; } @@ -558,6 +561,9 @@ static PyObject *SignalTuple; static PyObject * signaldict_iter(PyObject *self UNUSED) { + if (SdFlagAddr(self) == NULL) { + return value_error_ptr(INVALID_SIGNALDICT_ERROR_MSG); + } return PyTuple_Type.tp_iter(SignalTuple); } @@ -565,6 +571,9 @@ static PyObject * signaldict_getitem(PyObject *self, PyObject *key) { uint32_t flag; + if (SdFlagAddr(self) == NULL) { + return value_error_ptr(INVALID_SIGNALDICT_ERROR_MSG); + } flag = exception_as_flag(key); if (flag & DEC_ERRORS) { @@ -580,6 +589,10 @@ signaldict_setitem(PyObject *self, PyObject *key, PyObject *value) uint32_t flag; int x; + if (SdFlagAddr(self) == NULL) { + return value_error_int(INVALID_SIGNALDICT_ERROR_MSG); + } + if (value == NULL) { return value_error_int("signal keys cannot be deleted"); } @@ -612,6 +625,10 @@ signaldict_repr(PyObject *self) const char *b[SIGNAL_MAP_LEN]; /* bool */ int i; + if (SdFlagAddr(self) == NULL) { + return value_error_ptr(INVALID_SIGNALDICT_ERROR_MSG); + } + assert(SIGNAL_MAP_LEN == 9); for (cm=signal_map, i=0; cm->name != NULL; cm++, i++) { @@ -634,6 +651,10 @@ signaldict_richcompare(PyObject *v, PyObject *w, int op) assert(PyDecSignalDict_Check(v)); + if ((SdFlagAddr(v) == NULL) || (SdFlagAddr(w) == NULL)) { + return value_error_ptr(INVALID_SIGNALDICT_ERROR_MSG); + } + if (op == Py_EQ || op == Py_NE) { if (PyDecSignalDict_Check(w)) { res = (SdFlags(v)==SdFlags(w)) ^ (op==Py_NE) ? Py_True : Py_False; @@ -662,6 +683,9 @@ signaldict_richcompare(PyObject *v, PyObject *w, int op) static PyObject * signaldict_copy(PyObject *self, PyObject *args UNUSED) { + if (SdFlagAddr(self) == NULL) { + return value_error_ptr(INVALID_SIGNALDICT_ERROR_MSG); + } return flags_as_dict(SdFlags(self)); } diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index 63d0695bfb4a6e..6e4f1c4046398c 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -1432,6 +1432,7 @@ Modules/_decimal/_decimal.c - invalid_rounding_err - Modules/_decimal/_decimal.c - invalid_signals_err - Modules/_decimal/_decimal.c - signal_map - Modules/_decimal/_decimal.c - ssize_constants - +Modules/_decimal/_decimal.c - INVALID_SIGNALDICT_ERROR_MSG - Modules/_elementtree.c - ExpatMemoryHandler - Modules/_io/_iomodule.c - static_types - Modules/_io/textio.c - encodefuncs - From f64da19b6c34b25c0ee55378057e425397a54027 Mon Sep 17 00:00:00 2001 From: CharlieZhao Date: Mon, 31 Jul 2023 18:44:48 +0800 Subject: [PATCH 2/2] Add newline to NEWS --- .../next/Library/2023-06-30-16-42-44.gh-issue-106263.tk-t93.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2023-06-30-16-42-44.gh-issue-106263.tk-t93.rst b/Misc/NEWS.d/next/Library/2023-06-30-16-42-44.gh-issue-106263.tk-t93.rst index 23763818d84ba5..d86a6bfdabbfb0 100644 --- a/Misc/NEWS.d/next/Library/2023-06-30-16-42-44.gh-issue-106263.tk-t93.rst +++ b/Misc/NEWS.d/next/Library/2023-06-30-16-42-44.gh-issue-106263.tk-t93.rst @@ -1,2 +1,2 @@ Fix crash when calling ``repr`` with a manually constructed SignalDict object. -Patch by Charlie Zhao. \ No newline at end of file +Patch by Charlie Zhao.