-
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
More ext-random integer overflow #9190
Comments
Curious why it didn't pop up earlier, the "offending" |
Probably the same problem: #9191 |
Because |
Standalone reproducer script: #include<stdint.h>
#include<stdio.h>
typedef int64_t zend_long;
typedef uint64_t zend_ulong;
# define PHP_MT_RAND_MAX ((zend_long) (0x7FFFFFFF))
# define RAND_RANGE_BADSCALING(__n, __min, __max, __tmax) \
(__n) = (__min) + (zend_long) ((double) ( (double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))
zend_ulong bad_scaling(zend_ulong __n, zend_long __min, zend_long __max, zend_long __tmax)
{
return (__min)
+
(zend_long) (
(double) (
(double) (__max)
-
(__min)
+
1.0
)
*
(
(__n)
/
(
(__tmax)
+
1.0
)
)
);
}
int
main(void)
{
zend_long min, max;
zend_ulong r;
min = INT64_MIN;
max = INT64_MAX;
r = PHP_MT_RAND_MAX - 1;
// RAND_RANGE_BADSCALING(r, min, max, PHP_MT_RAND_MAX);
r = bad_scaling(r, min, max, PHP_MT_RAND_MAX);
printf("%ld\n", (zend_long) r);
} results in:
|
RAND_RANGE_BADSCALING() invokes undefined behavior when (max - min) > ZEND_LONG_MAX, because the intermediate `double` might not fit into `zend_long`. Fix this by inlining a fixed version of the macro into Mt19937's range() function. Fixing the macro itself cannot be done in the general case, because the types of the inputs are not known. Instead of replacing one possibly broken version with another possibly broken version, the macro is simply left as is and should be removed in a future version. The fix itself is simple: Instead of storing the "offset" in a `zend_long`, we use a `zend_ulong` which is capable of storing the resulting double by construction. With this fix the implementation of this broken scaling is effectively identical to the implementation of php_random_range from a data type perspective, making it easy to verify the correctness. It was further empirically verified that the broken macro and the fix return the same results for all possible values of `r` for several distinct pairs of (min, max). Fixes phpGH-9190 Fixes phpGH-9191
Okay, this scaling function is absolutely horrible and we really shouldn't have added the support for That said: There's a fix in #9197. |
RAND_RANGE_BADSCALING() invokes undefined behavior when (max - min) > ZEND_LONG_MAX, because the intermediate `double` might not fit into `zend_long`. Fix this by inlining a fixed version of the macro into Mt19937's range() function. Fixing the macro itself cannot be done in the general case, because the types of the inputs are not known. Instead of replacing one possibly broken version with another possibly broken version, the macro is simply left as is and should be removed in a future version. The fix itself is simple: Instead of storing the "offset" in a `zend_long`, we use a `zend_ulong` which is capable of storing the resulting double by construction. With this fix the implementation of this broken scaling is effectively identical to the implementation of php_random_range from a data type perspective, making it easy to verify the correctness. It was further empirically verified that the broken macro and the fix return the same results for all possible values of `r` for several distinct pairs of (min, max). Fixes phpGH-9190 Fixes phpGH-9191
…9197) RAND_RANGE_BADSCALING() invokes undefined behavior when (max - min) > ZEND_LONG_MAX, because the intermediate `double` might not fit into `zend_long`. Fix this by inlining a fixed version of the macro into Mt19937's range() function. Fixing the macro itself cannot be done in the general case, because the types of the inputs are not known. Instead of replacing one possibly broken version with another possibly broken version, the macro is simply left as is and should be removed in a future version. The fix itself is simple: Instead of storing the "offset" in a `zend_long`, we use a `zend_ulong` which is capable of storing the resulting double by construction. With this fix the implementation of this broken scaling is effectively identical to the implementation of php_random_range from a data type perspective, making it easy to verify the correctness. It was further empirically verified that the broken macro and the fix return the same results for all possible values of `r` for several distinct pairs of (min, max). Fixes GH-9190 Fixes GH-9191
Thanks @TimWolla! |
Description
https://github.com/php/php-src/runs/7571517985?check_suite_focus=true
Note: This error occurred only in the tests with tracing JIT.
/cc @zeriyoshi
Thanks for taking a look!
PHP Version
master
Operating System
No response
The text was updated successfully, but these errors were encountered: