diff --git a/NEWS b/NEWS index fc03fd36f15..cacfdc28892 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,10 @@ PHP NEWS . Fixed bug GH-20435 (SensitiveParameter doesn't work for named argument passing to variadic parameter). (ndossche) +- Bz2: + . Fix assertion failures resulting in crashes with stream filter + object parameters. (ndossche) + - Date: . Fix crashes when trying to instantiate uninstantiable classes via date static constructors. (ndossche) @@ -45,6 +49,10 @@ PHP NEWS - Zip: . Fix crash in property existence test. (ndossche) +- Zlib: + . Fix assertion failures resulting in crashes with stream filter + object parameters. (ndossche) + 20 Nov 2025, PHP 8.3.28 - Core: diff --git a/ext/bz2/bz2_filter.c b/ext/bz2/bz2_filter.c index 9b3480b4a5c..b093ac7d752 100644 --- a/ext/bz2/bz2_filter.c +++ b/ext/bz2/bz2_filter.c @@ -337,12 +337,14 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi zval *tmpzval = NULL; if (Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) { - if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "concatenated", sizeof("concatenated")-1))) { + HashTable *ht = HASH_OF(filterparams); + + if ((tmpzval = zend_hash_str_find_ind(ht, "concatenated", sizeof("concatenated")-1))) { data->expect_concatenated = zend_is_true(tmpzval); tmpzval = NULL; } - tmpzval = zend_hash_str_find(HASH_OF(filterparams), "small", sizeof("small")-1); + tmpzval = zend_hash_str_find_ind(ht, "small", sizeof("small")-1); } else { tmpzval = filterparams; } @@ -362,7 +364,9 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi zval *tmpzval; if (Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) { - if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "blocks", sizeof("blocks")-1))) { + HashTable *ht = HASH_OF(filterparams); + + if ((tmpzval = zend_hash_str_find_ind(ht, "blocks", sizeof("blocks")-1))) { /* How much memory to allocate (1 - 9) x 100kb */ zend_long blocks = zval_get_long(tmpzval); if (blocks < 1 || blocks > 9) { @@ -372,7 +376,7 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi } } - if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "work", sizeof("work")-1))) { + if ((tmpzval = zend_hash_str_find_ind(ht, "work", sizeof("work")-1))) { /* Work Factor (0 - 250) */ zend_long work = zval_get_long(tmpzval); if (work < 0 || work > 250) { diff --git a/ext/bz2/tests/filter_broken_object_options.phpt b/ext/bz2/tests/filter_broken_object_options.phpt new file mode 100644 index 00000000000..84e49a64ccb --- /dev/null +++ b/ext/bz2/tests/filter_broken_object_options.phpt @@ -0,0 +1,25 @@ +--TEST-- +bz2 filter assertion failure with non-dynamic properties in filter param object +--EXTENSIONS-- +bz2 +--FILE-- + +--EXPECT-- +Hello world, hopefully not broken diff --git a/ext/phar/stream.c b/ext/phar/stream.c index 1151b520bba..c455a8880d2 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -211,18 +211,18 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha php_url_free(resource); efree(internal_file); - if (context && Z_TYPE(context->options) != IS_UNDEF && (pzoption = zend_hash_str_find(HASH_OF(&context->options), "phar", sizeof("phar")-1)) != NULL) { + if (context && Z_TYPE(context->options) != IS_UNDEF && (pzoption = zend_hash_str_find_ind(HASH_OF(&context->options), "phar", sizeof("phar")-1)) != NULL) { pharcontext = HASH_OF(pzoption); if (idata->internal_file->uncompressed_filesize == 0 && idata->internal_file->compressed_filesize == 0 - && (pzoption = zend_hash_str_find(pharcontext, "compress", sizeof("compress")-1)) != NULL + && (pzoption = zend_hash_str_find_ind(pharcontext, "compress", sizeof("compress")-1)) != NULL && Z_TYPE_P(pzoption) == IS_LONG && (Z_LVAL_P(pzoption) & ~PHAR_ENT_COMPRESSION_MASK) == 0 ) { idata->internal_file->flags &= ~PHAR_ENT_COMPRESSION_MASK; idata->internal_file->flags |= Z_LVAL_P(pzoption); } - if ((pzoption = zend_hash_str_find(pharcontext, "metadata", sizeof("metadata")-1)) != NULL) { + if ((pzoption = zend_hash_str_find_ind(pharcontext, "metadata", sizeof("metadata")-1)) != NULL) { phar_metadata_tracker_free(&idata->internal_file->metadata_tracker, idata->internal_file->is_persistent); metadata = pzoption; diff --git a/ext/zlib/tests/filter_broken_object_options.phpt b/ext/zlib/tests/filter_broken_object_options.phpt new file mode 100644 index 00000000000..beb0fef9fb1 --- /dev/null +++ b/ext/zlib/tests/filter_broken_object_options.phpt @@ -0,0 +1,21 @@ +--TEST-- +zlib filter assertion failure with non-dynamic properties in filter param object +--EXTENSIONS-- +zlib +--FILE-- + +--EXPECT-- +Hello world, hopefully not broken diff --git a/ext/zlib/zlib_filter.c b/ext/zlib/zlib_filter.c index 24d418ae04c..e5491afec39 100644 --- a/ext/zlib/zlib_filter.c +++ b/ext/zlib/zlib_filter.c @@ -323,7 +323,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f zval *tmpzval; if ((Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) && - (tmpzval = zend_hash_str_find(HASH_OF(filterparams), "window", sizeof("window") - 1))) { + (tmpzval = zend_hash_str_find_ind(HASH_OF(filterparams), "window", sizeof("window") - 1))) { /* log-2 base of history window (9 - 15) */ zend_long tmp = zval_get_long(tmpzval); if (tmp < -MAX_WBITS || tmp > MAX_WBITS + 32) { @@ -354,8 +354,10 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f switch (Z_TYPE_P(filterparams)) { case IS_ARRAY: - case IS_OBJECT: - if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "memory", sizeof("memory") -1))) { + case IS_OBJECT: { + HashTable *ht = HASH_OF(filterparams); + + if ((tmpzval = zend_hash_str_find_ind(ht, "memory", sizeof("memory") -1))) { /* Memory Level (1 - 9) */ tmp = zval_get_long(tmpzval); if (tmp < 1 || tmp > MAX_MEM_LEVEL) { @@ -365,7 +367,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f } } - if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "window", sizeof("window") - 1))) { + if ((tmpzval = zend_hash_str_find_ind(ht, "window", sizeof("window") - 1))) { /* log-2 base of history window (9 - 15) */ tmp = zval_get_long(tmpzval); if (tmp < -MAX_WBITS || tmp > MAX_WBITS + 16) { @@ -375,13 +377,14 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f } } - if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "level", sizeof("level") - 1))) { + if ((tmpzval = zend_hash_str_find_ind(ht, "level", sizeof("level") - 1))) { tmp = zval_get_long(tmpzval); /* Pseudo pass through to catch level validating code */ goto factory_setlevel; } break; + } case IS_STRING: case IS_DOUBLE: case IS_LONG: