Skip to content

Commit 621d4ff

Browse files
authored
gh-111178: fix UBSan failures in Modules/curses*.c (GH-128244)
* fix UBSan failures in `_cursesmodule.c` * fix UBSan failures in `_curses_panel.c` * suppress an unused return value
1 parent 8522f8b commit 621d4ff

File tree

2 files changed

+114
-71
lines changed

2 files changed

+114
-71
lines changed

Modules/_curses_panel.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ _curses_panel_traverse(PyObject *mod, visitproc visit, void *arg)
6262
static void
6363
_curses_panel_free(void *mod)
6464
{
65-
_curses_panel_clear((PyObject *) mod);
65+
(void)_curses_panel_clear((PyObject *)mod);
6666
}
6767

6868
/* Utility Functions */
@@ -101,6 +101,8 @@ typedef struct {
101101
PyCursesWindowObject *wo; /* for reference counts */
102102
} PyCursesPanelObject;
103103

104+
#define _PyCursesPanelObject_CAST(op) ((PyCursesPanelObject *)(op))
105+
104106
/* Some helper functions. The problem is that there's always a window
105107
associated with a panel. To ensure that Python's GC doesn't pull
106108
this window from under our feet we need to keep track of references
@@ -277,9 +279,10 @@ PyCursesPanel_New(_curses_panel_state *state, PANEL *pan,
277279
}
278280

279281
static void
280-
PyCursesPanel_Dealloc(PyCursesPanelObject *po)
282+
PyCursesPanel_Dealloc(PyObject *self)
281283
{
282284
PyObject *tp, *obj;
285+
PyCursesPanelObject *po = _PyCursesPanelObject_CAST(self);
283286

284287
tp = (PyObject *) Py_TYPE(po);
285288
obj = (PyObject *) panel_userptr(po->pan);

Modules/_cursesmodule.c

Lines changed: 109 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ get_cursesmodule_state_by_win(PyCursesWindowObject *win)
187187
return get_cursesmodule_state_by_cls(Py_TYPE(win));
188188
}
189189

190+
#define _PyCursesWindowObject_CAST(op) ((PyCursesWindowObject *)(op))
191+
190192
/*[clinic input]
191193
module _curses
192194
class _curses.window "PyCursesWindowObject *" "clinic_state()->window_type"
@@ -654,53 +656,80 @@ class component_converter(CConverter):
654656
PARSESTR - format string for argument parsing
655657
*/
656658

