From 17831b5e61bb34941d6f3e9041243fa3db5872b2 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Wed, 26 Aug 2026 09:01:50 +0200 Subject: [PATCH] Io\Poll\Context::wait() max events range check --- ext/standard/io_poll.c | 7 ++++-- ...ctx_wait.phpt => poll_ctx_wait_error.phpt} | 14 +++++++++++ .../tests/poll/poll_ctx_wait_error_int64.phpt | 23 +++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) rename ext/standard/tests/poll/{poll_ctx_wait.phpt => poll_ctx_wait_error.phpt} (58%) create mode 100644 ext/standard/tests/poll/poll_ctx_wait_error_int64.phpt diff --git a/ext/standard/io_poll.c b/ext/standard/io_poll.c index f57813874d52..a8a0563627fa 100644 --- a/ext/standard/io_poll.c +++ b/ext/standard/io_poll.c @@ -804,12 +804,15 @@ PHP_METHOD(Io_Poll_Context, wait) if (max_events <= 0) { max_events = 64; } - } else if (max_events <= 0) { + } else if (UNEXPECTED(max_events <= 0)) { zend_argument_value_error(2, "must be greater than 0"); RETURN_THROWS(); + } else if (ZEND_LONG_INT_OVFL(max_events)) { + zend_argument_value_error(2, "must be less than or equal to %d", INT_MAX); + RETURN_THROWS(); } - php_poll_event *events = safe_emalloc(max_events, sizeof(*events), 0); + php_poll_event *events = safe_emalloc((size_t) max_events, sizeof(*events), 0); int num_events = php_poll_wait(intern->ctx, events, (int) max_events, timeout ? &timeout_ts : NULL); if (num_events < 0) { diff --git a/ext/standard/tests/poll/poll_ctx_wait.phpt b/ext/standard/tests/poll/poll_ctx_wait_error.phpt similarity index 58% rename from ext/standard/tests/poll/poll_ctx_wait.phpt rename to ext/standard/tests/poll/poll_ctx_wait_error.phpt index 5080c1421fdb..c514884c3c6f 100644 --- a/ext/standard/tests/poll/poll_ctx_wait.phpt +++ b/ext/standard/tests/poll/poll_ctx_wait_error.phpt @@ -12,13 +12,27 @@ try { echo $e::class, ': ', $e->getMessage(), PHP_EOL; } +try { + $poll_ctx->wait(maxEvents: PHP_INT_MIN); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + try { $poll_ctx->wait(maxEvents: -1); } catch (Throwable $e) { echo $e::class, ': ', $e->getMessage(), PHP_EOL; } +try { + $poll_ctx->wait(maxEvents: 0); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + ?> --EXPECT-- ValueError: Io\Poll\Context::wait(): Argument #1 ($timeout) must not be negative ValueError: Io\Poll\Context::wait(): Argument #2 ($maxEvents) must be greater than 0 +ValueError: Io\Poll\Context::wait(): Argument #2 ($maxEvents) must be greater than 0 +ValueError: Io\Poll\Context::wait(): Argument #2 ($maxEvents) must be greater than 0 diff --git a/ext/standard/tests/poll/poll_ctx_wait_error_int64.phpt b/ext/standard/tests/poll/poll_ctx_wait_error_int64.phpt new file mode 100644 index 000000000000..3d881050e655 --- /dev/null +++ b/ext/standard/tests/poll/poll_ctx_wait_error_int64.phpt @@ -0,0 +1,23 @@ +--TEST-- +Io\Poll\Context::wait(): Parameter validation upper limit +--SKIPIF-- + 32bit platforms only"); +} +?> +--FILE-- +wait(maxEvents: PHP_INT_MAX); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +ValueError: Io\Poll\Context::wait(): Argument #2 ($maxEvents) must be less than or equal to 2147483647