mirror of https://github.com/python/cpython
gh-120378: Fix crash caused by integer overflow in `curses` (#124555)
This is actually an upstream problem in curses, and has been reported to them already: https://lists.gnu.org/archive/html/bug-ncurses/2024-09/msg00101.html This is a nice workaround in the meantime to prevent the segfault. Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
parent
7bd9dbf8e1
commit
c2ba931318
|
@ -1081,6 +1081,14 @@ class TestCurses(unittest.TestCase):
|
|||
self.assertEqual(curses.LINES, lines)
|
||||
self.assertEqual(curses.COLS, cols)
|
||||
|
||||
with self.assertRaises(OverflowError):
|
||||
curses.resize_term(35000, 1)
|
||||
with self.assertRaises(OverflowError):
|
||||
curses.resize_term(1, 35000)
|
||||
# GH-120378: Overflow failure in resize_term() causes refresh to fail
|
||||
tmp = curses.initscr()
|
||||
tmp.erase()
|
||||
|
||||
@requires_curses_func('resizeterm')
|
||||
def test_resizeterm(self):
|
||||
curses.update_lines_cols()
|
||||
|
@ -1095,6 +1103,14 @@ class TestCurses(unittest.TestCase):
|
|||
self.assertEqual(curses.LINES, lines)
|
||||
self.assertEqual(curses.COLS, cols)
|
||||
|
||||
with self.assertRaises(OverflowError):
|
||||
curses.resizeterm(35000, 1)
|
||||
with self.assertRaises(OverflowError):
|
||||
curses.resizeterm(1, 35000)
|
||||
# GH-120378: Overflow failure in resizeterm() causes refresh to fail
|
||||
tmp = curses.initscr()
|
||||
tmp.erase()
|
||||
|
||||
def test_ungetch(self):
|
||||
curses.ungetch(b'A')
|
||||
self.assertEqual(self.stdscr.getkey(), 'A')
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Fix a crash related to an integer overflow in :func:`curses.resizeterm`
|
||||
and :func:`curses.resize_term`.
|
|
@ -4204,9 +4204,9 @@ NoArgNoReturnFunctionBody(resetty)
|
|||
/*[clinic input]
|
||||
_curses.resizeterm
|
||||
|
||||
nlines: int
|
||||
nlines: short
|
||||
Height.
|
||||
ncols: int
|
||||
ncols: short
|
||||
Width.
|
||||
/
|
||||
|
||||
|
@ -4217,8 +4217,8 @@ window dimensions (in particular the SIGWINCH handler).
|
|||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
_curses_resizeterm_impl(PyObject *module, int nlines, int ncols)
|
||||
/*[clinic end generated code: output=56d6bcc5194ad055 input=0fca02ebad5ffa82]*/
|
||||
_curses_resizeterm_impl(PyObject *module, short nlines, short ncols)
|
||||
/*[clinic end generated code: output=4de3abab50c67f02 input=414e92a63e3e9899]*/
|
||||
{
|
||||
PyObject *result;
|
||||
|
||||
|
@ -4240,9 +4240,9 @@ _curses_resizeterm_impl(PyObject *module, int nlines, int ncols)
|
|||
/*[clinic input]
|
||||
_curses.resize_term
|
||||
|
||||
nlines: int
|
||||
nlines: short
|
||||
Height.
|
||||
ncols: int
|
||||
ncols: short
|
||||
Width.
|
||||
/
|
||||
|
||||
|
@ -4256,8 +4256,8 @@ without additional interaction with the application.
|
|||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
_curses_resize_term_impl(PyObject *module, int nlines, int ncols)
|
||||
/*[clinic end generated code: output=9e26d8b9ea311ed2 input=2197edd05b049ed4]*/
|
||||
_curses_resize_term_impl(PyObject *module, short nlines, short ncols)
|
||||
/*[clinic end generated code: output=46c6d749fa291dbd input=276afa43d8ea7091]*/
|
||||
{
|
||||
PyObject *result;
|
||||
|
||||
|
|
|
@ -3693,26 +3693,56 @@ PyDoc_STRVAR(_curses_resizeterm__doc__,
|
|||
{"resizeterm", _PyCFunction_CAST(_curses_resizeterm), METH_FASTCALL, _curses_resizeterm__doc__},
|
||||
|
||||
static PyObject *
|
||||
_curses_resizeterm_impl(PyObject *module, int nlines, int ncols);
|
||||
_curses_resizeterm_impl(PyObject *module, short nlines, short ncols);
|
||||
|
||||
static PyObject *
|
||||
_curses_resizeterm(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
int nlines;
|
||||
int ncols;
|
||||
short nlines;
|
||||
short ncols;
|
||||
|
||||
if (!_PyArg_CheckPositional("resizeterm", nargs, 2, 2)) {
|
||||
goto exit;
|
||||
}
|
||||
nlines = PyLong_AsInt(args[0]);
|
||||
if (nlines == -1 && PyErr_Occurred()) {
|
||||
{
|
||||
long ival = PyLong_AsLong(args[0]);
|
||||
if (ival == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
ncols = PyLong_AsInt(args[1]);
|
||||
if (ncols == -1 && PyErr_Occurred()) {
|
||||
else if (ival < SHRT_MIN) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"signed short integer is less than minimum");
|
||||
goto exit;
|
||||
}
|
||||
else if (ival > SHRT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"signed short integer is greater than maximum");
|
||||
goto exit;
|
||||
}
|
||||
else {
|
||||
nlines = (short) ival;
|
||||
}
|
||||
}
|
||||
{
|
||||
long ival = PyLong_AsLong(args[1]);
|
||||
if (ival == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
else if (ival < SHRT_MIN) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"signed short integer is less than minimum");
|
||||
goto exit;
|
||||
}
|
||||
else if (ival > SHRT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"signed short integer is greater than maximum");
|
||||
goto exit;
|
||||
}
|
||||
else {
|
||||
ncols = (short) ival;
|
||||
}
|
||||
}
|
||||
return_value = _curses_resizeterm_impl(module, nlines, ncols);
|
||||
|
||||
exit:
|
||||
|
@ -3744,26 +3774,56 @@ PyDoc_STRVAR(_curses_resize_term__doc__,
|
|||
{"resize_term", _PyCFunction_CAST(_curses_resize_term), METH_FASTCALL, _curses_resize_term__doc__},
|
||||
|
||||
static PyObject *
|
||||
_curses_resize_term_impl(PyObject *module, int nlines, int ncols);
|
||||
_curses_resize_term_impl(PyObject *module, short nlines, short ncols);
|
||||
|
||||
static PyObject *
|
||||
_curses_resize_term(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
int nlines;
|
||||
int ncols;
|
||||
short nlines;
|
||||
short ncols;
|
||||
|
||||
if (!_PyArg_CheckPositional("resize_term", nargs, 2, 2)) {
|
||||
goto exit;
|
||||
}
|
||||
nlines = PyLong_AsInt(args[0]);
|
||||
if (nlines == -1 && PyErr_Occurred()) {
|
||||
{
|
||||
long ival = PyLong_AsLong(args[0]);
|
||||
if (ival == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
ncols = PyLong_AsInt(args[1]);
|
||||
if (ncols == -1 && PyErr_Occurred()) {
|
||||
else if (ival < SHRT_MIN) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"signed short integer is less than minimum");
|
||||
goto exit;
|
||||
}
|
||||
else if (ival > SHRT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"signed short integer is greater than maximum");
|
||||
goto exit;
|
||||
}
|
||||
else {
|
||||
nlines = (short) ival;
|
||||
}
|
||||
}
|
||||
{
|
||||
long ival = PyLong_AsLong(args[1]);
|
||||
if (ival == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
else if (ival < SHRT_MIN) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"signed short integer is less than minimum");
|
||||
goto exit;
|
||||
}
|
||||
else if (ival > SHRT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"signed short integer is greater than maximum");
|
||||
goto exit;
|
||||
}
|
||||
else {
|
||||
ncols = (short) ival;
|
||||
}
|
||||
}
|
||||
return_value = _curses_resize_term_impl(module, nlines, ncols);
|
||||
|
||||
exit:
|
||||
|
@ -4318,4 +4378,4 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored
|
|||
#ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF
|
||||
#define _CURSES_USE_DEFAULT_COLORS_METHODDEF
|
||||
#endif /* !defined(_CURSES_USE_DEFAULT_COLORS_METHODDEF) */
|
||||
/*[clinic end generated code: output=96887782374f070a input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=8745c1562b537fb4 input=a9049054013a1b77]*/
|
||||
|
|
Loading…
Reference in New Issue