Skip to content

Commit a72cfed

Browse files
committed
Fix GH-14780: p(f)sockopen overflow on timeout argument.
1 parent cd67080 commit a72cfed

File tree

4 files changed

+43
-7
lines changed

4 files changed

+43
-7
lines changed

ext/standard/file.h

+6
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ PHPAPI ssize_t php_fputcsv(php_stream *stream, zval *fields, char delimiter, cha
6060
#define PHP_FILE_APPEND (1 << 3)
6161
#define PHP_FILE_NO_DEFAULT_CONTEXT (1 << 4)
6262

63+
#ifndef _WIN32
64+
#define PHP_TIMEOUT_ULL_MAX ULLONG_MAX
65+
#else
66+
#define PHP_TIMEOUT_ULL_MAX UINT64_MAX
67+
#endif
68+
6369
typedef enum _php_meta_tags_token {
6470
TOK_EOF = 0,
6571
TOK_OPENTAG,

ext/standard/fsock.c

+18-5
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,27 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
7373
}
7474

7575
/* prepare the timeout value for use */
76+
if (timeout < 0.0 || timeout > (double) PHP_TIMEOUT_ULL_MAX / 1000000.0) {
77+
if (port > 0) {
78+
efree(hostname);
79+
}
80+
81+
if (hashkey) {
82+
efree(hashkey);
83+
}
84+
85+
zend_argument_value_error(6, "must be between 0 and " ZEND_ULONG_FMT, (PHP_TIMEOUT_ULL_MAX / 1000000.0));
86+
RETURN_THROWS();
87+
} else {
7688
#ifndef PHP_WIN32
77-
conv = (time_t) (timeout * 1000000.0);
78-
tv.tv_sec = conv / 1000000;
89+
conv = (time_t) (timeout * 1000000.0);
90+
tv.tv_sec = conv / 1000000;
7991
#else
80-
conv = (long) (timeout * 1000000.0);
81-
tv.tv_sec = conv / 1000000;
92+
conv = (long) (timeout * 1000000.0);
93+
tv.tv_sec = conv / 1000000;
8294
#endif
83-
tv.tv_usec = conv % 1000000;
95+
tv.tv_usec = conv % 1000000;
96+
}
8497

8598
stream = php_stream_xport_create(hostname, hostname_len, REPORT_ERRORS,
8699
STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, hashkey, &tv, NULL, &errstr, &err);

ext/standard/streamsfuncs.c

-2
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,11 @@
3333
#ifndef PHP_WIN32
3434
#define php_select(m, r, w, e, t) select(m, r, w, e, t)
3535
typedef unsigned long long php_timeout_ull;
36-
#define PHP_TIMEOUT_ULL_MAX ULLONG_MAX
3736
#else
3837
#include "win32/select.h"
3938
#include "win32/sockets.h"
4039
#include "win32/console.h"
4140
typedef unsigned __int64 php_timeout_ull;
42-
#define PHP_TIMEOUT_ULL_MAX UINT64_MAX
4341
#endif
4442

4543
#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)))
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
GH-14780: p(f)sockopen overflow on timeout.
3+
--FILE--
4+
<?php
5+
$code = null;
6+
$err = null;
7+
try {
8+
pfsockopen('udp://127.0.0.1', '63844', $code, $err, (PHP_INT_MAX/100000)+1);
9+
} catch (\ValueError $e) {
10+
echo $e->getMessage() . PHP_EOL;
11+
}
12+
try {
13+
pfsockopen('udp://127.0.0.1', '63844', $code, $err, (PHP_INT_MIN/100000)-1);
14+
} catch (\ValueError $e) {
15+
echo $e->getMessage();
16+
}
17+
--EXPECTF--
18+
pfsockopen(): Argument #6 must be between 0 and %s
19+
pfsockopen(): Argument #6 must be between 0 and %s

0 commit comments

Comments
 (0)