10000 gh-134209: use heap-allocated memory in `_curses.window.{instr,getstr}` by zydtiger · Pull Request #134283 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-134209: use heap-allocated memory in _curses.window.{instr,getstr} #134283

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 34 commits into from
May 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
46a6f47
made curses buffer heap allocated instead of stack
zydtiger May 19, 2025
7eeb8f6
change docs to explicitly mention the max buffer size
zydtiger May 19, 2025
d5aa3db
remove unintentional changes
zydtiger May 19, 2025
020d798
📜🤖 Added by blurb_it.
blurb-it[bot] May 19, 2025
823fa38
reword news to satify linter
zydtiger May 19, 2025
571091d
Merge branch 'main' into fix-issue-134209
zydtiger May 19, 2025
1e7edf4
Merge branch 'main' into fix-issue-134209
zydtiger May 19, 2025
0cb5fe0
Reword the ReST news entry.
gpshead May 20, 2025
63a3ed2
use rtn value from winnstr instead of strlen
zydtiger May 20, 2025
58d6cde
changing GetStr() function to behave similarly too
zydtiger May 20, 2025
82c9b1c
updated curses doc for getstr function
zydtiger May 20, 2025
04a9b14
Merge branch 'main' into fix-issue-134209
zydtiger May 20, 2025
cbce07b
Update Doc/library/curses.rst
zydtiger May 20, 2025
dfd210d
Update Doc/library/curses.rst
zydtiger May 20, 2025
ad832bd
Update Misc/NEWS.d/next/Library/2025-05-19-20-59-06.gh-issue-134209.a…
zydtiger May 20, 2025
f7a51f9
Update Modules/_cursesmodule.c
zydtiger May 20, 2025
e5597a2
Update Modules/_cursesmodule.c
zydtiger May 20, 2025
5dd4304
Update Modules/_cursesmodule.c
zydtiger May 20, 2025
d868088
Update instr with proper return error handling
zydtiger May 20, 2025
1a519cb
Update Modules/_cursesmodule.c
zydtiger May 20, 2025
87bb8cb
Merge branch 'main' into fix-issue-134209
zydtiger May 20, 2025
083f855
change to strlen and better memory safety
zydtiger May 20, 2025
20046cb
Update Doc/library/curses.rst
zydtiger May 20, 2025
fd5c3f4
Update Doc/library/curses.rst
zydtiger May 20, 2025
c061f89
change from const int to Py_ssize_t
zydtiger May 20, 2025
d11b04f
Merge branch 'main' into fix-issue-134209
zydtiger May 20, 2025
c3323a3
fix indent
zydtiger May 20, 2025
12d4a5f
Update Doc/library/curses.rst
zydtiger May 20, 2025
769ba15
add mem allocation guard
zydtiger May 20, 2025
59b49b4
remove trailing spaces in line
zydtiger May 20, 2025
5bfa810
Merge branch 'main' into fix-issue-134209
zydtiger May 20, 2025
6510d09
fix indent
zydtiger May 20, 2025
6eccdc9
update versionchanged to mention it was an increase.
gpshead May 20, 2025
769bb87
explicitly use versionchanged 3.14 as that is its own branch now.
gpshead May 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Doc/library/curses.rst
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,10 @@ the following methods and attributes:
window.getstr(y, x, n)

Read a bytes object from the user, with primitive line editing capacity.
The maximum value for *n* is 2047.

.. versionchanged:: 3.14
The maximum value for *n* was increased from 1023 to 2047.


.. method:: window.getyx()
Expand Down Expand Up @@ -1079,6 +1083,10 @@ the following methods and attributes:
current cursor position, or at *y*, *x* if specified. Attributes are stripped
from the characters. If *n* is specified, :meth:`instr` returns a string
at most *n* characters long (exclusive of the trailing NUL).
The maximum value for *n* is 2047.

.. versionchanged:: 3.14
The maximum value for *n* was increased from 1023 to 2047.


.. method:: window.is_linetouched(line)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:mod:`curses`: The :meth:`curses.window.instr` and :meth:`curses.window.getstr`
methods now allocate their internal buffer on the heap instead of the stack;
in addition, the max buffer size is increased from 1023 to 2047.
102 changes: 69 additions & 33 deletions Modules/_cursesmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1816,7 +1816,7 @@ _curses.window.getstr
x: int
X-coordinate.
]
n: int = 1023
n: int = 2047
Maximal number of characters.
/

Expand All @@ -1829,62 +1829,80 @@ PyCursesWindow_GetStr(PyObject *op, PyObject *args)
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);

int x, y, n;
char rtn[1024]; /* This should be big enough.. I hope */
int rtn2;
int rtn;

/* could make the buffer size larger/dynamic */
Py_ssize_t max_buf_size = 2048;
PyObject *result = PyBytes_FromStringAndSize(NULL, max_buf_size);
if (result == NULL)
return NULL;
char *buf = PyBytes_AS_STRING(result);

