Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3979150

Browse filesBrowse files
gh-106263: Fix segfault in signaldict_repr in _decimal module (#106270)
Co-authored-by: sunmy2019 <59365878+sunmy2019@users.noreply.github.com>
1 parent 5113ed7 commit 3979150
Copy full SHA for 3979150

File tree

Expand file treeCollapse file tree

4 files changed

+61
-4
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+61
-4
lines changed

‎Lib/test/test_decimal.py

Copy file name to clipboardExpand all lines: Lib/test/test_decimal.py
+30Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5701,6 +5701,36 @@ def test_c_disallow_instantiation(self):
57015701
ContextManager = type(C.localcontext())
57025702
check_disallow_instantiation(self, ContextManager)
57035703

5704+
def test_c_signaldict_segfault(self):
5705+
# See gh-106263 for details.
5706+
SignalDict = type(C.Context().flags)
5707+
sd = SignalDict()
5708+
err_msg = "invalid signal dict"
5709+
5710+
with self.assertRaisesRegex(ValueError, err_msg):
5711+
len(sd)
5712+
5713+
with self.assertRaisesRegex(ValueError, err_msg):
5714+
iter(sd)
5715+
5716+
with self.assertRaisesRegex(ValueError, err_msg):
5717+
repr(sd)
5718+
5719+
with self.assertRaisesRegex(ValueError, err_msg):
5720+
sd[C.InvalidOperation] = True
5721+
5722+
with self.assertRaisesRegex(ValueError, err_msg):
5723+
sd[C.InvalidOperation]
5724+
5725+
with self.assertRaisesRegex(ValueError, err_msg):
5726+
sd == C.Context().flags
5727+
5728+
with self.assertRaisesRegex(ValueError, err_msg):
5729+
C.Context().flags == sd
5730+
5731+
with self.assertRaisesRegex(ValueError, err_msg):
5732+
sd.copy()
5733+
57045734
@requires_docstrings
57055735
@requires_cdecimal
57065736
class SignatureTest(unittest.TestCase):
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix crash when calling ``repr`` with a manually constructed SignalDict object.
2+
Patch by Charlie Zhao.

‎Modules/_decimal/_decimal.c

Copy file name to clipboardExpand all lines: Modules/_decimal/_decimal.c
+28-4Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -314,14 +314,12 @@ value_error_int(const char *mesg)
314314
return -1;
315315
}
316316

317-
#ifdef CONFIG_32
318317
static PyObject *
319318
value_error_ptr(const char *mesg)
320319
{
321320
PyErr_SetString(PyExc_ValueError, mesg);
322321
return NULL;
323322
}
324-
#endif
325323

326324
static int
327325
type_error_int(const char *mesg)
@@ -608,6 +606,8 @@ getround(decimal_state *state, PyObject *v)
608606
initialized to new SignalDicts. Once a SignalDict is tied to
609607
a context, it cannot be deleted. */
610608

609+
static const char *INVALID_SIGNALDICT_ERROR_MSG = "invalid signal dict";
610+
611611
static int
612612
signaldict_init(PyObject *self, PyObject *args UNUSED, PyObject *kwds UNUSED)
613613
{
@@ -616,14 +616,20 @@ signaldict_init(PyObject *self, PyObject *args UNUSED, PyObject *kwds UNUSED)
616616
}
617617

618618
static Py_ssize_t
619-
signaldict_len(PyObject *self UNUSED)
619+
signaldict_len(PyObject *self)
620620
{
621+
if (SdFlagAddr(self) == NULL) {
622+
return value_error_int(INVALID_SIGNALDICT_ERROR_MSG);
623+
}
621624
return SIGNAL_MAP_LEN;
622625
}
623626

