Skip to content

Commit cc4df05

Browse files
committed
Compare handler in a safe helper function
1 parent 3438104 commit cc4df05

File tree

1 file changed

+23
-39
lines changed

1 file changed

+23
-39
lines changed

Modules/signalmodule.c

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,17 @@ get_signal_state(PyObject *module)
177177
}
178178

179179

180+
static inline int
181+
compare_handler(PyObject *handler, PyObject *func)
182+
{
183+
assert(PyLong_CheckExact(handler));
184+
if (!PyLong_CheckExact(func)) {
185+
return 0;
186+
}
187+
// Assume that comparison of two PyLong objects will never fail.
188+
return PyObject_RichCompareBool(func, handler, Py_EQ) == 1;
189+
}
190+
180191
#ifdef HAVE_GETITIMER
181192
/* auxiliary functions for setitimer */
182193
static int
@@ -496,7 +507,6 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler)
496507
_signal_module_state *modstate = get_signal_state(module);
497508
PyObject *old_handler;
498509
void (*func)(int);
499-
int match = 0; // cannot use func == NULL as sentinel, SIG_DFL == 0
500510
#ifdef MS_WINDOWS
501511
/* Validate that signalnum is one of the allowable signals */
502512
switch (signalnum) {
@@ -531,31 +541,11 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler)
531541
}
532542
if (PyCallable_Check(handler)) {
533543
func = signal_handler;
534-
match = 1;
535-
}
536-
if (!match) {
537-
int cmp = PyObject_RichCompareBool(handler, modstate->ignore_handler, Py_EQ);
538-
switch (cmp) {
539-
case -1:
540-
return NULL;
541-
case 1:
542-
func = SIG_IGN;
543-
match = 1;
544-
break;
545-
}
546-
}
547-
if (!match) {
548-
int cmp = PyObject_RichCompareBool(handler, modstate->default_handler, Py_EQ);
549-
switch (cmp) {
550-
case -1:
551-
return NULL;
552-
case 1:
553-
func = SIG_DFL;
554-
match = 1;
555-
break;
556-
}
557-
}
558-
if (!match) {
544+
} else if (compare_handler(handler, modstate->ignore_handler)) {
545+
func = SIG_IGN;
546+
} else if (compare_handler(handler, modstate->default_handler)) {
547+
func = SIG_DFL;
548+
} else {
559549
_PyErr_SetString(tstate, PyExc_TypeError,
560550
"signal handler must be signal.SIG_IGN, "
561551
"signal.SIG_DFL, or a callable object");
@@ -1770,8 +1760,8 @@ _PySignal_Fini(void)
17701760
set_handler(signum, NULL);
17711761
if (func != NULL
17721762
&& func != Py_None
1773-
&& func != state->default_handler
1774-
&& func != state->ignore_handler)
1763+
&& !compare_handler(func, state->default_handler)
1764+
&& !compare_handler(func, state->ignore_handler))
17751765
{
17761766
PyOS_setsig(signum, SIG_DFL);
17771767
}
@@ -1842,8 +1832,9 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate)
18421832
* (see bpo-43406).
18431833
*/
18441834
PyObject *func = get_handler(i);
1845-
if (func == NULL || func == Py_None || func == state->ignore_handler ||
1846-
func == state->default_handler) {
1835+
if (func == NULL || func == Py_None ||
1836+
compare_handler(func, state->ignore_handler) ||
1837+
compare_handler(func, state->default_handler)) {
18471838
/* No Python signal handler due to aforementioned race condition.
18481839
* We can't call raise() as it would break the assumption
18491840
* that PyErr_SetInterrupt() only *simulates* an incoming
@@ -1911,15 +1902,8 @@ PyErr_SetInterruptEx(int signum)
19111902

19121903
signal_state_t *state = &signal_global_state;
19131904
PyObject *func = get_handler(signum);
1914-
int is_ign = PyObject_RichCompareBool(func, state->ignore_handler, Py_EQ);
1915-
if (is_ign == -1) {
1916-
return -1;
1917-
}
1918-
int is_dfl = PyObject_RichCompareBool(func, state->default_handler, Py_EQ);
1919-
if (is_dfl == -1) {
1920-
return -1;
1921-
}
1922-
if ((is_ign == 0) && (is_dfl == 0)) {
1905+
if (!compare_handler(func, state->ignore_handler)
1906+
&& !compare_handler(func, state->default_handler)) {
19231907
trip_signal(signum);
19241908
}
19251909
return 0;

0 commit comments

Comments
 (0)