Skip to content

Commit 281588a

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 920b3df commit 281588a

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
@@ -36,7 +36,7 @@ int (*PyOS_InputHook)(void) = NULL;
3636
except if _PyOS_InterruptOccurred() returns true. */
3737

3838
static int
39-
my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp)
39+
my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp, int n)
4040
{
4141
#ifdef MS_WINDOWS
4242
HANDLE handle;
@@ -51,7 +51,7 @@ my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp)
5151
#endif
5252

5353
while (1) {
54-
if (PyOS_InputHook != NULL &&
54+
if (PyOS_InputHook != NULL && n == 0 &&
5555
// GH-104668: See PyOS_ReadlineFunctionPointer's comment below...
5656
_Py_IsMainInterpreter(tstate->interp))
5757
{
@@ -331,7 +331,7 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
331331
return NULL;
332332
}
333333
p = pr;
334-
int err = my_fgets(tstate, p + n, (int)incr, sys_stdin);
334+
int err = my_fgets(tstate, p + n, (int)incr, sys_stdin, n);
335335
if (err == 1) {
336336
// Interrupt
337337
PyMem_RawFree(p);

0 commit comments

Comments
 (0)