624627
static PyObject *
625628
signaldict_iter(PyObject *self)
626629
{
630+
if (SdFlagAddr(self) == NULL) {
631+
return value_error_ptr(INVALID_SIGNALDICT_ERROR_MSG);
632+
}
627633
decimal_state *state = get_module_state_by_def(Py_TYPE(self));
628634
return PyTuple_Type.tp_iter(state->SignalTuple);
629635
}
@@ -632,6 +638,9 @@ static PyObject *
632638
signaldict_getitem(PyObject *self, PyObject *key)
633639
{
634640
uint32_t flag;
641+
if (SdFlagAddr(self) == NULL) {
642+
return value_error_ptr(INVALID_SIGNALDICT_ERROR_MSG);
643+
}
635644
decimal_state *state = get_module_state_by_def(Py_TYPE(self));
636645

637646
flag = exception_as_flag(state, key);
@@ -648,11 +657,15 @@ signaldict_setitem(PyObject *self, PyObject *key, PyObject *value)
648657
uint32_t flag;
649658
int x;
650659

651-
decimal_state *state = get_module_state_by_def(Py_TYPE(self));
660+
if (SdFlagAddr(self) == NULL) {
661+
return value_error_int(INVALID_SIGNALDICT_ERROR_MSG);
662+
}
663+
652664
if (value == NULL) {
653665
return value_error_int("signal keys cannot be deleted");
654666
}
655667

668+
decimal_state *state = get_module_state_by_def(Py_TYPE(self));
656669
flag = exception_as_flag(state, key);
657670
if (flag & DEC_ERRORS) {
658671
return -1;
@@ -697,6 +710,10 @@ signaldict_repr(PyObject *self)
697710
const char *b[SIGNAL_MAP_LEN]; /* bool */
698711
int i;
699712

713+
if (SdFlagAddr(self) == NULL) {
714+
return value_error_ptr(INVALID_SIGNALDICT_ERROR_MSG);
715+
}
716+
700717
assert(SIGNAL_MAP_LEN == 9);
701718

702719
decimal_state *state = get_module_state_by_def(Py_TYPE(self));
@@ -721,6 +738,10 @@ signaldict_richcompare(PyObject *v, PyObject *w, int op)
721738
decimal_state *state = find_state_left_or_right(v, w);
722739
assert(PyDecSignalDict_Check(state, v));
723740

741+
if ((SdFlagAddr(v) == NULL) || (SdFlagAddr(w) == NULL)) {
742+
return value_error_ptr(INVALID_SIGNALDICT_ERROR_MSG);
743+
}
744+
724745
if (op == Py_EQ || op == Py_NE) {
725746
if (PyDecSignalDict_Check(state, w)) {
726747
res = (SdFlags(v)==SdFlags(w)) ^ (op==Py_NE) ? Py_True : Py_False;
@@ -748,6 +769,9 @@ signaldict_richcompare(PyObject *v, PyObject *w, int op)
748769
static PyObject *
749770
signaldict_copy(PyObject *self, PyObject *args UNUSED)
750771
{
772+
if (SdFlagAddr(self) == NULL) {
773+
return value_error_ptr(INVALID_SIGNALDICT_ERROR_MSG);
774+
}
751775
decimal_state *state = get_module_state_by_def(Py_TYPE(self));
752776
return flags_as_dict(state, SdFlags(self));
753777
}

‎Tools/c-analyzer/cpython/ignored.tsv

Copy file name to clipboardExpand all lines: Tools/c-analyzer/cpython/ignored.tsv
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ Modules/_decimal/_decimal.c - invalid_rounding_err -
213213
Modules/_decimal/_decimal.c - invalid_signals_err -
214214
Modules/_decimal/_decimal.c - signal_map_template -
215215
Modules/_decimal/_decimal.c - ssize_constants -
216+
Modules/_decimal/_decimal.c - INVALID_SIGNALDICT_ERROR_MSG -
216217
Modules/_elementtree.c - ExpatMemoryHandler -
217218
Modules/_hashopenssl.c - py_hashes -
218219
Modules/_hacl/Hacl_Hash_SHA1.c - _h0 -

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.