-
Notifications
You must be signed in to change notification settings - Fork 7.8k
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
ext/sockets: further timeout handling changes. #17210
ext/sockets: further timeout handling changes. #17210
Conversation
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.
Thank you!
ext/sockets/sockets.c
Outdated
#ifndef PHP_WIN32 | ||
tv.tv_sec = timeout.tv_sec; | ||
tv.tv_usec = timeout.tv_usec; | ||
#else | ||
tv.tv_sec = timeout ? (long)(timeout / 1000) : 0; | ||
tv.tv_usec = timeout ? (long)((timeout * 1000) % 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 looks not quite correct. If we get a large timeout (DWORD can be up to 2^32) and multiply by 1000, we can overflow (since unsigned no UB, but still not desireable, I think). Is there a reason not to do:
tv.tv_usec = timeout ? (long)((timeout * 1000) % 1000000) : 0; | |
tv.tv_usec = timeout ? (long)((timeout % 1000) * 1000) : 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.
I did not change the windows part as I can't test (I should set up a php build in my windows laptop :)) but I ll have a look at your suggestion later.
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 didn't test either; and no need for Windows for this one. :)
#include <stdio.h>
#include <limits.h>
int main()
{
unsigned int timeout = UINT_MAX;
printf("%u\n", timeout);
printf("%d\n", (long)((timeout * 1000) % 1000000));
printf("%d\n", (long)((timeout % 1000) * 1000));
return 0;
}
outputs:
4294967295
966296
295000
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.
fair fair, you got a point :)
|
||
timeout = valsec * 1000; | ||
|
||
if (valusec < 0 || timeout > ULONG_MAX - (valusec / 1000)) { |
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.
It seems to me that ULONG_MAX - (valusec / 1000)
can yield a negative result, in which case we would throw. If we're fine with this (I think we are), the code is good as is.
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.
Maybe add a comment that valuesec / 1000 > ULONG_MAX
is indeed considered a programmer error (i.e. throwing is deliberate here). Note that this code is only for Windows, where ULONG_MAX
is 2^32, but ZEND_LONG_MAX
is 2^63 for 64bit architectures.
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.
Looks good to me now.
|
||
timeout = valsec * 1000; | ||
|
||
if (valusec < 0 || timeout > ULONG_MAX - (valusec / 1000)) { |
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.
Maybe add a comment that valuesec / 1000 > ULONG_MAX
is indeed considered a programmer error (i.e. throwing is deliberate here). Note that this code is only for Windows, where ULONG_MAX
is 2^32, but ZEND_LONG_MAX
is 2^63 for 64bit architectures.
1a45f36
to
c0cf208
Compare
No description provided.