diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index fee800f7e02..1eddb342bcc 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1195,6 +1195,7 @@ PHP_FUNCTION(time_sleep_until) struct timespec php_req, php_rem; uint64_t current_ns, target_ns, diff_ns; const uint64_t ns_per_sec = 1000000000; + const double top_target_sec = (double)(UINT64_MAX / ns_per_sec); ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_DOUBLE(target_secs) @@ -1204,6 +1205,11 @@ PHP_FUNCTION(time_sleep_until) RETURN_FALSE; } + if (UNEXPECTED(!(target_secs >= 0 && target_secs <= top_target_sec))) { + zend_argument_value_error(1, "must be between 0 and %" PRIu64, (uint64_t)top_target_sec); + RETURN_THROWS(); + } + target_ns = (uint64_t) (target_secs * ns_per_sec); current_ns = ((uint64_t) tm.tv_sec) * ns_per_sec + ((uint64_t) tm.tv_usec) * 1000; if (target_ns < current_ns) { diff --git a/ext/standard/tests/misc/gh14774.phpt b/ext/standard/tests/misc/gh14774.phpt new file mode 100644 index 00000000000..1f9cd921e03 --- /dev/null +++ b/ext/standard/tests/misc/gh14774.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-14774 time_sleep_until overflow +--SKIPIF-- + +--FILE-- +getMessage() . PHP_EOL; + } +} +?> +--EXPECTF-- +time_sleep_until(): Argument #1 ($timestamp) must be between 0 and %d +time_sleep_until(): Argument #1 ($timestamp) must be between 0 and %d +time_sleep_until(): Argument #1 ($timestamp) must be between 0 and %d +time_sleep_until(): Argument #1 ($timestamp) must be between 0 and %d +time_sleep_until(): Argument #1 ($timestamp) must be between 0 and %d +time_sleep_until(): Argument #1 ($timestamp) must be between 0 and %d