[php-src] master: ext/standard: Io\Poll\Context::wait() max events range check
Marc Bennewitz via David Carlier <[email protected]>
| Newsgroups | gmane.comp.php.cvs.general |
|---|---|
| Message-ID | <[email protected]> |
Author: Marc Bennewitz (marc-mabe)
Committer: David Carlier (devnexen)
Date: 2026-08-27T21:38:23+01:00
Commit: https://github.com/php/php-src/commit/b3cbd55a69f957dc830b01141dafcef86205d493
Raw diff: https://github.com/php/php-src/commit/b3cbd55a69f957dc830b01141dafcef86205d493.diff
ext/standard: Io\Poll\Context::wait() max events range check
Reject a $maxEvents value greater than INT_MAX instead of truncating it,
which prevents an integer overflow where SIZEOF_INT < SIZEOF_ZEND_LONG.
Close GH-23468
Changed paths:
A ext/standard/tests/poll/poll_ctx_wait_error.phpt
A ext/standard/tests/poll/poll_ctx_wait_error_int64.phpt
D ext/standard/tests/poll/poll_ctx_wait.phpt
M NEWS
M ext/standard/io_poll.c
Diff:
diff --git a/NEWS b/NEWS
index 871c1c9adde7..df78bf6abe8a 100644
--- a/NEWS
+++ b/NEWS
@@ -30,6 +30,8 @@ PHP NEWS
. Fixed an out-of-bounds read when following a redirect response with an
empty Location header. (iliaal)
. Fixed read buffer compaction in php_stream_filter_flush(). (crystarm)
+ . Io\Poll\Context::wait() now rejects a $maxEvents value greater than
+ INT_MAX instead of truncating it. (marc-mabe)
27 Aug 2026, PHP 8.6.0beta2
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--
+<?php
+if (PHP_INT_SIZE <= 4) {
+ die("skip this test is for > 32bit platforms only");
+}
+?>
+--FILE--
+<?php
+require_once __DIR__ . '/poll.inc';
+
+$poll_ctx = new Io\Poll\Context();
+
+try {
+ $poll_ctx->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