php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71507 Overflow in php_tvtoto
Submitted: 2016-02-03 11:58 UTC Modified: 2016-10-17 16:36 UTC
From: martijn at hexon dot cx Assigned:
Status: Open Package: Network related
PHP Version: 5.6.17 OS:
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: martijn at hexon dot cx
New email:
PHP Version: OS:

 

 [2016-02-03 11:58 UTC] martijn at hexon dot cx
Description:
------------
php_tvtoto() in main/php_network.h converts a struct timeval to a timeout in seconds.

In some cases php_tvtoto() is called with a large value for tv_sec, causing the resulting integer to overflow.

For example with mysqlnd, where the default value for mysqlnd.net_read_timeout is 31536000 (one year, in seconds)

poll([{fd=13, events=POLLIN|POLLERR|POLLHUP}], 1, 1471228928) = 1 ([{fd=13, revents=POLLIN}])

#0  0x00007f47000bbe88 in poll () from /lib64/libc.so.6
#1  0x0000000000801399 in php_pollfd_for (stream=<value optimized out>, buf=<value optimized out>, count=<value optimized out>) at /usr/src/php-5.6.17/main/php_network.h:165
#2  php_sockop_write (stream=<value optimized out>, buf=<value optimized out>, count=<value optimized out>) at /usr/src/php-5.6.17/main/streams/xp_socket.c:82
#3  0x000000000047fee0 in php_openssl_sockop_io (read=0, stream=<value optimized out>, buf=<value optimized out>, count=18446744073709551615) at /usr/src/php-5.6.17/ext/openssl/xp_ssl.c:1971
#4  0x00000000007f4457 in _php_stream_write_buffer (stream=0xeadb090, buf=0x148d0780 "e-querylarge-querylarge-querylarge-querylarge-"..., count=25467)
    at /usr/src/php-5.6.17/main/streams/streams.c:1133
#5  0x00000000007c9eec in php_mysqlnd_net_send_ex_pub (net=0x105bb7e0, buffer=0x148cb2a8 "O\270", count=<value optimized out>, conn_stats=<value optimized out>, error_info=<value optimized out>) at /usr/src/php-5.6.17/ext/mysqlnd/mysqlnd_net.c:447
...

31536000 * 1000 mod 2^32 = 1471228928

So poll times out after ~17 days instead of 365 days.

Test script:
---------------
test.php:
<?php
  $db = new mysqli(...);

  // Prepare large query to fill the output buffer causing mysqlnd
  // to call php_pollfd_for()
  $largeSQL = 'SELECT "'. str_repeat('large-query', 1000000) .'"';
  $db->query($largeSQL);
?>

strace test.php

Expected result:
----------------
poll([{fd=4, events=POLLOUT}], 1, 4294967296) = 1 ([{fd=4, revents=POLLOUT}])

(or maybe a timeout of -1 is better)

Actual result:
--------------
poll([{fd=4, events=POLLOUT}], 1, 1471228928) = 1 ([{fd=4, revents=POLLOUT}])


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-07-02 14:43 UTC] cmb@php.net
Presuming that int is at least 32bit on all supported platforms,
this issue appears to be academic, as timeouts up to 596 hours
(i.e. more than 24 days) would be supported.

Shouldn't we just adjust mysqlnd.net_read_timeout to default to a
smaller value? 1 day appears to be more than sufficient.
 [2016-10-17 16:36 UTC] andrey@php.net
This got fixed in mysqlnd, as of today, and the timeour is now just 24 hours == no overflow.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Nov 22 17:01:31 2024 UTC