[3.12] gh-106263: Fix segfault in signaldict_repr in _decimal module (#… (#107491)

Co-authored-by: sunmy2019 <59365878+sunmy2019@users.noreply.github.com>

(cherry picked from commit 3979150a0d)
This commit is contained in:
Charlie Zhao 2023-07-31 20:34:16 +08:00 committed by GitHub
parent 8f080a290b
commit 99518bbbf4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 3 deletions

View file

@ -5682,6 +5682,36 @@ class CWhitebox(unittest.TestCase):
self.assertEqual(Decimal(400) ** -1, Decimal('0.0025')) 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_docstrings
@requires_cdecimal @requires_cdecimal
class SignatureTest(unittest.TestCase): class SignatureTest(unittest.TestCase):

View file

@ -0,0 +1,2 @@
Fix crash when calling ``repr`` with a manually constructed SignalDict object.
Patch by Charlie Zhao.

View file

@ -246,14 +246,12 @@ value_error_int(const char *mesg)
return -1; return -1;
} }
#ifdef CONFIG_32
static PyObject * static PyObject *
value_error_ptr(const char *mesg) value_error_ptr(const char *mesg)
{ {
PyErr_SetString(PyExc_ValueError, mesg); PyErr_SetString(PyExc_ValueError, mesg);
return NULL; return NULL;
} }
#endif
static int static int
type_error_int(const char *mesg) type_error_int(const char *mesg)
@ -540,6 +538,8 @@ getround(PyObject *v)
initialized to new SignalDicts. Once a SignalDict is tied to initialized to new SignalDicts. Once a SignalDict is tied to
a context, it cannot be deleted. */ a context, it cannot be deleted. */
static const char *INVALID_SIGNALDICT_ERROR_MSG = "invalid signal dict";
static int static int
signaldict_init(PyObject *self, PyObject *args UNUSED, PyObject *kwds UNUSED) signaldict_init(PyObject *self, PyObject *args UNUSED, PyObject *kwds UNUSED)
{ {
@ -548,8 +548,11 @@ signaldict_init(PyObject *self, PyObject *args UNUSED, PyObject *kwds UNUSED)
} }
static Py_ssize_t 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; return SIGNAL_MAP_LEN;
} }
@ -557,6 +560,9 @@ static PyObject *SignalTuple;
static PyObject * static PyObject *
signaldict_iter(PyObject *self UNUSED) signaldict_iter(PyObject *self UNUSED)
{ {
if (SdFlagAddr(self) == NULL) {
return value_error_ptr(INVALID_SIGNALDICT_ERROR_MSG);
}
return PyTuple_Type.tp_iter(SignalTuple); return PyTuple_Type.tp_iter(SignalTuple);
} }
@ -564,6 +570,9 @@ static PyObject *
signaldict_getitem(PyObject *self, PyObject *key) signaldict_getitem(PyObject *self, PyObject *key)
{ {
uint32_t flag; uint32_t flag;
if (SdFlagAddr(self) == NULL) {
return value_error_ptr(INVALID_SIGNALDICT_ERROR_MSG);
}
flag = exception_as_flag(key); flag = exception_as_flag(key);
if (flag & DEC_ERRORS) { if (flag & DEC_ERRORS) {
@ -579,6 +588,10 @@ signaldict_setitem(PyObject *self, PyObject *key, PyObject *value)
uint32_t flag; uint32_t flag;
int x; int x;
if (SdFlagAddr(self) == NULL) {
return value_error_int(INVALID_SIGNALDICT_ERROR_MSG);
}
if (value == NULL) { if (value == NULL) {
return value_error_int("signal keys cannot be deleted"); return value_error_int("signal keys cannot be deleted");
} }
@ -611,6 +624,10 @@ signaldict_repr(PyObject *self)
const char *b[SIGNAL_MAP_LEN]; /* bool */ const char *b[SIGNAL_MAP_LEN]; /* bool */
int i; int i;
if (SdFlagAddr(self) == NULL) {
return value_error_ptr(INVALID_SIGNALDICT_ERROR_MSG);
}
assert(SIGNAL_MAP_LEN == 9); assert(SIGNAL_MAP_LEN == 9);
for (cm=signal_map, i=0; cm->name != NULL; cm++, i++) { for (cm=signal_map, i=0; cm->name != NULL; cm++, i++) {
@ -632,6 +649,9 @@ signaldict_richcompare(PyObject *v, PyObject *w, int op)
PyObject *res = Py_NotImplemented; PyObject *res = Py_NotImplemented;
assert(PyDecSignalDict_Check(v)); 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 (op == Py_EQ || op == Py_NE) {
if (PyDecSignalDict_Check(w)) { if (PyDecSignalDict_Check(w)) {
@ -660,6 +680,9 @@ signaldict_richcompare(PyObject *v, PyObject *w, int op)
static PyObject * static PyObject *
signaldict_copy(PyObject *self, PyObject *args UNUSED) 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)); return flags_as_dict(SdFlags(self));
} }

View file

@ -213,6 +213,7 @@ Modules/_decimal/_decimal.c - invalid_rounding_err -
Modules/_decimal/_decimal.c - invalid_signals_err - Modules/_decimal/_decimal.c - invalid_signals_err -
Modules/_decimal/_decimal.c - signal_map - Modules/_decimal/_decimal.c - signal_map -
Modules/_decimal/_decimal.c - ssize_constants - Modules/_decimal/_decimal.c - ssize_constants -
Modules/_decimal/_decimal.c - INVALID_SIGNALDICT_ERROR_MSG -
Modules/_elementtree.c - ExpatMemoryHandler - Modules/_elementtree.c - ExpatMemoryHandler -
Modules/_hashopenssl.c - py_hashes - Modules/_hashopenssl.c - py_hashes -
Modules/_hacl/Hacl_Hash_SHA1.c - _h0 - Modules/_hacl/Hacl_Hash_SHA1.c - _h0 -

Can't render this file because it has a wrong number of fields in line 4.