From a160ab3d03f5897d186e19edab64fdeb9b921e40 Mon Sep 17 00:00:00 2001 From: lacatoire Date: Mon, 24 Aug 2026 09:11:33 +0200 Subject: [PATCH] Fix wrong argument number and UB in fsockopen timeout error 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 zend_ulong before the call. --- NEWS | 2 ++ ext/standard/fsock.c | 2 +- .../fsockopen_timeout_out_of_range.phpt | 19 +++++++++++++++++++ ext/standard/tests/streams/gh14780.phpt | 8 ++++---- 4 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 ext/standard/tests/network/fsockopen_timeout_out_of_range.phpt diff --git a/NEWS b/NEWS index d25d441ca8b5..2fc9b3f83766 100644 --- a/NEWS +++ b/NEWS @@ -39,6 +39,8 @@ PHP NEWS with no other live PDO handle. (iliaal) - Standard: + . Fixed GH-23338 (fsockopen()/pfsockopen() ValueError reported wrong + argument number for $timeout). (lacatoire) . Fixed a memory leak in array_merge_recursive() when the recursive merge of an object converted to an array fails. (David Carlier) diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c index c8e6ed08e4c0..6dd07049e021 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 " ZEND_ULONG_FMT, (zend_ulong)((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 000000000000..575db4690fb9 --- /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-- +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 064e496b1753..c0fc4e621a9d 100644 --- a/ext/standard/tests/streams/gh14780.phpt +++ b/ext/standard/tests/streams/gh14780.phpt @@ -31,8 +31,8 @@ try { } ?> --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