Skip to content

Commit 1d13392

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 9a87ce8 commit 1d13392

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
@@ -143,6 +143,8 @@ the same library that the Python runtime is using.
143143
event loops, as done in the :file:`Modules/_tkinter.c` in the
144144
Python source code.
145145
146+
This function should block until stdin is readable.
147+
146148
.. versionchanged:: 3.12
147149
This function is only called from the
148150
:ref:`main interpreter <sub-interpreter-support>`.

Parser/myreadline.c

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

4040
static int
41-
my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp)
41+
my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp, int n)
4242
{
4343
#ifdef MS_WINDOWS
4444
HANDLE handle;
@@ -53,7 +53,7 @@ my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp)
5353
#endif
5454

5555
while (1) {
56-
if (PyOS_InputHook != NULL &&
56+
if (PyOS_InputHook != NULL && n == 0 &&
5757
// GH-104668: See PyOS_ReadlineFunctionPointer's comment below...
5858
_Py_IsMainInterpreter(tstate->interp))
5959
{
@@ -333,7 +333,7 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
333333
return NULL;
334334
}
335335
p = pr;
336-
int err = my_fgets(tstate, p + n, (int)incr, sys_stdin);
336+
int err = my_fgets(tstate, p + n, (int)incr, sys_stdin, n);
337337
if (err == 1) {
338338
// Interrupt
339339
PyMem_RawFree(p);

0 commit comments

Comments
 (0)