@@ -99,7 +99,6 @@ PHP_FUNCTION(stream_socket_client)
9999 zval * zerrno = NULL , * zerrstr = NULL , * zcontext = NULL ;
100100 double timeout ;
101101 bool timeout_is_null = 1 ;
102- php_timeout_ull conv ;
103102 struct timeval tv ;
104103 char * hashkey = NULL ;
105104 php_stream * stream = NULL ;
@@ -122,33 +121,38 @@ PHP_FUNCTION(stream_socket_client)
122121
123122 if (timeout_is_null ) {
124123 timeout = (double )FG (default_socket_timeout );
125- } else if (!zend_finite (timeout )) {
124+ } else if (!zend_finite (timeout ) || zend_isnan ( timeout ) ) {
126125 zend_argument_value_error (4 , "must be a finite value" );
127126 RETURN_THROWS ();
128127 }
129128
130129 context = php_stream_context_from_zval (zcontext , flags & PHP_FILE_NO_DEFAULT_CONTEXT );
131130
132- if (flags & PHP_STREAM_CLIENT_PERSISTENT ) {
133- spprintf (& hashkey , 0 , "stream_socket_client__%s" , ZSTR_VAL (host ));
134- }
135-
136131 /* prepare the timeout value for use */
137132 struct timeval * tv_pointer ;
138- if (timeout < 0.0 || timeout >= (double ) PHP_TIMEOUT_ULL_MAX / 1000000.0 ) {
133+ if (timeout < 0.0 ) {
134+ php_error_docref (NULL , E_WARNING , "timeout must greater than or equal to 0" );
135+ if (UNEXPECTED (EG (exception ))) {
136+ RETURN_THROWS ();
137+ }
139138 tv_pointer = NULL ;
140139 } 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
140+ double microseconds_f = 0 ;
141+ double seconds = 0 ;
142+
143+ seconds = modf (timeout , & microseconds_f );
144+ microseconds_f *= 1000000.0 ;
145+ long microseconds = lround (microseconds_f );
146+
147+ tv .tv_sec = (time_t ) seconds ;
148+ tv .tv_usec = microseconds ;
149149 tv_pointer = & tv ;
150150 }
151151
152+ if (flags & PHP_STREAM_CLIENT_PERSISTENT ) {
153+ spprintf (& hashkey , 0 , "stream_socket_client__%s" , ZSTR_VAL (host ));
154+ }
155+
152156 if (zerrno ) {
153157 ZEND_TRY_ASSIGN_REF_LONG (zerrno , 0 );
154158 }
@@ -262,7 +266,6 @@ PHP_FUNCTION(stream_socket_accept)
262266 bool timeout_is_null = 1 ;
263267 zval * zpeername = NULL ;
264268 zend_string * peername = NULL ;
265- php_timeout_ull conv ;
266269 struct timeval tv ;
267270 php_stream * stream = NULL , * clistream = NULL ;
268271 zval * zstream ;
@@ -286,17 +289,22 @@ PHP_FUNCTION(stream_socket_accept)
286289
287290 /* prepare the timeout value for use */
288291 struct timeval * tv_pointer ;
289- if (timeout < 0.0 || timeout >= (double ) PHP_TIMEOUT_ULL_MAX / 1000000.0 ) {
292+ if (timeout < 0.0 ) {
293+ php_error_docref (NULL , E_WARNING , "timeout must greater than or equal to 0" );
294+ if (UNEXPECTED (EG (exception ))) {
295+ RETURN_THROWS ();
296+ }
290297 tv_pointer = NULL ;
291298 } 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
299+ double microseconds_f = 0 ;
300+ double seconds = 0 ;
301+
302+ seconds = modf (timeout , & microseconds_f );
303+ microseconds_f *= 1000000.0 ;
304+ long microseconds = lround (microseconds_f );
305+
306+ tv .tv_sec = (time_t ) seconds ;
307+ tv .tv_usec = microseconds ;
300308 tv_pointer = & tv ;
301309 }
302310
@@ -830,11 +838,16 @@ PHP_FUNCTION(stream_select)
830838 } else if (usec < 0 ) {
831839 zend_argument_value_error (5 , "must be greater than or equal to 0" );
832840 RETURN_THROWS ();
841+ } else if (usec >= 1000000 ) {
842+ php_error_docref (NULL , E_WARNING , "must be less than 1000000" );
843+ if (UNEXPECTED (EG (exception ))) {
844+ RETURN_THROWS ();
845+ }
833846 }
834847
835848 /* 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 );
849+ tv .tv_sec = (time_t )(sec + (usec / 1000000 ));
850+ tv .tv_usec = (suseconds_t )(usec % 1000000 );
838851 tv_p = & tv ;
839852 }
840853
@@ -1419,7 +1432,6 @@ PHP_FUNCTION(stream_set_timeout)
14191432 zend_long seconds , microseconds = 0 ;
14201433 struct timeval t ;
14211434 php_stream * stream ;
1422- int argc = ZEND_NUM_ARGS ();
14231435
14241436 ZEND_PARSE_PARAMETERS_START (2 , 3 )
14251437 Z_PARAM_RESOURCE (socket )
@@ -1430,25 +1442,25 @@ PHP_FUNCTION(stream_set_timeout)
14301442
14311443 php_stream_from_zval (stream , socket );
14321444
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 ;
1445+ if (seconds < 0 ) {
1446+ php_error_docref (NULL , E_WARNING , "must be greater than or equal to 0" );
1447+ if (UNEXPECTED (EG (exception ))) {
1448+ RETURN_THROWS ();
1449+ }
14411450 }
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 ;
1451+ if (microseconds < 0 || microseconds >= 1000000 ) {
1452+ php_error_docref (NULL , E_WARNING , "must be between 0 and 999999" );
1453+ if (UNEXPECTED (EG (exception ))) {
1454+ RETURN_THROWS ();
1455+ }
1456+ if (microseconds >= 1000000 ) {
1457+ seconds += microseconds / 1000000 ;
1458+ microseconds %= 1000000 ;
1459+ }
14501460 }
1451- #endif
1461+
1462+ t .tv_sec = (time_t ) seconds ;
1463+ t .tv_usec = (suseconds_t ) microseconds ;
14521464
14531465 if (PHP_STREAM_OPTION_RETURN_OK == php_stream_set_option (stream , PHP_STREAM_OPTION_READ_TIMEOUT , 0 , & t )) {
14541466 RETURN_TRUE ;
0 commit comments