From 6f51b1e8c44e2c9ffd563022f376b79919e0acf5 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 3 Jul 2024 12:39:54 +0100 Subject: [PATCH] Fix GH-14780: p(f)sockopen overflow on timeout argument. --- ext/standard/fsock.c | 19 +++++++++++++++---- ext/standard/tests/streams/gh14780.phpt | 13 +++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 ext/standard/tests/streams/gh14780.phpt diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c index 9e1a53c0ec2a0..b7353865da8c0 100644 --- a/ext/standard/fsock.c +++ b/ext/standard/fsock.c @@ -30,6 +30,7 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent) char *host; size_t host_len; zend_long port = -1; + zend_ulong ltimeout; zval *zerrno = NULL, *zerrstr = NULL; double timeout; bool timeout_is_null = 1; @@ -73,13 +74,23 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent) } /* prepare the timeout value for use */ + ltimeout = (zend_ulong)(timeout * 1000000.0); + if (ltimeout > LONG_MAX) { + if (port > 0) { + efree(hostname); + } + if (hashkey) { + efree(hashkey); + } + zend_argument_value_error(6, "must be between 0 and " ZEND_LONG_FMT, (LONG_MAX / 1000000)); + RETURN_THROWS(); + } #ifndef PHP_WIN32 - conv = (time_t) (timeout * 1000000.0); - tv.tv_sec = conv / 1000000; + conv = (time_t) (ltimeout); #else - conv = (long) (timeout * 1000000.0); - tv.tv_sec = conv / 1000000; + conv = (long) (ltimeout); #endif + tv.tv_sec = conv / 1000000; tv.tv_usec = conv % 1000000; stream = php_stream_xport_create(hostname, hostname_len, REPORT_ERRORS, diff --git a/ext/standard/tests/streams/gh14780.phpt b/ext/standard/tests/streams/gh14780.phpt new file mode 100644 index 0000000000000..57b216c618c0e --- /dev/null +++ b/ext/standard/tests/streams/gh14780.phpt @@ -0,0 +1,13 @@ +--TEST-- +GH-14780: p(f)sockopen overflow on timeout. +--FILE-- +getMessage(); +} +--EXPECTF-- +pfsockopen(): Argument #6 must be between 0 and %s