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.LINES, lines)
|
||||||
self.assertEqual(curses.COLS, cols)
|
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')
|
@requires_curses_func('resizeterm')
|
||||||
def test_resizeterm(self):
|
def test_resizeterm(self):
|
||||||
curses.update_lines_cols()
|
curses.update_lines_cols()
|
||||||
|
@ -1095,6 +1103,14 @@ class TestCurses(unittest.TestCase):
|
||||||
self.assertEqual(curses.LINES, lines)
|
self.assertEqual(curses.LINES, lines)
|
||||||
self.assertEqual(curses.COLS, cols)
|
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):
|
def test_ungetch(self):
|
||||||
curses.ungetch(b'A')
|
curses.ungetch(b'A')
|
||||||
self.assertEqual(self.stdscr.getkey(), '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]
|
/*[clinic input]
|
||||||
_curses.resizeterm
|
_curses.resizeterm
|
||||||
|
|
||||||
nlines: int
|
nlines: short
|
||||||
Height.
|
Height.
|
||||||
ncols: int
|
ncols: short
|
||||||
Width.
|
Width.
|
||||||
/
|
/
|
||||||
|
|
||||||
|
@ -4217,8 +4217,8 @@ window dimensions (in particular the SIGWINCH handler).
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_curses_resizeterm_impl(PyObject *module, int nlines, int ncols)
|
_curses_resizeterm_impl(PyObject *module, short nlines, short ncols)
|
||||||
/*[clinic end generated code: output=56d6bcc5194ad055 input=0fca02ebad5ffa82]*/
|
/*[clinic end generated code: output=4de3abab50c67f02 input=414e92a63e3e9899]*/
|
||||||
{
|
{
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
|
|
||||||
|
@ -4240,9 +4240,9 @@ _curses_resizeterm_impl(PyObject *module, int nlines, int ncols)
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
_curses.resize_term
|
_curses.resize_term
|
||||||
|
|
||||||
nlines: int
|
nlines: short
|
||||||
Height.
|
Height.
|
||||||
ncols: int
|
ncols: short
|
||||||
Width.
|
Width.
|
||||||
/
|
/
|
||||||
|
|
||||||
|
@ -4256,8 +4256,8 @@ without additional interaction with the application.
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_curses_resize_term_impl(PyObject *module, int nlines, int ncols)
|
_curses_resize_term_impl(PyObject *module, short nlines, short ncols)
|
||||||
/*[clinic end generated code: output=9e26d8b9ea311ed2 input=2197edd05b049ed4]*/
|
/*[clinic end generated code: output=46c6d749fa291dbd input=276afa43d8ea7091]*/
|
||||||
{
|
{
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
|
|
||||||
|
|
|
@ -3693,25 +3693,55 @@ PyDoc_STRVAR(_curses_resizeterm__doc__,
|
||||||
{"resizeterm", _PyCFunction_CAST(_curses_resizeterm), METH_FASTCALL, _curses_resizeterm__doc__},
|
{"resizeterm", _PyCFunction_CAST(_curses_resizeterm), METH_FASTCALL, _curses_resizeterm__doc__},
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_curses_resizeterm_impl(PyObject *module, int nlines, int ncols);
|
_curses_resizeterm_impl(PyObject *module, short nlines, short ncols);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_curses_resizeterm(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
_curses_resizeterm(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
PyObject *return_value = NULL;
|
||||||
int nlines;
|
short nlines;
|
||||||
int ncols;
|
short ncols;
|
||||||
|
|
||||||
if (!_PyArg_CheckPositional("resizeterm", nargs, 2, 2)) {
|
if (!_PyArg_CheckPositional("resizeterm", nargs, 2, 2)) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
nlines = PyLong_AsInt(args[0]);
|
{
|
||||||
if (nlines == -1 && PyErr_Occurred()) {
|
long ival = PyLong_AsLong(args[0]);
|
||||||
goto exit;
|
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 {
|
||||||
|
nlines = (short) ival;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ncols = PyLong_AsInt(args[1]);
|
{
|
||||||
if (ncols == -1 && PyErr_Occurred()) {
|
long ival = PyLong_AsLong(args[1]);
|
||||||
goto exit;
|
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);
|
return_value = _curses_resizeterm_impl(module, nlines, ncols);
|
||||||
|
|
||||||
|
@ -3744,25 +3774,55 @@ PyDoc_STRVAR(_curses_resize_term__doc__,
|
||||||
{"resize_term", _PyCFunction_CAST(_curses_resize_term), METH_FASTCALL, _curses_resize_term__doc__},
|
{"resize_term", _PyCFunction_CAST(_curses_resize_term), METH_FASTCALL, _curses_resize_term__doc__},
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_curses_resize_term_impl(PyObject *module, int nlines, int ncols);
|
_curses_resize_term_impl(PyObject *module, short nlines, short ncols);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_curses_resize_term(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
_curses_resize_term(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
PyObject *return_value = NULL;
|
||||||
int nlines;
|
short nlines;
|
||||||
int ncols;
|
short ncols;
|
||||||
|
|
||||||
if (!_PyArg_CheckPositional("resize_term", nargs, 2, 2)) {
|
if (!_PyArg_CheckPositional("resize_term", nargs, 2, 2)) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
nlines = PyLong_AsInt(args[0]);
|
{
|
||||||
if (nlines == -1 && PyErr_Occurred()) {
|
long ival = PyLong_AsLong(args[0]);
|
||||||
goto exit;
|
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 {
|
||||||
|
nlines = (short) ival;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ncols = PyLong_AsInt(args[1]);
|
{
|
||||||
if (ncols == -1 && PyErr_Occurred()) {
|
long ival = PyLong_AsLong(args[1]);
|
||||||
goto exit;
|
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);
|
return_value = _curses_resize_term_impl(module, nlines, ncols);
|
||||||
|
|
||||||
|
@ -4318,4 +4378,4 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored
|
||||||
#ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF
|
#ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF
|
||||||
#define _CURSES_USE_DEFAULT_COLORS_METHODDEF
|
#define _CURSES_USE_DEFAULT_COLORS_METHODDEF
|
||||||
#endif /* !defined(_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