diff --git a/ext/random/gammasection.c b/ext/random/gammasection.c index fb0c2cd3bf94d..aa4531fba22f7 100644 --- a/ext/random/gammasection.c +++ b/ext/random/gammasection.c @@ -66,6 +66,11 @@ PHPAPI double php_random_gammasection_closed_open(const php_random_algo *algo, p { double g = gamma_max(min, max); uint64_t hi = ceilint(min, max, g); + + if (UNEXPECTED(max <= min || hi < 1)) { + return NAN; + } + uint64_t k = 1 + php_random_range64(algo, status, hi - 1); /* [1, hi] */ if (fabs(min) <= fabs(max)) { @@ -79,6 +84,11 @@ PHPAPI double php_random_gammasection_closed_closed(const php_random_algo *algo, { double g = gamma_max(min, max); uint64_t hi = ceilint(min, max, g); + + if (UNEXPECTED(max < min)) { + return NAN; + } + uint64_t k = php_random_range64(algo, status, hi); /* [0, hi] */ if (fabs(min) <= fabs(max)) { @@ -92,6 +102,11 @@ PHPAPI double php_random_gammasection_open_closed(const php_random_algo *algo, p { double g = gamma_max(min, max); uint64_t hi = ceilint(min, max, g); + + if (UNEXPECTED(max <= min || hi < 1)) { + return NAN; + } + uint64_t k = php_random_range64(algo, status, hi - 1); /* [0, hi - 1] */ if (fabs(min) <= fabs(max)) { @@ -105,6 +120,11 @@ PHPAPI double php_random_gammasection_open_open(const php_random_algo *algo, php { double g = gamma_max(min, max); uint64_t hi = ceilint(min, max, g); + + if (UNEXPECTED(max <= min || hi < 2)) { + return NAN; + } + uint64_t k = 1 + php_random_range64(algo, status, hi - 2); /* [1, hi - 1] */ if (fabs(min) <= fabs(max)) { diff --git a/ext/random/randomizer.c b/ext/random/randomizer.c index 0a801e35c74c6..75e88c8b01012 100644 --- a/ext/random/randomizer.c +++ b/ext/random/randomizer.c @@ -190,7 +190,14 @@ PHP_METHOD(Random_Randomizer, getFloat) RETURN_THROWS(); } - RETURN_DOUBLE(php_random_gammasection_open_open(randomizer->algo, randomizer->status, min, max)); + RETVAL_DOUBLE(php_random_gammasection_open_open(randomizer->algo, randomizer->status, min, max)); + + if (UNEXPECTED(isnan(Z_DVAL_P(return_value)))) { + zend_value_error("The given interval is empty, there are no floats between argument #1 ($min) and argument #2 ($max)."); + RETURN_THROWS(); + } + + return; default: ZEND_UNREACHABLE(); } diff --git a/ext/random/tests/03_randomizer/methods/getFloat_error.phpt b/ext/random/tests/03_randomizer/methods/getFloat_error.phpt index 1e200f2507a69..286435e1752fb 100644 --- a/ext/random/tests/03_randomizer/methods/getFloat_error.phpt +++ b/ext/random/tests/03_randomizer/methods/getFloat_error.phpt @@ -73,10 +73,17 @@ foreach ([ } catch (ValueError $e) { echo $e->getMessage(), PHP_EOL; } + + try { + // There is no float between the two parameters, thus making the OpenOpen interval empty. + var_dump(randomizer()->getFloat(1.0, 1 + PHP_FLOAT_EPSILON, $boundary)); + } catch (ValueError $e) { + echo $e->getMessage(), PHP_EOL; + } } ?> ---EXPECT-- +--EXPECTF-- ClosedClosed Random\Randomizer::getFloat(): Argument #1 ($min) must be finite Random\Randomizer::getFloat(): Argument #1 ($min) must be finite @@ -87,6 +94,7 @@ Random\Randomizer::getFloat(): Argument #2 ($max) must be finite Random\Randomizer::getFloat(): Argument #2 ($max) must be greater than or equal to argument #1 ($min) float(0) float(1.0E+17) +float(%f) ClosedOpen Random\Randomizer::getFloat(): Argument #1 ($min) must be finite Random\Randomizer::getFloat(): Argument #1 ($min) must be finite @@ -97,6 +105,7 @@ Random\Randomizer::getFloat(): Argument #2 ($max) must be finite Random\Randomizer::getFloat(): Argument #2 ($max) must be greater than argument #1 ($min) Random\Randomizer::getFloat(): Argument #2 ($max) must be greater than argument #1 ($min) Random\Randomizer::getFloat(): Argument #2 ($max) must be greater than argument #1 ($min) +float(1) OpenClosed Random\Randomizer::getFloat(): Argument #1 ($min) must be finite Random\Randomizer::getFloat(): Argument #1 ($min) must be finite @@ -107,6 +116,7 @@ Random\Randomizer::getFloat(): Argument #2 ($max) must be finite Random\Randomizer::getFloat(): Argument #2 ($max) must be greater than argument #1 ($min) Random\Randomizer::getFloat(): Argument #2 ($max) must be greater than argument #1 ($min) Random\Randomizer::getFloat(): Argument #2 ($max) must be greater than argument #1 ($min) +float(1.0000000000000002) OpenOpen Random\Randomizer::getFloat(): Argument #1 ($min) must be finite Random\Randomizer::getFloat(): Argument #1 ($min) must be finite @@ -117,3 +127,4 @@ Random\Randomizer::getFloat(): Argument #2 ($max) must be finite Random\Randomizer::getFloat(): Argument #2 ($max) must be greater than argument #1 ($min) Random\Randomizer::getFloat(): Argument #2 ($max) must be greater than argument #1 ($min) Random\Randomizer::getFloat(): Argument #2 ($max) must be greater than argument #1 ($min) +The given interval is empty, there are no floats between argument #1 ($min) and argument #2 ($max).