Skip to content

Commit 822dc1a

Browse files
committed
ext/standard: Improve handling of timeout values
1 parent 2d217f0 commit 822dc1a

File tree

1 file changed

+45
-44
lines changed

1 file changed

+45
-44
lines changed

ext/standard/streamsfuncs.c

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ typedef unsigned long long php_timeout_ull;
3434
#include "win32/select.h"
3535
#include "win32/sockets.h"
3636
#include "win32/console.h"
37+
#include "win32/time.h"
3738
typedef unsigned __int64 php_timeout_ull;
3839
#endif
3940

@@ -99,7 +100,6 @@ PHP_FUNCTION(stream_socket_client)
99100
zval *zerrno = NULL, *zerrstr = NULL, *zcontext = NULL;
100101
double timeout;
101102
bool timeout_is_null = 1;
102-
php_timeout_ull conv;
103103
struct timeval tv;
104104
char *hashkey = NULL;
105105
php_stream *stream = NULL;
@@ -129,26 +129,25 @@ PHP_FUNCTION(stream_socket_client)
129129

130130
context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
131131

132-
if (flags & PHP_STREAM_CLIENT_PERSISTENT) {
133-
spprintf(&hashkey, 0, "stream_socket_client__%s", ZSTR_VAL(host));
134-
}
135-
136132
/* prepare the timeout value for use */
137133
struct timeval *tv_pointer;
138-
if (timeout < 0.0 || timeout >= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0) {
134+
if (timeout < 0.0) {
135+
php_error_docref(NULL, E_WARNING, "timeout must greater than or equal to 0");
136+
if (UNEXPECTED(EG(exception))) {
137+
RETURN_THROWS();
138+
}
139139
tv_pointer = NULL;
140140
} else {
141-
conv = (php_timeout_ull) (timeout * 1000000.0);
142-
#ifdef PHP_WIN32
143-
tv.tv_sec = (long)(conv / 1000000);
144-
tv.tv_usec = (long)(conv % 1000000);
145-
#else
146-
tv.tv_sec = conv / 1000000;
147-
tv.tv_usec = conv % 1000000;
148-
#endif
141+
php_timeout_ull conv = (php_timeout_ull) (timeout * 1000000.0);
142+
tv.tv_sec = (time_t) (conv / 1000000);
143+
tv.tv_usec = (suseconds_t) (conv % 1000000);
149144
tv_pointer = &tv;
150145
}
151146

147+
if (flags & PHP_STREAM_CLIENT_PERSISTENT) {
148+
spprintf(&hashkey, 0, "stream_socket_client__%s", ZSTR_VAL(host));
149+
}
150+
152151
if (zerrno) {
153152
ZEND_TRY_ASSIGN_REF_LONG(zerrno, 0);
154153
}
@@ -262,7 +261,6 @@ PHP_FUNCTION(stream_socket_accept)
262261
bool timeout_is_null = 1;
263262
zval *zpeername = NULL;
264263
zend_string *peername = NULL;
265-
php_timeout_ull conv;
266264
struct timeval tv;
267265
php_stream *stream = NULL, *clistream = NULL;
268266
zval *zstream;
@@ -286,17 +284,16 @@ PHP_FUNCTION(stream_socket_accept)
286284

287285
/* prepare the timeout value for use */
288286
struct timeval *tv_pointer;
289-
if (timeout < 0.0 || timeout >= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0) {
287+
if (timeout < 0.0) {
288+
php_error_docref(NULL, E_WARNING, "timeout must greater than or equal to 0");
289+
if (UNEXPECTED(EG(exception))) {
290+
RETURN_THROWS();
291+
}
290292
tv_pointer = NULL;
291293
} else {
292-
conv = (php_timeout_ull) (timeout * 1000000.0);
293-
#ifdef PHP_WIN32
294-
tv.tv_sec = (long)(conv / 1000000);
295-
tv.tv_usec = (long)(conv % 1000000);
296-
#else
297-
tv.tv_sec = conv / 1000000;
298-
tv.tv_usec = conv % 1000000;
299-
#endif
294+
php_timeout_ull conv = (php_timeout_ull) (timeout * 1000000.0);
295+
tv.tv_sec = (time_t) (conv / 1000000);
296+
tv.tv_usec = (suseconds_t) (conv % 1000000);
300297
tv_pointer = &tv;
301298
}
302299

@@ -830,11 +827,16 @@ PHP_FUNCTION(stream_select)
830827
} else if (usec < 0) {
831828
zend_argument_value_error(5, "must be greater than or equal to 0");
832829
RETURN_THROWS();
830+
} else if (usec >= 1000000) {
831+
php_error_docref(NULL, E_WARNING, "must be less than 1000000");
832+
if (UNEXPECTED(EG(exception))) {
833+
RETURN_THROWS();
834+
}
833835
}
834836

835837
/* Windows, Solaris and BSD do not like microsecond values which are >= 1 sec */
836-
tv.tv_sec = (long)(sec + (usec / 1000000));
837-
tv.tv_usec = (long)(usec % 1000000);
838+
tv.tv_sec = (time_t)(sec + (usec / 1000000));
839+
tv.tv_usec = (suseconds_t)(usec % 1000000);
838840
tv_p = &tv;
839841
}
840842

@@ -1419,7 +1421,6 @@ PHP_FUNCTION(stream_set_timeout)
14191421
zend_long seconds, microseconds = 0;
14201422
struct timeval t;
14211423
php_stream *stream;
1422-
int argc = ZEND_NUM_ARGS();
14231424

14241425
ZEND_PARSE_PARAMETERS_START(2, 3)
14251426
Z_PARAM_RESOURCE(socket)
@@ -1430,25 +1431,25 @@ PHP_FUNCTION(stream_set_timeout)
14301431

14311432
php_stream_from_zval(stream, socket);
14321433

1433-
#ifdef PHP_WIN32
1434-
t.tv_sec = (long)seconds;
1435-
1436-
if (argc == 3) {
1437-
t.tv_usec = (long)(microseconds % 1000000);
1438-
t.tv_sec +=(long)(microseconds / 1000000);
1439-
} else {
1440-
t.tv_usec = 0;
1434+
if (seconds < 0) {
1435+
php_error_docref(NULL, E_WARNING, "must be greater than or equal to 0");
1436+
if (UNEXPECTED(EG(exception))) {
1437+
RETURN_THROWS();
1438+
}
14411439
}
1442-
#else
1443-
t.tv_sec = seconds;
1444-
1445-
if (argc == 3) {
1446-
t.tv_usec = microseconds % 1000000;
1447-
t.tv_sec += microseconds / 1000000;
1448-
} else {
1449-
t.tv_usec = 0;
1440+
if (microseconds < 0 || microseconds >= 1000000) {
1441+
php_error_docref(NULL, E_WARNING, "must be between 0 and 999999");
1442+
if (UNEXPECTED(EG(exception))) {
1443+
RETURN_THROWS();
1444+
}
1445+
if (microseconds >= 1000000) {
1446+
seconds += microseconds / 1000000;
1447+
microseconds %= 1000000;
1448+
}
14501449
}
1451-
#endif
1450+
1451+
t.tv_sec = (time_t) seconds;
1452+
t.tv_usec = (suseconds_t) microseconds;
14521453

14531454
if (PHP_STREAM_OPTION_RETURN_OK == php_stream_set_option(stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &t)) {
14541455
RETURN_TRUE;

0 commit comments

Comments
 (0)