switch (PyTuple_Size(args)) {
case 0:
Py_BEGIN_ALLOW_THREADS
rtn2 = wgetnstr(self->win,rtn, 1023);
rtn = wgetnstr(self->win, buf, max_buf_size - 1);
Py_END_ALLOW_THREADS
break;
case 1:
if (!PyArg_ParseTuple(args,"i;n", &n))
return NULL;
goto error;
if (n < 0) {
PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
return NULL;
goto error;
}
Py_BEGIN_ALLOW_THREADS
rtn2 = wgetnstr(self->win, rtn, Py_MIN(n, 1023));
rtn = wgetnstr(self->win, buf, Py_MIN(n, max_buf_size - 1));
Py_END_ALLOW_THREADS
break;
case 2:
if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x))
return NULL;
goto error;
Py_BEGIN_ALLOW_THREADS
#ifdef STRICT_SYSV_CURSES
rtn2 = wmove(self->win,y,x)==ERR ? ERR : wgetnstr(self->win, rtn, 1023);
rtn = wmove(self->win,y,x)==ERR ? ERR : wgetnstr(self->win, rtn, max_buf_size - 1);
#else
rtn2 = mvwgetnstr(self->win,y,x,rtn, 1023);
rtn = mvwgetnstr(self->win,y,x,buf, max_buf_size - 1);
#endif
Py_END_ALLOW_THREADS
break;
case 3:
if (!PyArg_ParseTuple(args,"iii;y,x,n", &y, &x, &n))
return NULL;
goto error;
if (n < 0) {
PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
return NULL;
goto error;
}
#ifdef STRICT_SYSV_CURSES
Py_BEGIN_ALLOW_THREADS
rtn2 = wmove(self->win,y,x)==ERR ? ERR :
wgetnstr(self->win, rtn, Py_MIN(n, 1023));
rtn = wmove(self->win,y,x)==ERR ? ERR :
wgetnstr(self->win, rtn, Py_MIN(n, max_buf_size - 1));
Py_END_ALLOW_THREADS
#else
Py_BEGIN_ALLOW_THREADS
rtn2 = mvwgetnstr(self->win, y, x, rtn, Py_MIN(n, 1023));
rtn = mvwgetnstr(self->win, y, x, buf, Py_MIN(n, max_buf_size - 1));
Py_END_ALLOW_THREADS
#endif
break;
default:
PyErr_SetString(PyExc_TypeError, "getstr requires 0 to 3 arguments");
goto error;
}

if (rtn == ERR) {
Py_DECREF(result);
return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
}

if (_PyBytes_Resize(&result, strlen(buf)) < 0) {
return NULL;
}
if (rtn2 == ERR)
rtn[0] = 0;
return PyBytes_FromString(rtn);

return result;

error:
Py_DECREF(result);
return NULL;
}

/*[clinic input]
Expand Down Expand Up @@ -2023,7 +2041,7 @@ _curses.window.instr
x: int
X-coordinate.
]
n: int = 1023
n: int = 2047
Maximal number of characters.
/

Expand All @@ -2040,43 +2058,61 @@ PyCursesWindow_InStr(PyObject *op, PyObject *args)
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);

int x, y, n;
char rtn[1024]; /* This should be big enough.. I hope */
int rtn2;
int rtn;

/* could make the buffer size larger/dynamic */
Py_ssize_t max_buf_size = 2048;
PyObject *result = PyBytes_FromStringAndSize(NULL, max_buf_size);
if (result == NULL)
return NULL;
char *buf = PyBytes_AS_STRING(result);

switch (PyTuple_Size(args)) {
case 0:
rtn2 = winnstr(self->win,rtn, 1023);
rtn = winnstr(self->win, buf, max_buf_size - 1);
break;
case 1:
if (!PyArg_ParseTuple(args,"i;n", &n))
return NULL;
goto error;
if (n < 0) {
PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
return NULL;
goto error;
}
rtn2 = winnstr(self->win, rtn, Py_MIN(n, 1023));
rtn = winnstr(self->win, buf, Py_MIN(n, max_buf_size - 1));
break;
case 2:
if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x))
return NULL;
rtn2 = mvwinnstr(self->win,y,x,rtn,1023);
goto error;
rtn = mvwinnstr(self->win, y, x, buf, max_buf_size - 1);
break;
case 3:
if (!PyArg_ParseTuple(args, "iii;y,x,n", &y, &x, &n))
return NULL;
goto error;
if (n < 0) {
PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
return NULL;
goto error;
}
rtn2 = mvwinnstr(self->win, y, x, rtn, Py_MIN(n,1023));
rtn = mvwinnstr(self->win, y, x, buf, Py_MIN(n, max_buf_size - 1));
break;
default:
PyErr_SetString(PyExc_TypeError, "instr requires 0 or 3 arguments");
goto error;
}

if (rtn == ERR) {
Py_DECREF(result);
return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
}

if (_PyBytes_Resize(&result, strlen(buf)) < 0) {
return NULL;
}
if (rtn2 == ERR)
rtn[0] = 0;
return PyBytes_FromString(rtn);

return result;

error:
Py_DECREF(result);
return NULL;
}

/*[clinic input]
Expand Down
Loading
0