Commit 8d0d6307aac for php.net

commit 8d0d6307aaca39223d5dd9461dc8dea90286a3bb
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Fri Aug 21 13:13:21 2026 -0400

    Fix three Win32-only defects in proc_open descriptor handling

    init_process_info() memset the pointer parameter instead of the
    PROCESS_INFORMATION structure it points at, leaving the struct
    uninitialized before CreateProcessW(). Zero it through the pointer.

    find_comspec_nt() dereferences *comspec in its cleanup while the
    caller only assigns it on success, so a failed SearchPathW() read an
    indeterminate value. Initialize the caller's variable to NULL.

    set_proc_descriptor_to_blackhole() tested CreateFileA() against NULL,
    but CreateFileA() signals failure with INVALID_HANDLE_VALUE, so a
    failed open went undetected and an invalid handle was inherited by
    the child. Test against INVALID_HANDLE_VALUE.

    Closes GH-23412

diff --git a/NEWS b/NEWS
index d81d3170a6f..51580b6c778 100644
--- a/NEWS
+++ b/NEWS
@@ -50,6 +50,11 @@ PHP                                                                        NEWS
   . Fixed a crash when SQLite3::close() is called from a userland callback.
     (Ilia Alshanetsky)

+- Standard:
+  . Fixed three Windows-only proc_open() defects: an uninitialized
+    PROCESS_INFORMATION, an indeterminate comspec pointer after a failed
+    lookup, and an unchecked CreateFileA() failure. (Ilia Alshanetsky)
+
 - XSL:
   . Fixed bug GH-23730 (use-after-free when XSLTProcessor::importStylesheet()
     is called during a transformation). (David Carlier)
diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c
index d2d51de5a85..bd4cf7a0a0e 100644
--- a/ext/standard/proc_open.c
+++ b/ext/standard/proc_open.c
@@ -695,7 +695,7 @@ static void init_startup_info(STARTUPINFOW *si, descriptorspec_item *descriptors

 static void init_process_info(PROCESS_INFORMATION *pi)
 {
-	memset(&pi, 0, sizeof(pi));
+	memset(pi, 0, sizeof(*pi));
 }

 /* on success, returns length of *comspec, which then needs to be efree'd by caller */
@@ -746,7 +746,7 @@ static size_t find_comspec_nt(wchar_t **comspec)

 static zend_result convert_command_to_use_shell(wchar_t **cmdw, size_t cmdw_len)
 {
-	wchar_t *comspec;
+	wchar_t *comspec = NULL;
 	size_t len = find_comspec_nt(&comspec);
 	if (len == 0) {
 		php_error_docref(NULL, E_WARNING, "Command conversion failed");
@@ -829,7 +829,7 @@ static zend_result set_proc_descriptor_to_blackhole(descriptorspec_item *desc)
 #ifdef PHP_WIN32
 	desc->childend = CreateFileA("nul", GENERIC_READ | GENERIC_WRITE,
 		FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
-	if (desc->childend == NULL) {
+	if (desc->childend == INVALID_HANDLE_VALUE) {
 		php_error_docref(NULL, E_WARNING, "Failed to open nul");
 		return FAILURE;
 	}