Skip to content

Commit 1e6fc5b

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 56c7176 commit 1e6fc5b

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
171173
.. c:var:: char* (*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *)
172174

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
(void)(PyOS_InputHook)();
5050
}
5151

@@ -319,7 +319,7 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
319319
return NULL;
320320
}
321321
p = pr;
322-
int err = my_fgets(tstate, p + n, (int)incr, sys_stdin);
322+
int err = my_fgets(tstate, p + n, (int)incr, sys_stdin, n);
323323
if (err == 1) {
324324
// Interrupt
325325
PyMem_RawFree(p);

0 commit comments

Comments
 (0)