From c0b4e8d5bcd1db8e5dc36e0e7ee7e5b62a48254d Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sun, 21 Jun 2026 08:05:21 -0400 Subject: [PATCH] Fix posix_getpwnam()/posix_getpwuid() crash on NULL passwd fields php_posix_passwd_to_array() passed pw_name, pw_passwd, pw_gecos, pw_dir and pw_shell straight to add_assoc_string() with no NULL guard, so a NULL field segfaults via zend_string_init(). glibc's files NSS backend normalizes empty fields to "", but third-party NSS modules (nss-systemd, nss-ldap, sssd and other directory backends) populate struct passwd directly and may leave fields NULL. Guard each string field and emit null instead, mirroring the existing pw/gr handling in php_posix_group_to_array(). --- ext/posix/posix.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/ext/posix/posix.c b/ext/posix/posix.c index 8578056b28da..38f7eaa41860 100644 --- a/ext/posix/posix.c +++ b/ext/posix/posix.c @@ -910,13 +910,33 @@ int php_posix_passwd_to_array(struct passwd *pw, zval *return_value) /* {{{ */ if (NULL == return_value || Z_TYPE_P(return_value) != IS_ARRAY) return 0; - add_assoc_string(return_value, "name", pw->pw_name); - add_assoc_string(return_value, "passwd", pw->pw_passwd); - add_assoc_long (return_value, "uid", pw->pw_uid); - add_assoc_long (return_value, "gid", pw->pw_gid); - add_assoc_string(return_value, "gecos", pw->pw_gecos); - add_assoc_string(return_value, "dir", pw->pw_dir); - add_assoc_string(return_value, "shell", pw->pw_shell); + if (pw->pw_name) { + add_assoc_string(return_value, "name", pw->pw_name); + } else { + add_assoc_null(return_value, "name"); + } + if (pw->pw_passwd) { + add_assoc_string(return_value, "passwd", pw->pw_passwd); + } else { + add_assoc_null(return_value, "passwd"); + } + add_assoc_long(return_value, "uid", pw->pw_uid); + add_assoc_long(return_value, "gid", pw->pw_gid); + if (pw->pw_gecos) { + add_assoc_string(return_value, "gecos", pw->pw_gecos); + } else { + add_assoc_null(return_value, "gecos"); + } + if (pw->pw_dir) { + add_assoc_string(return_value, "dir", pw->pw_dir); + } else { + add_assoc_null(return_value, "dir"); + } + if (pw->pw_shell) { + add_assoc_string(return_value, "shell", pw->pw_shell); + } else { + add_assoc_null(return_value, "shell"); + } return 1; } /* }}} */