657-
#define Window_NoArgNoReturnFunction(X) \
658-
static PyObject *PyCursesWindow_ ## X \
659-
(PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \
660-
{ return PyCursesCheckERR_ForWin(self, X(self->win), # X); }
659+
#define Window_NoArgNoReturnFunction(X) \
660+
static PyObject *PyCursesWindow_ ## X \
661+
(PyObject *op, PyObject *Py_UNUSED(ignored)) \
662+
{ \
663+
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
664+
int code = X(self->win); \
665+
return PyCursesCheckERR_ForWin(self, code, # X); \
666+
}
661667

662668
#define Window_NoArgTrueFalseFunction(X) \
663669
static PyObject * PyCursesWindow_ ## X \
664-
(PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \
670+
(PyObject *op, PyObject *Py_UNUSED(ignored)) \
665671
{ \
666-
return PyBool_FromLong(X(self->win)); }
672+
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
673+
return PyBool_FromLong(X(self->win)); \
674+
}
667675

668-
#define Window_NoArgNoReturnVoidFunction(X) \
669-
static PyObject * PyCursesWindow_ ## X \
670-
(PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \
671-
{ \
672-
X(self->win); Py_RETURN_NONE; }
676+
#define Window_NoArgNoReturnVoidFunction(X) \
677+
static PyObject * PyCursesWindow_ ## X \
678+
(PyObject *op, PyObject *Py_UNUSED(ignored)) \
679+
{ \
680+
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
681+
X(self->win); \
682+
Py_RETURN_NONE; \
683+
}
673684

674685
#define Window_NoArg2TupleReturnFunction(X, TYPE, ERGSTR) \
675686
static PyObject * PyCursesWindow_ ## X \
676-
(PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \
687+
(PyObject *op, PyObject *Py_UNUSED(ignored)) \
677688
{ \
678689
TYPE arg1, arg2; \
679-
X(self->win,arg1,arg2); return Py_BuildValue(ERGSTR, arg1, arg2); }
690+
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
691+
X(self->win, arg1, arg2); \
692+
return Py_BuildValue(ERGSTR, arg1, arg2); \
693+
}
680694

681695
#define Window_OneArgNoReturnVoidFunction(X, TYPE, PARSESTR) \
682696
static PyObject * PyCursesWindow_ ## X \
683-
(PyCursesWindowObject *self, PyObject *args) \
697+
(PyObject *op, PyObject *args) \
684698
{ \
685699
TYPE arg1; \
686-
if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) return NULL; \
687-
X(self->win,arg1); Py_RETURN_NONE; }
700+
if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) { \
701+
return NULL; \
702+
} \
703+
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
704+
X(self->win, arg1); \
705+
Py_RETURN_NONE; \
706+
}
688707

689708
#define Window_OneArgNoReturnFunction(X, TYPE, PARSESTR) \
690709
static PyObject * PyCursesWindow_ ## X \
691-
(PyCursesWindowObject *self, PyObject *args) \
710+
(PyObject *op, PyObject *args) \
692711
{ \
693712
TYPE arg1; \
694-
if (!PyArg_ParseTuple(args,PARSESTR, &arg1)) return NULL; \
695-
return PyCursesCheckERR_ForWin(self, X(self->win, arg1), # X); }
713+
if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) { \
714+
return NULL; \
715+
} \
716+
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
717+
int code = X(self->win, arg1); \
718+
return PyCursesCheckERR_ForWin(self, code, # X); \
719+
}
696720

697721
#define Window_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \
698722
static PyObject * PyCursesWindow_ ## X \
699-
(PyCursesWindowObject *self, PyObject *args) \
723+
(PyObject *op, PyObject *args) \
700724
{ \
701725
TYPE arg1, arg2; \
702-
if (!PyArg_ParseTuple(args,PARSESTR, &arg1, &arg2)) return NULL; \
703-
return PyCursesCheckERR_ForWin(self, X(self->win, arg1, arg2), # X); }
726+
if (!PyArg_ParseTuple(args,PARSESTR, &arg1, &arg2)) { \
727+
return NULL; \
728+
} \
729+
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
730+
int code = X(self->win, arg1, arg2); \
731+
return PyCursesCheckERR_ForWin(self, code, # X); \
732+
}
704733

705734
/* ------------- WINDOW routines --------------- */
706735

@@ -1302,8 +1331,10 @@ the touchline() method so that the contents will be redisplayed by the next
13021331
window refresh.
13031332
[-clinic start generated code]*/
13041333
static PyObject *
1305-
PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args)
1334+
PyCursesWindow_ChgAt(PyObject *op, PyObject *args)
13061335
{
1336+
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
1337+
13071338
int rtn;
13081339
int x, y;
13091340
int num = -1;
@@ -1656,8 +1687,10 @@ Read a string from the user, with primitive line editing capacity.
16561687
[-clinic start generated code]*/
16571688

16581689
static PyObject *
1659-
PyCursesWindow_GetStr(PyCursesWindowObject *self, PyObject *args)
1690+
PyCursesWindow_GetStr(PyObject *op, PyObject *args)
16601691
{
1692+
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
1693+
16611694
int x, y, n;
16621695
char rtn[1024]; /* This should be big enough.. I hope */
16631696
int rtn2;
@@ -1860,8 +1893,10 @@ from the characters. If n is specified, instr() returns a string at most
18601893
n characters long (exclusive of the trailing NUL).
18611894
[-clinic start generated code]*/
18621895
static PyObject *
1863-
PyCursesWindow_InStr(PyCursesWindowObject *self, PyObject *args)
1896+
PyCursesWindow_InStr(PyObject *op, PyObject *args)
18641897
{
1898+
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
1899+
18651900
int x, y, n;
18661901
char rtn[1024]; /* This should be big enough.. I hope */
18671902
int rtn2;
@@ -2557,14 +2592,17 @@ _curses_window_vline_impl(PyCursesWindowObject *self, int group_left_1,
25572592
}
25582593

25592594
static PyObject *
2560-
PyCursesWindow_get_encoding(PyCursesWindowObject *self, void *closure)
2595+
PyCursesWindow_get_encoding(PyObject *op, void *closure)
25612596
{
2597+
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
25622598
return PyUnicode_FromString(self->encoding);
25632599
}
25642600

25652601
static int
2566-
PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value, void *Py_UNUSED(ignored))
2602+
PyCursesWindow_set_encoding(PyObject *op, PyObject *value, void *Py_UNUSED(ignored))
25672603
{
2604+
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
2605+
25682606
PyObject *ascii;
25692607
char *encoding;
25702608

@@ -2607,88 +2645,90 @@ static PyMethodDef PyCursesWindow_methods[] = {
26072645
_CURSES_WINDOW_ATTRSET_METHODDEF
26082646
_CURSES_WINDOW_BKGD_METHODDEF
26092647
#ifdef HAVE_CURSES_WCHGAT
2610-
{"chgat", (PyCFunction)PyCursesWindow_ChgAt, METH_VARARGS},
2648+
{"chgat", PyCursesWindow_ChgAt, METH_VARARGS},
26112649
#endif
26122650
_CURSES_WINDOW_BKGDSET_METHODDEF
26132651
_CURSES_WINDOW_BORDER_METHODDEF
26142652
_CURSES_WINDOW_BOX_METHODDEF
2615-
{"clear", (PyCFunction)PyCursesWindow_wclear, METH_NOARGS},
2616-
{"clearok", (PyCFunction)PyCursesWindow_clearok, METH_VARARGS},
2617-
{"clrtobot", (PyCFunction)PyCursesWindow_wclrtobot, METH_NOARGS},
2618-
{"clrtoeol", (PyCFunction)PyCursesWindow_wclrtoeol, METH_NOARGS},
2619-
{"cursyncup", (PyCFunction)PyCursesWindow_wcursyncup, METH_NOARGS},
2653+
{"clear", PyCursesWindow_wclear, METH_NOARGS},
2654+
{"clearok", PyCursesWindow_clearok, METH_VARARGS},
2655+
{"clrtobot", PyCursesWindow_wclrtobot, METH_NOARGS},
2656+
{"clrtoeol", PyCursesWindow_wclrtoeol, METH_NOARGS},
2657+
{"cursyncup", PyCursesWindow_wcursyncup, METH_NOARGS},
26202658
_CURSES_WINDOW_DELCH_METHODDEF
2621-
{"deleteln", (PyCFunction)PyCursesWindow_wdeleteln, METH_NOARGS},
2659+
{"deleteln", PyCursesWindow_wdeleteln, METH_NOARGS},
26222660
_CURSES_WINDOW_DERWIN_METHODDEF
26232661
_CURSES_WINDOW_ECHOCHAR_METHODDEF
26242662
_CURSES_WINDOW_ENCLOSE_METHODDEF
2625-
{"erase", (PyCFunction)PyCursesWindow_werase, METH_NOARGS},
2626-
{"getbegyx", (PyCFunction)PyCursesWindow_getbegyx, METH_NOARGS},
2663+
{"erase", PyCursesWindow_werase, METH_NOARGS},
2664+
{"getbegyx", PyCursesWindow_getbegyx, METH_NOARGS},
26272665
_CURSES_WINDOW_GETBKGD_METHODDEF
26282666
_CURSES_WINDOW_GETCH_METHODDEF
26292667
_CURSES_WINDOW_GETKEY_METHODDEF
26302668
_CURSES_WINDOW_GET_WCH_METHODDEF
2631-
{"getmaxyx", (PyCFunction)PyCursesWindow_getmaxyx, METH_NOARGS},
2632-
{"getparyx", (PyCFunction)PyCursesWindow_getparyx, METH_NOARGS},
2633-
{"getstr", (PyCFunction)PyCursesWindow_GetStr, METH_VARARGS},
2634-
{"getyx", (PyCFunction)PyCursesWindow_getyx, METH_NOARGS},
2669+
{"getmaxyx", PyCursesWindow_getmaxyx, METH_NOARGS},
2670+
{"getparyx", PyCursesWindow_getparyx, METH_NOARGS},
2671+
{"getstr", PyCursesWindow_GetStr, METH_VARARGS},
2672+
{"getyx", PyCursesWindow_getyx, METH_NOARGS},
26352673
_CURSES_WINDOW_HLINE_METHODDEF
2636-
{"idcok", (PyCFunction)PyCursesWindow_idcok, METH_VARARGS},
2637-
{"idlok", (PyCFunction)PyCursesWindow_idlok, METH_VARARGS},
2674+
{"idcok", PyCursesWindow_idcok, METH_VARARGS},
2675+
{"idlok", PyCursesWindow_idlok, METH_VARARGS},
26382676
#ifdef HAVE_CURSES_IMMEDOK
2639-
{"immedok", (PyCFunction)PyCursesWindow_immedok, METH_VARARGS},
2677+
{"immedok", PyCursesWindow_immedok, METH_VARARGS},
26402678
#endif
26412679
_CURSES_WINDOW_INCH_METHODDEF
26422680
_CURSES_WINDOW_INSCH_METHODDEF
2643-
{"insdelln", (PyCFunction)PyCursesWindow_winsdelln, METH_VARARGS},
2644-
{"insertln", (PyCFunction)PyCursesWindow_winsertln, METH_NOARGS},
2681+
{"insdelln", PyCursesWindow_winsdelln, METH_VARARGS},
2682+
{"insertln", PyCursesWindow_winsertln, METH_NOARGS},
26452683
_CURSES_WINDOW_INSNSTR_METHODDEF
26462684
_CURSES_WINDOW_INSSTR_METHODDEF
2647-
{"instr", (PyCFunction)PyCursesWindow_InStr, METH_VARARGS},
2685+
{"instr", PyCursesWindow_InStr, METH_VARARGS},
26482686
_CURSES_WINDOW_IS_LINETOUCHED_METHODDEF
2649-
{"is_wintouched", (PyCFunction)PyCursesWindow_is_wintouched, METH_NOARGS},
2650-
{"keypad", (PyCFunction)PyCursesWindow_keypad, METH_VARARGS},
2651-
{"leaveok", (PyCFunction)PyCursesWindow_leaveok, METH_VARARGS},
2652-
{"move", (PyCFunction)PyCursesWindow_wmove, METH_VARARGS},
2653-
{"mvderwin", (PyCFunction)PyCursesWindow_mvderwin, METH_VARARGS},
2654-
{"mvwin", (PyCFunction)PyCursesWindow_mvwin, METH_VARARGS},
2655-
{"nodelay", (PyCFunction)PyCursesWindow_nodelay, METH_VARARGS},
2656-
{"notimeout", (PyCFunction)PyCursesWindow_notimeout, METH_VARARGS},
2687+
{"is_wintouched", PyCursesWindow_is_wintouched, METH_NOARGS},
2688+
{"keypad", PyCursesWindow_keypad, METH_VARARGS},
2689+
{"leaveok", PyCursesWindow_leaveok, METH_VARARGS},
2690+
{"move", PyCursesWindow_wmove, METH_VARARGS},
2691+
{"mvderwin", PyCursesWindow_mvderwin, METH_VARARGS},
2692+
{"mvwin", PyCursesWindow_mvwin, METH_VARARGS},
2693+
{"nodelay", PyCursesWindow_nodelay, METH_VARARGS},
2694+
{"notimeout", PyCursesWindow_notimeout, METH_VARARGS},
26572695
_CURSES_WINDOW_NOUTREFRESH_METHODDEF
26582696
_CURSES_WINDOW_OVERLAY_METHODDEF
26592697
_CURSES_WINDOW_OVERWRITE_METHODDEF
26602698
_CURSES_WINDOW_PUTWIN_METHODDEF
26612699
_CURSES_WINDOW_REDRAWLN_METHODDEF
2662-
{"redrawwin", (PyCFunction)PyCursesWindow_redrawwin, METH_NOARGS},
2700+
{"redrawwin", PyCursesWindow_redrawwin, METH_NOARGS},
26632701
_CURSES_WINDOW_REFRESH_METHODDEF
26642702
#ifndef STRICT_SYSV_CURSES
2665-
{"resize", (PyCFunction)PyCursesWindow_wresize, METH_VARARGS},
2703+
{"resize", PyCursesWindow_wresize, METH_VARARGS},
26662704
#endif
26672705
_CURSES_WINDOW_SCROLL_METHODDEF
2668-
{"scrollok", (PyCFunction)PyCursesWindow_scrollok, METH_VARARGS},
2706+
{"scrollok", PyCursesWindow_scrollok, METH_VARARGS},
26692707
_CURSES_WINDOW_SETSCRREG_METHODDEF
2670-
{"standend", (PyCFunction)PyCursesWindow_wstandend, METH_NOARGS},
2671-
{"standout", (PyCFunction)PyCursesWindow_wstandout, METH_NOARGS},
2708+
{"standend", PyCursesWindow_wstandend, METH_NOARGS},
2709+
{"standout", PyCursesWindow_wstandout, METH_NOARGS},
26722710
{"subpad", (PyCFunction)_curses_window_subwin, METH_VARARGS, _curses_window_subwin__doc__},
26732711
_CURSES_WINDOW_SUBWIN_METHODDEF
2674-
{"syncdown", (PyCFunction)PyCursesWindow_wsyncdown, METH_NOARGS},
2712+
{"syncdown", PyCursesWindow_wsyncdown, METH_NOARGS},
26752713
#ifdef HAVE_CURSES_SYNCOK
2676-
{"syncok", (PyCFunction)PyCursesWindow_syncok, METH_VARARGS},
2714+
{"syncok", PyCursesWindow_syncok, METH_VARARGS},
26772715
#endif
2678-
{"syncup", (PyCFunction)PyCursesWindow_wsyncup, METH_NOARGS},
2679-
{"timeout", (PyCFunction)PyCursesWindow_wtimeout, METH_VARARGS},
2716+
{"syncup", PyCursesWindow_wsyncup, METH_NOARGS},
2717+
{"timeout", PyCursesWindow_wtimeout, METH_VARARGS},
26802718
_CURSES_WINDOW_TOUCHLINE_METHODDEF
2681-
{"touchwin", (PyCFunction)PyCursesWindow_touchwin, METH_NOARGS},
2682-
{"untouchwin", (PyCFunction)PyCursesWindow_untouchwin, METH_NOARGS},
2719+
{"touchwin", PyCursesWindow_touchwin, METH_NOARGS},
2720+
{"untouchwin", PyCursesWindow_untouchwin, METH_NOARGS},
26832721
_CURSES_WINDOW_VLINE_METHODDEF
26842722
{NULL, NULL} /* sentinel */
26852723
};
26862724

26872725
static PyGetSetDef PyCursesWindow_getsets[] = {
2688-
{"encoding",
2689-
(getter)PyCursesWindow_get_encoding,
2690-
(setter)PyCursesWindow_set_encoding,
2691-
"the typecode character used to create the array"},
2726+
{
2727+
"encoding",
2728+
PyCursesWindow_get_encoding,
2729+
PyCursesWindow_set_encoding,
2730+
"the typecode character used to create the array"
2731+
},
26922732
{NULL, NULL, NULL, NULL } /* sentinel */
26932733
};
26942734

0 commit comments

Comments
 (0)