Skip to content

Commit 5989953

Browse files
committed
Merge branch 'PHP-8.2'
* PHP-8.2: Fix pre-PHP 8.2 compatibility for php_mt_rand_range() with MT_RAND_PHP (php#9839)
2 parents 7532728 + 7f0b228 commit 5989953

File tree

4 files changed

+64
-19
lines changed

4 files changed

+64
-19
lines changed

ext/random/engine_mt19937.c

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -162,23 +162,7 @@ static uint64_t generate(php_random_status *status)
162162

163163
static zend_long range(php_random_status *status, zend_long min, zend_long max)
164164
{
165-
php_random_status_state_mt19937 *s = status->state;
166-
167-
if (s->mode == MT_RAND_MT19937) {
168-
return php_random_range(&php_random_algo_mt19937, status, min, max);
169-
}
170-
171-
/* Legacy mode deliberately not inside php_mt_rand_range()
172-
* to prevent other functions being affected */
173-
174-
uint64_t r = php_random_algo_mt19937.generate(status) >> 1;
175-
176-
/* This is an inlined version of the RAND_RANGE_BADSCALING macro that does not invoke UB when encountering
177-
* (max - min) > ZEND_LONG_MAX.
178-
*/
179-
zend_ulong offset = (double) ( (double) max - min + 1.0) * (r / (PHP_MT_RAND_MAX + 1.0));
180-
181-
return (zend_long) (offset + min);
165+
return php_random_range(&php_random_algo_mt19937, status, min, max);
182166
}
183167

184168
static bool serialize(php_random_status *status, HashTable *data)

ext/random/random.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,21 @@ PHPAPI zend_long php_mt_rand_range(zend_long min, zend_long max)
447447
* rand() allows min > max, mt_rand does not */
448448
PHPAPI zend_long php_mt_rand_common(zend_long min, zend_long max)
449449
{
450-
return php_mt_rand_range(min, max);
450+
php_random_status *status = php_random_default_status();
451+
php_random_status_state_mt19937 *s = status->state;
452+
453+
if (s->mode == MT_RAND_MT19937) {
454+
return php_mt_rand_range(min, max);
455+
}
456+
457+
uint64_t r = php_random_algo_mt19937.generate(php_random_default_status()) >> 1;
458+
459+
/* This is an inlined version of the RAND_RANGE_BADSCALING macro that does not invoke UB when encountering
460+
* (max - min) > ZEND_LONG_MAX.
461+
*/
462+
zend_ulong offset = (double) ( (double) max - min + 1.0) * (r / (PHP_MT_RAND_MAX + 1.0));
463+
464+
return (zend_long) (offset + min);
451465
}
452466
/* }}} */
453467

ext/random/randomizer.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,22 @@ PHP_METHOD(Random_Randomizer, getInt)
126126
RETURN_THROWS();
127127
}
128128

129-
result = randomizer->algo->range(randomizer->status, min, max);
129+
if (UNEXPECTED(
130+
randomizer->algo->range == php_random_algo_mt19937.range
131+
&& ((php_random_status_state_mt19937 *) randomizer->status->state)->mode != MT_RAND_MT19937
132+
)) {
133+
uint64_t r = php_random_algo_mt19937.generate(randomizer->status) >> 1;
134+
135+
/* This is an inlined version of the RAND_RANGE_BADSCALING macro that does not invoke UB when encountering
136+
* (max - min) > ZEND_LONG_MAX.
137+
*/
138+
zend_ulong offset = (double) ( (double) max - min + 1.0) * (r / (PHP_MT_RAND_MAX + 1.0));
139+
140+
result = (zend_long) (offset + min);
141+
} else {
142+
result = randomizer->algo->range(randomizer->status, min, max);
143+
}
144+
130145
if (EG(exception)) {
131146
RETURN_THROWS();
132147
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
array_rand() is not affected by MT_RAND_PHP as with PHP < 8.2
3+
--FILE--
4+
<?php
5+
6+
$array = [
7+
'foo',
8+
'bar',
9+
'baz',
10+
];
11+
12+
mt_srand(1, MT_RAND_PHP);
13+
function custom_array_rand() {
14+
global $array;
15+
$key = array_rand($array);
16+
var_dump('found key ' . $key);
17+
return $array[$key];
18+
}
19+
20+
var_dump(
21+
custom_array_rand(),
22+
custom_array_rand(),
23+
custom_array_rand(),
24+
);
25+
?>
26+
--EXPECTF--
27+
string(11) "found key 0"
28+
string(11) "found key 1"
29+
string(11) "found key 0"
30+
string(3) "foo"
31+
string(3) "bar"
32+
string(3) "foo"

0 commit comments

Comments
 (0)