Commit dfdae429ca0 for php.net
commit dfdae429ca0933169ff7e79fb9a5bacd89f56d43
Author: Louis-Arnaud <la.catoire@gmail.com>
Date: Sun Sep 6 14:58:17 2026 +0200
Fix wrong argument number and UB in fsockopen timeout error (#23431)
php_fsockopen_stream() called zend_argument_value_error(6, ...) for the
$timeout parameter, but $timeout is the 5th argument. This caused the
error message to show "Argument #6" with no parameter name, since
get_function_arg_name() returns NULL when arg_num exceeds the actual
argument count.
The format string also contained ZEND_ULONG_FMT (which expects a zend_ulong)
but received a double expression, causing undefined behavior.
This is fixed by casting to uint64_t instead.
diff --git a/NEWS b/NEWS
index 41b26e5d094..ab8e20c7507 100644
--- a/NEWS
+++ b/NEWS
@@ -104,6 +104,8 @@ PHP NEWS
. Fixed read buffer compaction in php_stream_filter_flush(). (crystarm)
. Fixed bug GH-22410 (Incorrect float behavior with large numbers).
(arshidkv12)
+ . Fixed GH-23338 (fsockopen()/pfsockopen() ValueError reported wrong
+ argument number for $timeout). (lacatoire)
- SimpleXML:
. Fixed writing to a dimension of the object returned by attributes() not
diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c
index c8e6ed08e4c..bf60f610f84 100644
--- a/ext/standard/fsock.c
+++ b/ext/standard/fsock.c
@@ -107,7 +107,7 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
efree(hashkey);
}
- zend_argument_value_error(6, "must be -1 or between 0 and " ZEND_ULONG_FMT, ((double) PHP_TIMEOUT_ULL_MAX / 1000000.0));
+ zend_argument_value_error(5, "must be -1 or between 0 and %" PRIu64, (uint64_t) ((double) PHP_TIMEOUT_ULL_MAX / 1000000.0));
RETURN_THROWS();
} else {
#ifndef PHP_WIN32
diff --git a/ext/standard/tests/network/fsockopen_timeout_out_of_range.phpt b/ext/standard/tests/network/fsockopen_timeout_out_of_range.phpt
new file mode 100644
index 00000000000..575db4690fb
--- /dev/null
+++ b/ext/standard/tests/network/fsockopen_timeout_out_of_range.phpt
@@ -0,0 +1,19 @@
+--TEST--
+fsockopen() and pfsockopen(): ValueError for $timeout reports correct argument number and name
+--FILE--
+<?php
+try {
+ fsockopen('localhost', 80, $errno, $errstr, -2.0);
+} catch (Throwable $e) {
+ echo $e::class, ': ', $e->getMessage(), "\n";
+}
+
+try {
+ pfsockopen('localhost', 80, $errno, $errstr, -2.0);
+} catch (Throwable $e) {
+ echo $e::class, ': ', $e->getMessage(), "\n";
+}
+?>
+--EXPECTF--
+ValueError: fsockopen(): Argument #5 ($timeout) must be -1 or between 0 and %s
+ValueError: pfsockopen(): Argument #5 ($timeout) must be -1 or between 0 and %s
diff --git a/ext/standard/tests/streams/gh14780.phpt b/ext/standard/tests/streams/gh14780.phpt
index 064e496b175..c0fc4e621a9 100644
--- a/ext/standard/tests/streams/gh14780.phpt
+++ b/ext/standard/tests/streams/gh14780.phpt
@@ -31,8 +31,8 @@
}
?>
--EXPECTF--
-pfsockopen(): Argument #6 must be -1 or between 0 and %s
-pfsockopen(): Argument #6 must be -1 or between 0 and %s
+pfsockopen(): Argument #5 ($timeout) must be -1 or between 0 and %s
+pfsockopen(): Argument #5 ($timeout) must be -1 or between 0 and %s
resource(%d) of type (persistent stream)
-pfsockopen(): Argument #6 must be -1 or between 0 and %s
-pfsockopen(): Argument #6 must be -1 or between 0 and %s
+pfsockopen(): Argument #5 ($timeout) must be -1 or between 0 and %s
+pfsockopen(): Argument #5 ($timeout) must be -1 or between 0 and %s