Skip to content

Fix GH-16809: fopen HTTP wrapper timeout stream context option overflow. #16810

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

devnexen
Copy link
Member

No description provided.

@devnexen devnexen linked an issue Nov 15, 2024 that may be closed by this pull request
@devnexen devnexen marked this pull request as ready for review November 15, 2024 07:59
@devnexen devnexen requested a review from bukka as a code owner November 15, 2024 07:59
@devnexen devnexen requested a review from cmb69 November 30, 2024 20:41
Copy link
Member

@cmb69 cmb69 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

zend_string_release(transport_string);
php_url_free(resource);
return NULL;
}
#ifndef PHP_WIN32
timeout.tv_sec = (time_t) d;
timeout.tv_usec = (size_t) ((d - timeout.tv_sec) * 1000000);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The size_t cast looks wrong. timeout.tv_usec is an suseconds_t which is according to POSIX:

The type suseconds_t shall be a signed integer type capable of storing values at least in the range [-1, 1000000].

Probably okay to leave this for stable branches, but I suggest to change to (suseconds_t) in master.

The (long) casts on Windows are, unfortunately, correct. From WinSock2.h:

struct timeval {
        long    tv_sec;         /* seconds */
        long    tv_usec;        /* and microseconds */
};

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I would definitively keep this existing code untouched in stable branch.

@@ -203,6 +203,13 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,

if (context && (tmpzval = php_stream_context_get_option(context, wrapper->wops->label, "timeout")) != NULL) {
double d = zval_get_double(tmpzval);

if (d > (double) PHP_TIMEOUT_ULL_MAX / 1000000.0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using PHP_TIMEOUT_ULL_MAX here (and maybe elsewhere) is presumptious. While that is likely good for POSIX platforms ("time_t shall be an integer type with a width (see <stdint.h> ) of at least 64 bits") (albeit not perfect since time_t could be signed), it's completely borked for Windows where long is uint32_t for x64 and x86. So for Windows, that needs to be:

if (d > (double) LONG_MAX / 1000000.0) {

For stable branches, maybe define a const variable conditionally (#ifndef PHP_WIN32), and use that for the check.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's completely borked for Windows where long is uint32_t for x64 and x86

Oh.

Copy link
Member

@bukka bukka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@devnexen devnexen closed this in 301b8e2 Dec 8, 2024
cmb69 added a commit to cmb69/php-src that referenced this pull request Feb 6, 2025
The fix for phpGH-16809[1] used a way too small timeout maximum on
Windows.  We correct this.

However, later on the timeout is applied to the current timestamp, so
we would need to take that into account, but due to the elapsed time
between the check and the actual network request, this could not be
precise, and the resulting error message would be confusing, since
after the developer would adjust the timeout to the reported maximum,
the check would fail again, now reporting a lower maximum timeout.

Thus we silently cap the value in `php_network_set_limit_time()` to
avoid undefined behavior, and are not picky about the usec value (we
just assume a second more), since there is a bigger issue, namely that
we hit the Y2038 problem on Windows.

[1] <php#16810>
charmitro pushed a commit to wasix-org/php that referenced this pull request Mar 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

UBSan alert at ext/standard/http_fopen_wrapper.c:236
3 participants