[newlib-cygwin] Cygwin: pty: grow GetConsoleProcessList buffer in find_pcon_pty()

Takashi Yano via Cygwin-cvs <[email protected]> Tue, 30 Jun 2026 08:26:19 +0000 (GMT)
Newsgroups gmane.os.cygwin.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=3Dnewlib-cygwin.git;h=3D10140bec21e=
4433ddbfb2308c8a4052f3eaaafa4

commit 10140bec21e4433ddbfb2308c8a4052f3eaaafa4
Author: Johannes Schindelin <[email protected]>
Date:   Fri May 29 19:07:26 2026 +0200

    Cygwin: pty: grow GetConsoleProcessList buffer in find_pcon_pty()
   =20
    find_pcon_pty() was passing a fixed 128-DWORD stack array to
    GetConsoleProcessList(). If the calling Cygwin process happens to be
    attached to a console with more than 128 processes, the Win32
    function returns the required size and the buffer contents are
    undefined; the existing if-zero check did not catch that case, so
    the subsequent loop walked uninitialised data and could either miss
    the candidate pty or, worse, match against junk PIDs and return the
    wrong tty index.
   =20
    Adopt the buffer-too-small dance from
    fhandler_termios::get_console_process_id() in
    winsup/cygwin/fhandler/termios.cc, which already had to solve this
    problem and which also notes that the new condrv does not accept
    oversized first-call buffers
    (https://github.com/microsoft/terminal/issues/18264#issuecomment-251544=
8548).
    The buffer comes from tmp_pathbuf so the same NT_MAX_PATH cap
    (currently 1024 DWORDs, i.e. 4096 processes) applies; we bail out
    with -1 if even that is not enough rather than allocate unbounded
    memory or guess. Bumping the start-with size from 1 would defeat the
    condrv work-around mentioned above, so we keep the same one-element
    initial probe as termios.cc and let the loop grow.
   =20
    Fixes: 6eed1ef74869 ("Cygwin: pty: detect pcon-backed pty for non-Cygwi=
n-spawned children")
    Suggested-by: Takashi Yano <[email protected]>
    Assisted-by: Opus 4.7
    Signed-off-by: Johannes Schindelin <[email protected]>
    Reviewed-by: Takashi Yano <[email protected]>

Diff:
---
 winsup/cygwin/tty.cc | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc
index 667aa2682..ba65aca3d 100644
--- a/winsup/cygwin/tty.cc
+++ b/winsup/cygwin/tty.cc
@@ -19,6 +19,7 @@ details. */
 #include "cygheap.h"
 #include "pinfo.h"
 #include "shared_info.h"
+#include "tls_pbuf.h"
=20
 HANDLE NO_COPY tty_list::mutex =3D NULL;
=20
@@ -135,7 +136,9 @@ tty_list::init ()
 int
 tty_list::find_pcon_pty ()
 {
-  DWORD pids[128];
+  tmp_pathbuf tp;
+  DWORD *pids =3D (DWORD *) tp.c_get ();
+  const DWORD buf_size =3D NT_MAX_PATH / sizeof (DWORD);
   DWORD count =3D 0;
   bool got_pids =3D false;
=20
@@ -144,10 +147,20 @@ tty_list::find_pcon_pty ()
       if (!ttys[i].has_active_pcon ())
 	continue;
=20
-      /* Fetch the console process list lazily, only on first candidate. */
+      /* Fetch the console process list lazily, only on first candidate.
+	 The buffer-too-large dance mirrors the one in termios.cc's
+	 get_console_process_id() and works around new condrv's dislike
+	 of oversized first-call buffers, see
+	 https://github.com/microsoft/terminal/issues/18264#issuecomment-25154485=
48 */
       if (!got_pids)
 	{
-	  count =3D GetConsoleProcessList (pids, 128);
+	  DWORD buf_size1 =3D 1;
+	  while ((count =3D GetConsoleProcessList (pids, buf_size1)) > buf_size1)
+	    {
+	      if (count > buf_size)
+		return -1;
+	      buf_size1 =3D count;
+	    }
 	  if (!count)
 	    return -1;
 	  got_pids =3D true;