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)