Fix GH-14780: p(f)sockopen overflow on timeout argument.

close GH-14785
This commit is contained in:
David Carlier 2024-07-22 12:53:54 +01:00
parent 40551dd74b
commit ba909d7c43
No known key found for this signature in database
GPG key ID: D308BD11AB42D054
5 changed files with 63 additions and 7 deletions

1
NEWS
View file

@ -32,6 +32,7 @@ PHP NEWS
- Standard:
. Fix passing non-finite timeout values in stream functions. (nielsdos)
. Fixed GH-14780 p(f)sockopen timeout overflow. (David Carlier)
- Streams:
. Fixed bug GH-15028 (Memory leak in ext/phar/stream.c). (nielsdos)

View file

@ -60,6 +60,12 @@ PHPAPI ssize_t php_fputcsv(php_stream *stream, zval *fields, char delimiter, cha
#define PHP_FILE_APPEND (1 << 3)
#define PHP_FILE_NO_DEFAULT_CONTEXT (1 << 4)
#ifndef _WIN32
#define PHP_TIMEOUT_ULL_MAX ULLONG_MAX
#else
#define PHP_TIMEOUT_ULL_MAX UINT64_MAX
#endif
typedef enum _php_meta_tags_token {
TOK_EOF = 0,
TOK_OPENTAG,

View file

@ -73,6 +73,18 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
}
/* prepare the timeout value for use */
if (timeout != -1.0 && !(timeout >= 0.0 && timeout <= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0)) {
if (port > 0) {
efree(hostname);
}
if (hashkey) {
efree(hashkey);
}
zend_argument_value_error(6, "must be -1 or between 0 and " ZEND_ULONG_FMT, (PHP_TIMEOUT_ULL_MAX / 1000000.0));
RETURN_THROWS();
} else {
#ifndef PHP_WIN32
conv = (time_t) (timeout * 1000000.0);
tv.tv_sec = conv / 1000000;
@ -81,6 +93,7 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
tv.tv_sec = conv / 1000000;
#endif
tv.tv_usec = conv % 1000000;
}
stream = php_stream_xport_create(hostname, hostname_len, REPORT_ERRORS,
STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, hashkey, &tv, NULL, &errstr, &err);

View file

@ -33,13 +33,11 @@
#ifndef PHP_WIN32
#define php_select(m, r, w, e, t) select(m, r, w, e, t)
typedef unsigned long long php_timeout_ull;
#define PHP_TIMEOUT_ULL_MAX ULLONG_MAX
#else
#include "win32/select.h"
#include "win32/sockets.h"
#include "win32/console.h"
typedef unsigned __int64 php_timeout_ull;
#define PHP_TIMEOUT_ULL_MAX UINT64_MAX
#endif
#define GET_CTX_OPT(stream, wrapper, name, val) (PHP_STREAM_CONTEXT(stream) && NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), wrapper, name)))

View file

@ -0,0 +1,38 @@
--TEST--
GH-14780: p(f)sockopen overflow on timeout.
--SKIPIF--
<?php
if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only");
?>
--FILE--
<?php
$code = null;
$err = null;
try {
pfsockopen('udp://127.0.0.1', '63844', $code, $err, (PHP_INT_MAX/100000)+1);
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
pfsockopen('udp://127.0.0.1', '63844', $code, $err, (PHP_INT_MIN/100000)-1);
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
var_dump(pfsockopen('udp://127.0.0.1', '63844', $code, $err, -1));
try {
pfsockopen('udp://127.0.0.1', '63844', $code, $err, NAN);
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
pfsockopen('udp://127.0.0.1', '63844', $code, $err, INF);
} catch (\ValueError $e) {
echo $e->getMessage();
}
?>
--EXPECTF--
pfsockopen(): Argument #6 must be -1 or between 0 and %s
pfsockopen(): Argument #6 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