-
Notifications
You must be signed in to change notification settings - Fork 7.8k
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
Conversation
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. |
a72cfed
to
a0a97a7
Compare
ext/standard/fsock.c
Outdated
@@ -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) { |
There was a problem hiding this comment.
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
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(); | ||
} |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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.
ext/standard/fsock.c
Outdated
@@ -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)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a test
There was a problem hiding this comment.
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
On Mon, Jul 22, 2024, 3:30 AM Niels Dossche ***@***.***> wrote:
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
<#11183>
—
Reply to this email directly, view it on GitHub
<#14785 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACE6KGZMKWA6SLW2GBH6PLZNQK5LAVCNFSM6AAAAABKJMSN7SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENBRG43DKMJWGM>
.
You are receiving this because you are subscribed to this thread.
if I am not mistaken, php does not support 32bit on windows anymore. 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: ***@***.***>
… |
I can see downloads for 32-bit x86 Windows builds on https://windows.php.net/download/, so it's still supported.
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 |
ext/standard/fsock.c
Outdated
efree(hashkey); | ||
} | ||
|
||
zend_argument_value_error(6, "must be between -1 and " ZEND_ULONG_FMT, (PHP_TIMEOUT_ULL_MAX / 1000000.0)); |
There was a problem hiding this comment.
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:
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)); |
There was a problem hiding this comment.
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.
On Tue, Jul 23, 2024, 1:07 AM Niels Dossche ***@***.***> wrote:
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
right, however we did ensure that int64_t (and other c99 types) are always
available, in all platform. It is defined in the CS, if that helps (
https://github.com/php/php-src/blob/b537f013537da981804282d1fe50f96a0cc325ee/CODING_STANDARDS.md?plain=1#L14
).
I checked the define and co, we still have too many places in standard code
relying on custom checks and define :-/.
cmb or Weltling know better and may provide more updated insights about
this.
I am also surprised we still provide 32bits build given the limitation, and
more importantly not being supported anymore by msft (windows releases,
32bit mode still works). But that's off topic :)
… —
Reply to this email directly, view it on GitHub
<#14785 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACE6KBTTIWZKJ7NDTQYDO3ZNVC7RAVCNFSM6AAAAABKJMSN7SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENBTGUZDQNBQGI>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
There was a problem hiding this 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.
I'm a bit concerned that some people may be passing PHP_INT_MAX to timeout without thinking though. |
No description provided.