Opened 5 weeks ago
Last modified 4 weeks ago
#63099 new defect (bug)
wp_rand() function returns only 0 or 1 when called without parameters on 32-bit PHP systems
Reported by: |
|
Owned by: | |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | normal | Version: | 6.7.2 |
Component: | General | Keywords: | has-patch |
Focuses: | Cc: |
Description
I've identified a bug in WordPress's wp_rand() function that causes it to return only the values 0 or 1 when called without parameters on 32-bit PHP systems.
Environment Information:
- PHP Version: 7.4.33
- PHP Int Max: 2147483647 (32-bit system)
- PHP Int Size: 4
- OS: Linux (64-bit)
- Server Software: Apache
- WordPress Version: 6.7.2
- Random Int Available: Yes
- OpenSSL Available: Yes
Issue Description:
When calling wp_rand() without parameters on a 32-bit PHP system, it consistently returns only the values 0 or 1, rather than generating random numbers across the expected range. This occurs due to an integer overflow issue.
Debug Results:
Array ( [start] => Array ( [min] => [max] => [rnd_value_length] => 0 [rnd_value] => ... ) [max_random_number] => 4294967295 [php_int_max] => 2147483647 [after_cast] => Array ( [min] => 0 [max] => -1 [max === max_random_number] => false ) [use_random_int_functionality] => true [random_int_try] => Array ( [_min] => -1 [_max] => 0 ) [random_int_result] => -1 [return_path] => random_int success [final_result] => 1 )
Root Cause Analysis:
- On 32-bit PHP systems (PHP_INT_MAX = 2147483647), the function sets $max_random_number to 4294967295 (unsigned 32-bit int max value)
- When this value is cast to an integer in 32-bit PHP, it overflows and becomes -1
- The function then calls random_int(-1, 0) which returns either -1 or 0
- Finally, the absint() function converts -1 to 1, resulting in only 0 or 1 being returned
Steps to Reproduce:
- Run WordPress on a 32-bit PHP system
- Call wp_rand() without parameters multiple times
- Observe that only 0 or 1 is returned
Expected Behavior:
The function should return random numbers across the full range (0 to getrandmax() or similar) when called without parameters, just like PHP's native rand() function.
Additional Tests:
- PHP's native rand() and mt_rand() functions work correctly on the same system
- When wp_rand() is called with specific parameters (e.g., wp_rand(10, 100)), it behaves correctly
This appears to be a bug in how the function handles 32-bit PHP systems when called without parameters.
Change History (4)
This ticket was mentioned in PR #8507 on WordPress/wordpress-develop by @debarghyabanerjee.
5 weeks ago
#2
- Keywords has-patch added
Trac Ticket: Core-63099
## Problem
On 32-bit PHP systems, the wp_rand() function would incorrectly return only 0 or 1 when called without parameters due to an integer overflow. This occurred because the function sets $max_random_number to 4294967295, which overflows to -1 on 32-bit systems, leading to invalid arguments being passed to random_int().
## Solution
- Modified the calculation of $max_random_number to dynamically use PHP_INT_MAX for 32-bit systems (PHP_INT_SIZE === 4).
- For 64-bit systems, the previous behavior with 4294967295 remains unchanged.
#3
follow-up:
↓ 4
@
4 weeks ago
@kalonya What exactly is your server configuration please? In the ticket description you state that the OS is Linux (64-bit)
. Are you running a 32 bit version of PHP and OpenSSL on a 64 bit OS?
#4
in reply to:
↑ 3
@
4 weeks ago
Replying to johnbillion:
@kalonya What exactly is your server configuration please? In the ticket description you state that the OS is
Linux (64-bit)
. Are you running a 32 bit version of PHP and OpenSSL on a 64 bit OS?
Not me, but three of our clients. They use a 32-bit version of PHP on a 64-bit OS. It doesn't happen on all 32-bit PHPs. Some implementations handle this problem by clamping 4294967295 to 2147483647, and some others just overflow and return -1. Unfortunately, I don't have access to their web server.
Maybe we should set the $max_random_number like this?
The code tries to cast a (float) number to (int), which causes an overflow in a 32-bit system.