mirror of
https://github.com/php/php-src.git
synced 2026-04-26 09:28:21 +02:00
Fix byte expansion in rand_rangeXX() (#9056)
* Fix shift in rand_range??() The last generated size is in bytes, whereas the shift is in bits. Multiple the generated size by 8 to correctly handle each byte once. * Correctly handle user engines returning less than 4 bytes in rand_rangeXX() We need to loop until we accumulate sufficient bytes, instead of just checking once. The version in the rejection loop was already correct. * Clean up some repetition in rand_rangeXX()
This commit is contained in:
+20
-32
@@ -88,19 +88,16 @@ static inline uint32_t rand_range32(const php_random_algo *algo, php_random_stat
|
||||
size_t total_size = 0;
|
||||
uint32_t count = 0;
|
||||
|
||||
result = algo->generate(status);
|
||||
total_size = status->last_generated_size;
|
||||
if (status->last_unsafe) {
|
||||
return 0;
|
||||
}
|
||||
if (total_size < sizeof(uint32_t)) {
|
||||
result = 0;
|
||||
total_size = 0;
|
||||
do {
|
||||
r = algo->generate(status);
|
||||
result = (result << status->last_generated_size) | r;
|
||||
result = (result << (8 * status->last_generated_size)) | r;
|
||||
total_size += status->last_generated_size;
|
||||
if (status->last_unsafe) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} while (total_size < sizeof(uint32_t));
|
||||
|
||||
/* Special case where no modulus is required */
|
||||
if (UNEXPECTED(umax == UINT32_MAX)) {
|
||||
@@ -126,19 +123,16 @@ static inline uint32_t rand_range32(const php_random_algo *algo, php_random_stat
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = algo->generate(status);
|
||||
total_size = status->last_generated_size;
|
||||
if (status->last_unsafe) {
|
||||
return 0;
|
||||
}
|
||||
while (total_size < sizeof(uint32_t)) {
|
||||
result = 0;
|
||||
total_size = 0;
|
||||
do {
|
||||
r = algo->generate(status);
|
||||
result = (result << status->last_generated_size) | r;
|
||||
result = (result << (8 * status->last_generated_size)) | r;
|
||||
total_size += status->last_generated_size;
|
||||
if (status->last_unsafe) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} while (total_size < sizeof(uint32_t));
|
||||
}
|
||||
|
||||
return result % umax;
|
||||
@@ -150,19 +144,16 @@ static inline uint64_t rand_range64(const php_random_algo *algo, php_random_stat
|
||||
size_t total_size = 0;
|
||||
uint32_t count = 0;
|
||||
|
||||
result = algo->generate(status);
|
||||
total_size = status->last_generated_size;
|
||||
if (status->last_unsafe) {
|
||||
return 0;
|
||||
}
|
||||
if (total_size < sizeof(uint64_t)) {
|
||||
result = 0;
|
||||
total_size = 0;
|
||||
do {
|
||||
r = algo->generate(status);
|
||||
result = (result << status->last_generated_size) | r;
|
||||
result = (result << (8 * status->last_generated_size)) | r;
|
||||
total_size += status->last_generated_size;
|
||||
if (status->last_unsafe) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} while (total_size < sizeof(uint64_t));
|
||||
|
||||
/* Special case where no modulus is required */
|
||||
if (UNEXPECTED(umax == UINT64_MAX)) {
|
||||
@@ -188,19 +179,16 @@ static inline uint64_t rand_range64(const php_random_algo *algo, php_random_stat
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = algo->generate(status);
|
||||
total_size = status->last_generated_size;
|
||||
if (status->last_unsafe) {
|
||||
return 0;
|
||||
}
|
||||
while (total_size < sizeof(uint64_t)) {
|
||||
result = 0;
|
||||
total_size = 0;
|
||||
do {
|
||||
r = algo->generate(status);
|
||||
result = (result << status->last_generated_size) | r;
|
||||
result = (result << (8 * status->last_generated_size)) | r;
|
||||
total_size += status->last_generated_size;
|
||||
if (status->last_unsafe) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} while (total_size < sizeof(uint64_t));
|
||||
}
|
||||
|
||||
return result % umax;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
Random: Randomizer: User Engine results are correctly expanded for getInt()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$randomizer = new \Random\Randomizer (
|
||||
new class () implements \Random\Engine
|
||||
{
|
||||
public function generate(): string
|
||||
{
|
||||
return "\x01";
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
var_dump(bin2hex(pack('V', $randomizer->getInt(0, 0xFFFFFF))));
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(8) "01010100"
|
||||
Reference in New Issue
Block a user