Skip to content

Commit e3759ab

Browse files
committed
GH-103929: handle long input lines with PyOS_InputHook
If: - stdin is in line buffer mode - the readline module is not loaded - not on windows - a GUI toolkit has installd PyOS_InputHook Then, if the user enters lines longer than 98 characters into `input`: - user calls `input(...)` - user types/pastes a line longer than 98 characters + 1 newline - PyOS_InputHook returns - the first 99 characters are returned - the last character is not a new line so we go back to my_fgets - the PyOS_InputHook blocks because despite there being value in the buffer, stdin does not flag itself as ready to be read again - user hits enter again and to finish reading the input - the extra new line comes out the next time the user calls input This fixes this bug by passing the currently read number of characters to `my_fgets` to skip the input hook when reading out a long buffer. closes #103929
1 parent 904aef9 commit e3759ab

File tree

2 files changed

+5
-3
lines changed

2 files changed

+5
-3
lines changed

Doc/c-api/veryhigh.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ the same library that the Python runtime is using.
167167
event loops, as done in the :file:`Modules/_tkinter.c` in the
168168
Python source code.
169169
170+
This function should block until stdin is readable.
171+
170172
.. versionchanged:: 3.12
171173
This function is only called from the
172174
:ref:`main interpreter <sub-interpreter-support>`.

Parser/myreadline.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ int (*PyOS_InputHook)(void) = NULL;
3030
except if _PyOS_InterruptOccurred() returns true. */
3131

3232
static int
33-
my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp)
33+
my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp, int n)
3434
{
3535
#ifdef MS_WINDOWS
3636
HANDLE handle;
@@ -45,7 +45,7 @@ my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp)
4545
#endif
4646

4747
while (1) {
48-
if (PyOS_InputHook != NULL &&
48+
if (PyOS_InputHook != NULL && n == 0 &&
4949
// GH-104668: See PyOS_ReadlineFunctionPointer's comment below...
5050
_Py_IsMainInterpreter(tstate->interp))
5151
{
@@ -325,7 +325,7 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
325325
return NULL;
326326
}
327327
p = pr;
328-
int err = my_fgets(tstate, p + n, (int)incr, sys_stdin);
328+
int err = my_fgets(tstate, p + n, (int)incr, sys_stdin, n);
329329
if (err == 1) {
330330
// Interrupt
331331
PyMem_RawFree(p);

0 commit comments

Comments
 (0)