diff --git a/NEWS b/NEWS index 2bbe43032ece..363c52506403 100644 --- a/NEWS +++ b/NEWS @@ -164,6 +164,7 @@ PHP NEWS ignored. (ndossche) . Fixed a bypass of the magic ".phar" directory protection in Phar::addEmptyDir() for paths starting with "/.phar". (Weilin Du) + . Fixed an integer underflow when parsing ZIP extra fields. (Weilin Du) . Phar::addEmptyDir() now allows non-magic directory names that merely share the ".phar" prefix. (Weilin Du) . Support overridden methods in SplFileInfo for getMTime() and getPathname() @@ -254,6 +255,8 @@ PHP NEWS (Weilin Du) . getenv() and putenv() now raises a ValueError when the first argument contains null bytes. (Weilin Du) + . dl() now raises a ValueError when the $extension_filename argument + contains null bytes. (Weilin Du) . parse_str() now raises a ValueError when the $string argument contains null bytes. (Weilin Du) . proc_open() now raises a ValueError when the $cwd argument contains diff --git a/UPGRADING b/UPGRADING index bdadc6efbefc..a9b1f34eae5a 100644 --- a/UPGRADING +++ b/UPGRADING @@ -151,6 +151,8 @@ PHP 8.6 UPGRADE NOTES argument value is passed. . getenv() and putenv() now raises a ValueError when the first argument contains null bytes. + . dl() now raises a ValueError when the $extension_filename argument + contains null bytes. . parse_str() now raises a ValueError when the $string argument contains null bytes. . linkinfo() now raises a ValueError when the $path argument is empty. @@ -233,6 +235,10 @@ PHP 8.6 UPGRADE NOTES tcp_keepintvl and tcp_keepcnt that allow setting socket keepalive options. . Allowed casting casting filtered streams as file descriptor for select. + . Added the "write_seek_mode stream" filter parameter for the bz2, iconv, + zlib, and string stream filters. This parameter must be set via an + associative array where the key is "write_seek_mode stream" and the + value is one of the following strings "preserve", "reset", or "strict". - URI: . Added Uri\Rfc3986\Uri:getUriType() and Uri\WhatWg\Url:isSpecialScheme(). diff --git a/ext/phar/tests/zip/zip_extra_underflow.phpt b/ext/phar/tests/zip/zip_extra_underflow.phpt new file mode 100644 index 000000000000..e37a3493b663 --- /dev/null +++ b/ext/phar/tests/zip/zip_extra_underflow.phpt @@ -0,0 +1,91 @@ +--TEST-- +Phar: ZIP extra field length must not underflow +--EXTENSIONS-- +phar +--FILE-- +getMTime(), "\n"; +} catch (Exception $e) { + echo $e->getMessage(), "\n"; +} +?> +--CLEAN-- + +--EXPECTF-- +phar error: Unable to process extra field header for file in central directory in zip-based phar "%szip_extra_underflow.zip" diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 7811865e3e69..5aa3f552b2ab 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -39,19 +39,30 @@ static inline void phar_write_16(char buffer[2], uint32_t value) # define PHAR_SET_32(var, value) phar_write_32(var, (uint32_t) (value)); # define PHAR_SET_16(var, value) phar_write_16(var, (uint16_t) (value)); -static zend_result phar_zip_process_extra(php_stream *fp, phar_entry_info *entry, uint16_t len) /* {{{ */ +static zend_result phar_zip_process_extra(php_stream *fp, phar_entry_info *entry, uint16_t extra_len) /* {{{ */ { union { phar_zip_extra_field_header header; phar_zip_unix3 unix3; phar_zip_unix_time time; } h; + size_t len = extra_len; size_t read; - do { + while (len) { + size_t header_size; + + if (len < sizeof(h.header)) { + return FAILURE; + } if (sizeof(h.header) != php_stream_read(fp, (char *) &h.header, sizeof(h.header))) { return FAILURE; } + len -= sizeof(h.header); + header_size = PHAR_GET_16(h.header.size); + if (header_size > len) { + return FAILURE; + } if (h.header.tag[0] == 'U' && h.header.tag[1] == 'T') { /* Unix timestamp header found. @@ -60,7 +71,6 @@ static zend_result phar_zip_process_extra(php_stream *fp, phar_entry_info *entry * We only store the modification time in the entry, so only read that. */ const size_t min_size = 5; - uint16_t header_size = PHAR_GET_16(h.header.size); if (header_size >= min_size) { read = php_stream_read(fp, &h.time.flags, min_size); if (read != min_size) { @@ -71,12 +81,11 @@ static zend_result phar_zip_process_extra(php_stream *fp, phar_entry_info *entry entry->timestamp = PHAR_GET_32(h.time.time); } - len -= header_size + 4; - /* Consume remaining bytes */ - if (header_size != read) { - php_stream_seek(fp, header_size - read, SEEK_CUR); + if (header_size != read && -1 == php_stream_seek(fp, header_size - read, SEEK_CUR)) { + return FAILURE; } + len -= header_size; continue; } /* Fallthrough to next if to skip header */ @@ -84,23 +93,36 @@ static zend_result phar_zip_process_extra(php_stream *fp, phar_entry_info *entry if (h.header.tag[0] != 'n' || h.header.tag[1] != 'u') { /* skip to next header */ - php_stream_seek(fp, PHAR_GET_16(h.header.size), SEEK_CUR); - len -= PHAR_GET_16(h.header.size) + 4; + if (header_size && -1 == php_stream_seek(fp, header_size, SEEK_CUR)) { + return FAILURE; + } + len -= header_size; continue; } /* unix3 header found */ - read = php_stream_read(fp, (char *) &(h.unix3.crc32), sizeof(h.unix3) - sizeof(h.header)); - len -= read + 4; + size_t unix3_size = sizeof(h.unix3) - sizeof(h.header); + size_t field_size = header_size; + if (field_size == unix3_size - sizeof(h.unix3.crc32)) { + /* Some archives omit the CRC32 from the unix3 size field. */ + field_size = unix3_size; + } + if (field_size < unix3_size || field_size > len) { + return FAILURE; + } - if (sizeof(h.unix3) - sizeof(h.header) != read) { + read = php_stream_read(fp, (char *) &(h.unix3.crc32), unix3_size); + if (unix3_size != read) { return FAILURE; } - if (PHAR_GET_16(h.unix3.size) > sizeof(h.unix3) - 4) { + if (field_size > unix3_size) { /* skip symlink filename - we may add this support in later */ - php_stream_seek(fp, PHAR_GET_16(h.unix3.size) - sizeof(h.unix3.size), SEEK_CUR); + if (-1 == php_stream_seek(fp, field_size - unix3_size, SEEK_CUR)) { + return FAILURE; + } } + len -= field_size; /* set permissions */ entry->flags &= PHAR_ENT_COMPRESSION_MASK; @@ -111,7 +133,7 @@ static zend_result phar_zip_process_extra(php_stream *fp, phar_entry_info *entry entry->flags |= PHAR_GET_16(h.unix3.perms) & PHAR_ENT_PERM_MASK; } - } while (len); + } return SUCCESS; } diff --git a/ext/standard/dl.c b/ext/standard/dl.c index a6d0ced6fa86..ca8ba57a16e9 100644 --- a/ext/standard/dl.c +++ b/ext/standard/dl.c @@ -43,7 +43,7 @@ PHPAPI PHP_FUNCTION(dl) size_t filename_len; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(filename, filename_len) + Z_PARAM_PATH(filename, filename_len) ZEND_PARSE_PARAMETERS_END(); if (!PG(enable_dl)) { diff --git a/ext/standard/io_poll.c b/ext/standard/io_poll.c index c500247dc8be..4bb7f6a80688 100644 --- a/ext/standard/io_poll.c +++ b/ext/standard/io_poll.c @@ -44,7 +44,7 @@ static zend_object_handlers php_io_poll_watcher_object_handlers; static zend_object_handlers php_io_poll_handle_object_handlers; /* Watcher object structure */ -typedef struct { +typedef struct php_io_poll_watcher_object { php_poll_handle_object *handle; uint32_t watched_events; uint32_t triggered_events; @@ -55,15 +55,16 @@ typedef struct { } php_io_poll_watcher_object; /* Context object structure */ -typedef struct { +typedef struct php_io_poll_context_object { php_poll_ctx *ctx; HashTable *watchers; /* Maps handle pointer -> watcher object */ zend_object std; } php_io_poll_context_object; /* Stream poll handle specific data */ -typedef struct { +typedef struct php_stream_poll_handle_data { php_stream *stream; + zend_resource *res; } php_stream_poll_handle_data; /* Accessor macros */ @@ -250,7 +251,9 @@ static void php_stream_poll_handle_cleanup(php_poll_handle_object *handle) { php_stream_poll_handle_data *data = (php_stream_poll_handle_data *) handle->handle_data; if (data) { - /* Don't close the stream - user still owns it */ + if (data->res) { + zend_list_delete(data->res); + } efree(data); handle->handle_data = NULL; } @@ -331,6 +334,15 @@ static void php_io_poll_context_free_object(zend_object *obj) { php_io_poll_context_object *intern = PHP_POLL_CONTEXT_OBJ_FROM_ZOBJ(obj); + if (intern->watchers) { + zval *zv; + ZEND_HASH_FOREACH_VAL(intern->watchers, zv) { + php_io_poll_watcher_object *watcher = PHP_POLL_WATCHER_OBJ_FROM_ZOBJ(Z_OBJ_P(zv)); + watcher->active = false; + watcher->poll_ctx = NULL; + } ZEND_HASH_FOREACH_END(); + } + if (intern->ctx) { php_poll_destroy(intern->ctx); } @@ -343,6 +355,36 @@ static void php_io_poll_context_free_object(zend_object *obj) zend_object_std_dtor(&intern->std); } +static HashTable *php_io_poll_watcher_get_gc(zend_object *obj, zval **table, int *n) +{ + php_io_poll_watcher_object *intern = PHP_POLL_WATCHER_OBJ_FROM_ZOBJ(obj); + zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); + + zend_get_gc_buffer_add_zval(gc_buffer, &intern->data); + if (intern->handle) { + zend_get_gc_buffer_add_obj(gc_buffer, &intern->handle->std); + } + + zend_get_gc_buffer_use(gc_buffer, table, n); + return NULL; +} + +static HashTable *php_io_poll_context_get_gc(zend_object *obj, zval **table, int *n) +{ + php_io_poll_context_object *intern = PHP_POLL_CONTEXT_OBJ_FROM_ZOBJ(obj); + zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); + + if (intern->watchers) { + zval *zv; + ZEND_HASH_FOREACH_VAL(intern->watchers, zv) { + zend_get_gc_buffer_add_zval(gc_buffer, zv); + } ZEND_HASH_FOREACH_END(); + } + + zend_get_gc_buffer_use(gc_buffer, table, n); + return NULL; +} + /* Utility functions */ static zend_always_inline zend_ulong php_io_poll_compute_ptr_key(void *ptr) @@ -448,13 +490,19 @@ PHP_METHOD(StreamPollHandle, __construct) php_poll_handle_object *intern = PHP_POLL_HANDLE_OBJ_FROM_ZV(getThis()); + if (intern->handle_data) { + zend_throw_error(NULL, "StreamPollHandle object is already constructed"); + RETURN_THROWS(); + } + /* Set up stream-specific data */ php_stream_poll_handle_data *data = emalloc(sizeof(php_stream_poll_handle_data)); data->stream = stream; + data->res = stream->res; intern->handle_data = data; /* Add reference to stream */ - GC_ADDREF(stream->res); + GC_ADDREF(data->res); } PHP_METHOD(StreamPollHandle, getStream) @@ -657,6 +705,11 @@ PHP_METHOD(Io_Poll_Context, __construct) php_io_poll_context_object *intern = PHP_POLL_CONTEXT_OBJ_FROM_ZV(getThis()); + if (intern->ctx) { + zend_throw_error(NULL, "Io\\Poll\\Context object is already constructed"); + RETURN_THROWS(); + } + php_poll_backend_type backend_type = PHP_POLL_BACKEND_AUTO; if (backend_obj != NULL) { backend_type = php_io_poll_backend_enum_to_type(Z_OBJ_P(backend_obj)); @@ -861,6 +914,7 @@ PHP_MINIT_FUNCTION(poll) memcpy(&php_io_poll_handle_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); php_io_poll_handle_object_handlers.offset = offsetof(php_poll_handle_object, std); php_io_poll_handle_object_handlers.free_obj = php_poll_handle_object_free; + php_io_poll_handle_object_handlers.clone_obj = NULL; php_stream_poll_handle_class_entry->default_object_handlers = &php_io_poll_handle_object_handlers; /* Register Watcher class */ @@ -871,6 +925,8 @@ PHP_MINIT_FUNCTION(poll) sizeof(zend_object_handlers)); php_io_poll_watcher_object_handlers.offset = offsetof(php_io_poll_watcher_object, std); php_io_poll_watcher_object_handlers.free_obj = php_io_poll_watcher_free_object; + php_io_poll_watcher_object_handlers.get_gc = php_io_poll_watcher_get_gc; + php_io_poll_watcher_object_handlers.clone_obj = NULL; php_io_poll_watcher_class_entry->default_object_handlers = &php_io_poll_watcher_object_handlers; /* Register Context class */ @@ -881,6 +937,8 @@ PHP_MINIT_FUNCTION(poll) sizeof(zend_object_handlers)); php_io_poll_context_object_handlers.offset = offsetof(php_io_poll_context_object, std); php_io_poll_context_object_handlers.free_obj = php_io_poll_context_free_object; + php_io_poll_context_object_handlers.get_gc = php_io_poll_context_get_gc; + php_io_poll_context_object_handlers.clone_obj = NULL; php_io_poll_context_class_entry->default_object_handlers = &php_io_poll_context_object_handlers; /* Register exception hierarchy */ diff --git a/ext/standard/io_poll.stub.php b/ext/standard/io_poll.stub.php index 689099a0b398..82bc00e0aaca 100644 --- a/ext/standard/io_poll.stub.php +++ b/ext/standard/io_poll.stub.php @@ -39,7 +39,7 @@ interface Handle { } - /* + /** * @strict-properties * @not-serializable */ @@ -70,7 +70,7 @@ public function modifyData(mixed $data): void {} public function remove(): void {} } - /* + /** * @strict-properties * @not-serializable */ @@ -145,7 +145,7 @@ class InvalidHandleException extends PollException {} } namespace { - /* + /** * @strict-properties * @not-serializable */ diff --git a/ext/standard/io_poll_arginfo.h b/ext/standard/io_poll_arginfo.h index 5272a2b2739b..ced48021eaad 100644 --- a/ext/standard/io_poll_arginfo.h +++ b/ext/standard/io_poll_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit io_poll.stub.php instead. - * Stub hash: 3791f4b8eefbab06da9386cff3c82974a3c080a2 */ + * Stub hash: 4383509df1f1ebcbf6188feb346cbe4805bb0cc5 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Io_Poll_Backend_getAvailableBackends, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -195,7 +195,7 @@ static zend_class_entry *register_class_Io_Poll_Watcher(void) zend_class_entry ce, *class_entry; INIT_NS_CLASS_ENTRY(ce, "Io\\Poll", "Watcher", class_Io_Poll_Watcher_methods); - class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL); + class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE); return class_entry; } @@ -205,7 +205,7 @@ static zend_class_entry *register_class_Io_Poll_Context(void) zend_class_entry ce, *class_entry; INIT_NS_CLASS_ENTRY(ce, "Io\\Poll", "Context", class_Io_Poll_Context_methods); - class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL); + class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE); return class_entry; } @@ -387,7 +387,7 @@ static zend_class_entry *register_class_StreamPollHandle(zend_class_entry *class zend_class_entry ce, *class_entry; INIT_CLASS_ENTRY(ce, "StreamPollHandle", class_StreamPollHandle_methods); - class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL); + class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE); zend_class_implements(class_entry, 1, class_entry_Io_Poll_Handle); return class_entry; diff --git a/ext/standard/tests/general_functions/dl_null_bytes.phpt b/ext/standard/tests/general_functions/dl_null_bytes.phpt new file mode 100644 index 000000000000..7f251393ba3b --- /dev/null +++ b/ext/standard/tests/general_functions/dl_null_bytes.phpt @@ -0,0 +1,14 @@ +--TEST-- +dl() rejects null bytes in extension filename +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +dl(): Argument #1 ($extension_filename) must not contain any null bytes diff --git a/ext/standard/tests/poll/poll_clone_not_allowed.phpt b/ext/standard/tests/poll/poll_clone_not_allowed.phpt new file mode 100644 index 000000000000..f31c4c2ecd7f --- /dev/null +++ b/ext/standard/tests/poll/poll_clone_not_allowed.phpt @@ -0,0 +1,26 @@ +--TEST-- +Io\Poll: Context, Watcher and StreamPollHandle are not cloneable +--FILE-- +add($handle, [Io\Poll\Event::Read]); + +foreach ([$ctx, $handle, $watcher] as $obj) { + try { + clone $obj; + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } +} + +echo "done\n"; +?> +--EXPECT-- +Trying to clone an uncloneable object of class Io\Poll\Context +Trying to clone an uncloneable object of class StreamPollHandle +Trying to clone an uncloneable object of class Io\Poll\Watcher +done diff --git a/ext/standard/tests/poll/poll_double_construct.phpt b/ext/standard/tests/poll/poll_double_construct.phpt new file mode 100644 index 000000000000..1fa5b65db38d --- /dev/null +++ b/ext/standard/tests/poll/poll_double_construct.phpt @@ -0,0 +1,28 @@ +--TEST-- +Io\Poll: calling __construct() twice throws instead of leaking +--FILE-- +__construct($r); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +$ctx = pt_new_stream_poll(); +try { + $ctx->__construct(); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +echo "done\n"; +?> +--EXPECT-- +StreamPollHandle object is already constructed +Io\Poll\Context object is already constructed +done diff --git a/ext/standard/tests/poll/poll_stream_handle_close_then_free.phpt b/ext/standard/tests/poll/poll_stream_handle_close_then_free.phpt new file mode 100644 index 000000000000..9a97fad8dd1c --- /dev/null +++ b/ext/standard/tests/poll/poll_stream_handle_close_then_free.phpt @@ -0,0 +1,20 @@ +--TEST-- +Io\Poll: StreamPollHandle cleanup is safe when the stream is closed first +--FILE-- +add(new StreamPollHandle($r), [Io\Poll\Event::Read]); + +// Close the underlying streams before the watcher and handle are freed. +fclose($r); +fclose($w); + +unset($watcher, $ctx); +gc_collect_cycles(); +echo "ok\n"; +?> +--EXPECT-- +ok diff --git a/ext/standard/tests/poll/poll_stream_handle_fd_release.phpt b/ext/standard/tests/poll/poll_stream_handle_fd_release.phpt new file mode 100644 index 000000000000..66d042c17138 --- /dev/null +++ b/ext/standard/tests/poll/poll_stream_handle_fd_release.phpt @@ -0,0 +1,28 @@ +--TEST-- +Io\Poll: StreamPollHandle releases its stream resource (no fd leak) +--SKIPIF-- + +--FILE-- + +--EXPECT-- +bool(true) diff --git a/ext/standard/tests/poll/poll_watcher_gc_cycle.phpt b/ext/standard/tests/poll/poll_watcher_gc_cycle.phpt new file mode 100644 index 000000000000..590649acef8f --- /dev/null +++ b/ext/standard/tests/poll/poll_watcher_gc_cycle.phpt @@ -0,0 +1,31 @@ +--TEST-- +Io\Poll: cycle collector reclaims a Watcher referenced through its own data +--FILE-- +add(new StreamPollHandle($r), [Io\Poll\Event::Read]); + +$c = new Canary(); +$c->ref = $watcher; // Canary -> Watcher +$watcher->modifyData($c); // Watcher->data -> Canary (cycle) + +unset($ctx, $watcher, $c, $r, $w); + +echo "before gc\n"; +gc_collect_cycles(); +echo "after gc\n"; +?> +--EXPECT-- +before gc +Canary freed +after gc diff --git a/ext/standard/tests/poll/poll_watcher_outlives_context.phpt b/ext/standard/tests/poll/poll_watcher_outlives_context.phpt new file mode 100644 index 000000000000..2c058d5b8966 --- /dev/null +++ b/ext/standard/tests/poll/poll_watcher_outlives_context.phpt @@ -0,0 +1,35 @@ +--TEST-- +Io\Poll: Watcher operations are safe after its Context is destroyed +--FILE-- +add(new StreamPollHandle($r), [Io\Poll\Event::Read], "data"); + +// Drop the Context while still holding the Watcher it returned. +unset($ctx); +gc_collect_cycles(); + +var_dump($watcher->isActive()); + +try { + $watcher->remove(); +} catch (Io\Poll\InactiveWatcherException $e) { + echo $e->getMessage(), "\n"; +} + +try { + $watcher->modifyEvents([Io\Poll\Event::Write]); +} catch (Io\Poll\InactiveWatcherException $e) { + echo $e->getMessage(), "\n"; +} + +echo "done\n"; +?> +--EXPECT-- +bool(false) +Cannot remove inactive watcher +Cannot modify inactive watcher +done diff --git a/main/poll/poll_backend_epoll.c b/main/poll/poll_backend_epoll.c index b0dbc4c7dbcf..685339da77d2 100644 --- a/main/poll/poll_backend_epoll.c +++ b/main/poll/poll_backend_epoll.c @@ -18,7 +18,7 @@ #include -typedef struct { +typedef struct epoll_backend_data { int epoll_fd; struct epoll_event *events; int events_capacity; diff --git a/main/poll/poll_backend_eventport.c b/main/poll/poll_backend_eventport.c index f3bb3fa66e34..35e7c61326f1 100644 --- a/main/poll/poll_backend_eventport.c +++ b/main/poll/poll_backend_eventport.c @@ -22,7 +22,7 @@ #include #include -typedef struct { +typedef struct eventport_backend_data { int port_fd; port_event_t *events; int events_capacity; @@ -212,7 +212,7 @@ static zend_result eventport_backend_remove(php_poll_ctx *ctx, int fd) } /* Callback context for associating fds */ -typedef struct { +typedef struct eventport_associate_ctx { eventport_backend_data_t *backend_data; php_poll_ctx *ctx; bool has_error; diff --git a/main/poll/poll_backend_kqueue.c b/main/poll/poll_backend_kqueue.c index 9a654c716d56..3d8e1feb4734 100644 --- a/main/poll/poll_backend_kqueue.c +++ b/main/poll/poll_backend_kqueue.c @@ -27,7 +27,7 @@ #define KQUEUE_FD_GARBAGE_WRITE (1 << 3) /* Write filter fired, needs read cleanup */ #define KQUEUE_FD_HAS_GARBAGE (KQUEUE_FD_GARBAGE_READ | KQUEUE_FD_GARBAGE_WRITE) -typedef struct { +typedef struct kqueue_backend_data { int kqueue_fd; struct kevent *events; int events_capacity; diff --git a/main/poll/poll_backend_poll.c b/main/poll/poll_backend_poll.c index 311c48529bc7..cca81b6fc4fb 100644 --- a/main/poll/poll_backend_poll.c +++ b/main/poll/poll_backend_poll.c @@ -16,7 +16,7 @@ #ifndef PHP_WIN32 -typedef struct { +typedef struct poll_backend_data { php_poll_fd_table *fd_table; struct pollfd *temp_fds; int temp_fds_capacity; @@ -162,7 +162,7 @@ static zend_result poll_backend_remove(php_poll_ctx *ctx, int fd) } /* Context for building struct pollfd array */ -typedef struct { +typedef struct poll_build_context { struct pollfd *fds; int index; } poll_build_context; diff --git a/main/poll/poll_backend_wsapoll.c b/main/poll/poll_backend_wsapoll.c index d8135d7f32a8..101a7cfe0e4b 100644 --- a/main/poll/poll_backend_wsapoll.c +++ b/main/poll/poll_backend_wsapoll.c @@ -19,7 +19,7 @@ #include #include -typedef struct { +typedef struct wsapoll_backend_data { php_poll_fd_table *fd_table; WSAPOLLFD *temp_fds; int temp_fds_capacity; @@ -167,7 +167,7 @@ static zend_result wsapoll_backend_remove(php_poll_ctx *ctx, int fd) } /* Context for building WSAPOLLFD array */ -typedef struct { +typedef struct wsapoll_build_context { WSAPOLLFD *fds; int index; } wsapoll_build_context; diff --git a/main/poll/poll_core.c b/main/poll/poll_core.c index 8422e46c9379..f985dbcdd3eb 100644 --- a/main/poll/poll_core.c +++ b/main/poll/poll_core.c @@ -191,7 +191,8 @@ PHPAPI php_poll_ctx *php_poll_create_by_name(const char *preferred_backend, uint /* Set event capacity hint (optional optimization) */ PHPAPI zend_result php_poll_set_max_events_hint(php_poll_ctx *ctx, int max_events) { - if (UNEXPECTED(!ctx || max_events <= 0)) { + ZEND_ASSERT(ctx); + if (UNEXPECTED(max_events <= 0)) { php_poll_set_error(ctx, PHP_POLL_ERR_INVALID); return FAILURE; } @@ -243,7 +244,8 @@ PHPAPI void php_poll_destroy(php_poll_ctx *ctx) /* Add file descriptor */ PHPAPI zend_result php_poll_add(php_poll_ctx *ctx, int fd, uint32_t events, void *data) { - if (UNEXPECTED(!ctx || !ctx->initialized || fd < 0)) { + ZEND_ASSERT(ctx); + if (UNEXPECTED(!ctx->initialized || fd < 0)) { php_poll_set_error(ctx, PHP_POLL_ERR_INVALID); return FAILURE; } @@ -259,7 +261,8 @@ PHPAPI zend_result php_poll_add(php_poll_ctx *ctx, int fd, uint32_t events, void /* Modify file descriptor */ PHPAPI zend_result php_poll_modify(php_poll_ctx *ctx, int fd, uint32_t events, void *data) { - if (UNEXPECTED(!ctx || !ctx->initialized || fd < 0)) { + ZEND_ASSERT(ctx); + if (UNEXPECTED(!ctx->initialized || fd < 0)) { php_poll_set_error(ctx, PHP_POLL_ERR_INVALID); return FAILURE; } @@ -275,7 +278,8 @@ PHPAPI zend_result php_poll_modify(php_poll_ctx *ctx, int fd, uint32_t events, v /* Remove file descriptor */ PHPAPI zend_result php_poll_remove(php_poll_ctx *ctx, int fd) { - if (UNEXPECTED(!ctx || !ctx->initialized || fd < 0)) { + ZEND_ASSERT(ctx); + if (UNEXPECTED(!ctx->initialized || fd < 0)) { php_poll_set_error(ctx, PHP_POLL_ERR_INVALID); return FAILURE; } @@ -292,7 +296,8 @@ PHPAPI zend_result php_poll_remove(php_poll_ctx *ctx, int fd) PHPAPI int php_poll_wait(php_poll_ctx *ctx, php_poll_event *events, int max_events, const struct timespec *timeout) { - if (UNEXPECTED(!ctx || !ctx->initialized || !events || max_events <= 0)) { + ZEND_ASSERT(ctx); + if (UNEXPECTED(!ctx->initialized || !events || max_events <= 0)) { php_poll_set_error(ctx, PHP_POLL_ERR_INVALID); return -1; } diff --git a/main/streams/filter.c b/main/streams/filter.c index 35dbef455a30..e53c4fa14ba0 100644 --- a/main/streams/filter.c +++ b/main/streams/filter.c @@ -277,7 +277,7 @@ PHPAPI php_stream_filter *_php_stream_filter_alloc(const php_stream_filter_ops * } PHPAPI zend_result php_stream_filter_parse_write_seek_mode( - zval *filterparams, + const zval *filterparams, php_stream_filter_seekable_t *write_seekable) { *write_seekable = PSFS_SEEKABLE_ALWAYS; @@ -285,18 +285,17 @@ PHPAPI zend_result php_stream_filter_parse_write_seek_mode( if (filterparams == NULL) { return SUCCESS; } - if (Z_TYPE_P(filterparams) != IS_ARRAY && Z_TYPE_P(filterparams) != IS_OBJECT) { + if (Z_TYPE_P(filterparams) != IS_ARRAY) { return SUCCESS; } - zval *tmp = zend_hash_str_find_ind(HASH_OF(filterparams), - "write_seek_mode", sizeof("write_seek_mode") - 1); - if (tmp == NULL) { + const zval *write_seek_mode = zend_hash_str_find(Z_ARR_P(filterparams), ZEND_STRL("write_seek_mode")); + if (write_seek_mode == NULL) { return SUCCESS; } zend_string *tmp_str; - zend_string *str = zval_get_tmp_string(tmp, &tmp_str); + const zend_string *str = zval_get_tmp_string(write_seek_mode, &tmp_str); zend_result result = SUCCESS; if (zend_string_equals_literal(str, "preserve")) { diff --git a/main/streams/php_stream_filter_api.h b/main/streams/php_stream_filter_api.h index 111127a8ad1a..20df33897799 100644 --- a/main/streams/php_stream_filter_api.h +++ b/main/streams/php_stream_filter_api.h @@ -144,7 +144,7 @@ PHPAPI void php_stream_filter_free(php_stream_filter *filter); PHPAPI php_stream_filter *_php_stream_filter_alloc(const php_stream_filter_ops *fops, void *abstract, bool persistent, php_stream_filter_seekable_t read_seekable, php_stream_filter_seekable_t write_seekable STREAMS_DC); -PHPAPI zend_result php_stream_filter_parse_write_seek_mode(zval *filterparams, +PHPAPI zend_result php_stream_filter_parse_write_seek_mode(const zval *filterparams, php_stream_filter_seekable_t *write_seekable); PHPAPI int php_stream_filter_get_chain_type(php_stream *stream, php_stream_filter *filter);