Commit f211ed307da for php
commit f211ed307dac3b567948b45a8057088b8e711ea8
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date: Thu Sep 24 09:00:35 2026 -0400
ext/standard: Retry getpwnam_r() on ERANGE in php_get_uid_by_name()
getpwnam_r() reports a too small buffer with ERANGE, but the ZTS code
path in php_get_uid_by_name() retried only on EAGAIN, so chown() and
lchown() failed to resolve a user name whose passwd entry did not fit
the initial buffer. Debug builds start from a 1-byte buffer, so every
user name lookup failed there.
Closes GH-24021
diff --git a/NEWS b/NEWS
index 34db44b5c89..72ed4ce12b6 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,10 @@ PHP NEWS
. Fixed bug GH-20890 (Segfault in zval_undefined_cv with non-simple property
hook with minimal tracing JIT). (ndossche)
+- Standard:
+ . Fixed chown() and lchown() failing to resolve user names in ZTS builds
+ when getpwnam_r() needs a larger buffer. (Ilia Alshanetsky)
+
22 Oct 2026, PHP 8.4.27
- BCMath:
diff --git a/ext/standard/filestat.c b/ext/standard/filestat.c
index 705370a5906..4d22a0f98ee 100644
--- a/ext/standard/filestat.c
+++ b/ext/standard/filestat.c
@@ -434,7 +434,7 @@ PHPAPI zend_result php_get_uid_by_name(const char *name, uid_t *uid)
try_again:
err = getpwnam_r(name, &pw, pwbuf, pwbuflen, &retpwptr);
if (err != 0 || retpwptr == NULL) {
- if (err == EAGAIN) {
+ if (err == ERANGE) {
pwbuflen *= 2;
pwbuf = erealloc(pwbuf, pwbuflen);
goto try_again;
diff --git a/ext/standard/tests/file/chown_user_name.phpt b/ext/standard/tests/file/chown_user_name.phpt
new file mode 100644
index 00000000000..6f8c9b2da1e
--- /dev/null
+++ b/ext/standard/tests/file/chown_user_name.phpt
@@ -0,0 +1,25 @@
+--TEST--
+chown() and lchown() with a user name
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) == 'WIN') die('skip no windows support');
+if (!function_exists("posix_getpwuid")) die("skip no posix_getpwuid()");
+if (posix_getpwuid(posix_getuid()) === false) die("skip current user has no passwd entry");
+?>
+--FILE--
+<?php
+$filename = __DIR__ . DIRECTORY_SEPARATOR . 'chown_user_name.txt';
+$name = posix_getpwuid(posix_getuid())['name'];
+
+var_dump(touch($filename));
+var_dump(chown($filename, $name));
+var_dump(lchown($filename, $name));
+?>
+--CLEAN--
+<?php
+@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'chown_user_name.txt');
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)