Skip to content

Fix GH-14780: p(f)sockopen overflow on timeout argument. #14785

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 1 commit into from

Conversation

devnexen
Copy link
Member

@devnexen devnexen commented Jul 3, 2024

No description provided.

@devnexen devnexen marked this pull request as ready for review July 3, 2024 17:50
@devnexen devnexen requested a review from bukka as a code owner July 3, 2024 17:50
@nielsdos
Copy link
Member

One tricky thing here is Windows: time_t is 32-bit on our x86 builds and 64-bit on x64 builds. But LONG_MAX is always the signed 32-bit limit even on Windows x64.
Also this whole issue is giving me a déjà vu, here's how I fixed it last year in another part of the codebase: #11183

@devnexen devnexen force-pushed the gh14780 branch 2 times, most recently from a72cfed to a0a97a7 Compare July 22, 2024 13:56
@@ -73,14 +73,27 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
}

/* prepare the timeout value for use */
if (timeout < 0.0 || timeout > (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.

This should still be the following to catch NAN and INF

Suggested change
if (timeout < 0.0 || timeout > (double) PHP_TIMEOUT_ULL_MAX / 1000000.0) {
if (!(timeout >= 0.0 && timeout <= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0)) {

Sorry for the confusion, this is in fact something I missed in my original patch. So I opened a PR to fix that: #15061

However, I'm not sure this is the best approach here after all.
My original patch didn't use a range check because some people use -1 to mean a practically infinite timeout, and I think we should keep that behaviour here as well. WDYT?

pfsockopen('udp://127.0.0.1', '63844', $code, $err, (PHP_INT_MIN/100000)-1);
} catch (\ValueError $e) {
echo $e->getMessage();
}
Copy link
Member

Choose a reason for hiding this comment

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

Please add a closing ?>

<?php
$code = null;
$err = null;
try {
Copy link
Member

Choose a reason for hiding this comment

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

Please also test NAN and INF.

@@ -73,14 +73,27 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
}

/* prepare the timeout value for use */
if (timeout != -1.0 && (timeout >= 0.0 || timeout <= (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.

Suggested change
if (timeout != -1.0 && (timeout >= 0.0 || timeout <= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0)) {
if (timeout != -1.0 && !(timeout >= 0.0 && timeout <= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0)) {

The error message also isn't technically correct anymore

Copy link
Member

Choose a reason for hiding this comment

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

Also, please check if -1 behaves correctly now.

Copy link
Member Author

Choose a reason for hiding this comment

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

I added a test

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, I missed that in the test file

@pierrejoye
Copy link
Contributor

pierrejoye commented Jul 22, 2024 via email

@nielsdos
Copy link
Member

if I am not mistaken, php does not support 32bit on windows anymore.

I can see downloads for 32-bit x86 Windows builds on https://windows.php.net/download/, so it's still supported.

Also we introduce c9x int declaration for portability purposes a while back. I am not sure why long max on windows (within php's build) remains 32bit :) Message ID: @.***>

LONG_MAX is in limits.h, not defined by PHP. See this msvc snippet that shows it's 32 bits on x64 msvc compiler: https://godbolt.org/z/bvjrdT8TM

efree(hashkey);
}

zend_argument_value_error(6, "must be between -1 and " ZEND_ULONG_FMT, (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.

This message still isn't technically right, this should be:

Suggested change
zend_argument_value_error(6, "must be between -1 and " ZEND_ULONG_FMT, (PHP_TIMEOUT_ULL_MAX / 1000000.0));
zend_argument_value_error(6, "must be -1 or between 0 and " ZEND_ULONG_FMT, (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.

In my patch I made finite but out-of-range values equal to an infinite timeout to preserve BC, whether we need that here I don't know. Part of me thinks your approach makes sense and part of me thinks we should be consistent.

@pierrejoye
Copy link
Contributor

pierrejoye commented Jul 22, 2024 via email

Copy link
Member

@nielsdos nielsdos left a comment

Choose a reason for hiding this comment

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

Technically this seems fine and fixes the UB, whether it's better to allow out of range values but treat them as infinite, I'm not sure. In any case this is an improvement as-is.

@nielsdos
Copy link
Member

I'm a bit concerned that some people may be passing PHP_INT_MAX to timeout without thinking though.

@devnexen devnexen closed this in ba909d7 Jul 22, 2024
devnexen added a commit to devnexen/php-src that referenced this pull request Jul 22, 2024
devnexen added a commit that referenced this pull request Jul 22, 2024
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.

3 participants