From 2642a08697448668506237adf591dcdd69de1533 Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Tue, 10 Oct 2023 11:45:26 -0400 Subject: [PATCH 01/66] PHP-8.2 is now for PHP 8.2.13-dev --- NEWS | 5 ++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 850831cead968..20afa169cbdce 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.2.12 +?? ??? ????, PHP 8.2.13 + + +26 Oct 2023, PHP 8.2.12 - Core: . Fixed bug GH-12207 (memory leak when class using trait with doc block). diff --git a/Zend/zend.h b/Zend/zend.h index 1d02cd346fdfe..4ae4b2d8f0670 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.2.12-dev" +#define ZEND_VERSION "4.2.13-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index b55fb1479bf7e..c8521f8f04133 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.2.12-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.2.13-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 74c8f28495e88..41359e73d4d12 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 2 -#define PHP_RELEASE_VERSION 12 +#define PHP_RELEASE_VERSION 13 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.2.12-dev" -#define PHP_VERSION_ID 80212 +#define PHP_VERSION "8.2.13-dev" +#define PHP_VERSION_ID 80213 From be64db59392dbf04a609b75b86facbf444560148 Mon Sep 17 00:00:00 2001 From: Patrick Allaert Date: Tue, 10 Oct 2023 22:54:03 +0200 Subject: [PATCH 02/66] PHP-8.1 is now for PHP 8.1.26-dev --- NEWS | 6 +++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 694493cca265a..9ea10ad8ebeb6 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.25 +?? ??? ????, PHP 8.1.26 + + + +26 Oct 2023, PHP 8.1.25 - Core: . Fixed bug GH-12207 (memory leak when class using trait with doc block). diff --git a/Zend/zend.h b/Zend/zend.h index bc9862de9f687..0df86327eb517 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.25-dev" +#define ZEND_VERSION "4.1.26-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 07fdab313cd4b..464ee54c9cfcf 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.1.25-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.26-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 35782be060ad3..4d3b2f5e1ace5 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 1 -#define PHP_RELEASE_VERSION 25 +#define PHP_RELEASE_VERSION 26 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.25-dev" -#define PHP_VERSION_ID 80125 +#define PHP_VERSION "8.1.26-dev" +#define PHP_VERSION_ID 80126 From 90f2e7607a7a9da1c50f3588adc79e189fd66349 Mon Sep 17 00:00:00 2001 From: Sergei Turchanov Date: Wed, 11 Oct 2023 16:57:18 +1000 Subject: [PATCH 03/66] Reset inheritance_cache pointer of zend_class_entry upon serialization (#12401) to opcache filecache. Usually, when a class is being loaded, a dependency tracking is performed after the call to zend_file_cache_script_store. But sometimes, when opcache cache is empty and there are many simultaneous outstanding requests for compilation, some classes do have their inheritance_cache initialized before the call to zend_file_cache_script_store, and in that case this pointer is serialized as-is. And when such a class is loaded from opcache filecache this pointer also loaded as-is, and now it points to some random location in memory. This causes segfaults occuring when traversing inheritance_cache of such classes. We need to reset inheritance_cache pointer of zend_class_entry upon serialization. This should have been done anyway since it is a sensible strategy to sanitize any memory pointer upon serialization (either by calling SERIALIZE_x macros or setting to NULL or any other deterministic value). --- ext/opcache/zend_file_cache.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index bcee38079b353..7b4b4cbb12112 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -867,6 +867,8 @@ static void zend_file_cache_serialize_class(zval *zv, ZEND_MAP_PTR_INIT(ce->static_members_table, NULL); ZEND_MAP_PTR_INIT(ce->mutable_data, NULL); + + ce->inheritance_cache = NULL; } static void zend_file_cache_serialize_warnings( From 53dbb760dad2c976347a9c093baee0e253b98731 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 10 Oct 2023 18:47:58 +0200 Subject: [PATCH 04/66] Fix use-after-free of constant name The constant name is usually interend. Without opcache, compilation always interns strings. Without opcache, compilation does not intern (new) strings, but persisting of script does. If a script is not stored in shm the constant name will not be interned. The building of enum backing stores was missing a addref for the constant name, leading to a double-free when releasing constants and backing stores of enums. Fixes GH-12366 Closes GH-12405 --- NEWS | 2 ++ Zend/tests/gh12366.inc | 7 +++++++ Zend/tests/gh12366.phpt | 16 ++++++++++++++++ Zend/zend_enum.c | 2 ++ 4 files changed, 27 insertions(+) create mode 100644 Zend/tests/gh12366.inc create mode 100644 Zend/tests/gh12366.phpt diff --git a/NEWS b/NEWS index 20afa169cbdce..60dbe770c07a2 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.13 +- Core: + . Fixed double-free of non-interned enum case name. (ilutov) 26 Oct 2023, PHP 8.2.12 diff --git a/Zend/tests/gh12366.inc b/Zend/tests/gh12366.inc new file mode 100644 index 0000000000000..c0f64e14ba7b5 --- /dev/null +++ b/Zend/tests/gh12366.inc @@ -0,0 +1,7 @@ + +--EXPECT-- +enum(Level::Debug) diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index 25261cf53f880..f807c8196548e 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -229,6 +229,7 @@ zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) ZSTR_VAL(name)); goto failure; } + Z_TRY_ADDREF_P(case_name); zend_hash_index_add_new(backed_enum_table, long_key, case_name); } else { ZEND_ASSERT(ce->enum_backing_type == IS_STRING); @@ -241,6 +242,7 @@ zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) ZSTR_VAL(name)); goto failure; } + Z_TRY_ADDREF_P(case_name); zend_hash_add_new(backed_enum_table, string_key, case_name); } } ZEND_HASH_FOREACH_END(); From 717746114141b9c7b97d9ff207ed135069e722df Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Tue, 10 Oct 2023 17:11:01 +0200 Subject: [PATCH 05/66] Report warning if JIT cannot be enabled Closes GH-12404 --- NEWS | 3 ++- ext/opcache/ZendAccelerator.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 9ea10ad8ebeb6..b56c9d8fb5506 100644 --- a/NEWS +++ b/NEWS @@ -2,7 +2,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.1.26 - +- Opcache: + . Added warning when JIT cannot be enabled. (danog) 26 Oct 2023, PHP 8.1.25 diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 429eadf023eb0..93afd8e415dc5 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -3270,6 +3270,7 @@ static zend_result accel_post_startup(void) || zend_jit_startup(ZSMMG(reserved), jit_size, reattached) != SUCCESS) { JIT_G(enabled) = 0; JIT_G(on) = 0; + zend_accel_error(ACCEL_LOG_WARNING, "Could not enable JIT!"); } } #endif From 1f4159e504133b9c5499f090cc44ec4aa62dec53 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 11 Oct 2023 17:17:11 +0200 Subject: [PATCH 06/66] [ci skip] NEWS Entry for 90f2e7607a. --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index b56c9d8fb5506..6d12cf0335d6e 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,8 @@ PHP NEWS - Opcache: . Added warning when JIT cannot be enabled. (danog) + . Fixed bug GH-8143 (Crashes in zend_accel_inheritance_cache_find since + upgrading to 8.1.3 due to corrupt on-disk file cache). (turchanov) 26 Oct 2023, PHP 8.1.25 From 71f14510f6643f9c0ba4dbb518a8ea75d093bc18 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 9 Oct 2023 11:46:55 +0300 Subject: [PATCH 07/66] Fix GH-11121: ReflectionFiber segfault Closes GH-12391. Co-authored-by: Aaron Piotrowski --- NEWS | 3 + Zend/zend_fibers.c | 6 +- .../tests/ReflectionFiber_bug_gh11121_1.phpt | 62 ++++++++++++++++++ .../tests/ReflectionFiber_bug_gh11121_2.phpt | 63 +++++++++++++++++++ 4 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 ext/reflection/tests/ReflectionFiber_bug_gh11121_1.phpt create mode 100644 ext/reflection/tests/ReflectionFiber_bug_gh11121_2.phpt diff --git a/NEWS b/NEWS index 6d12cf0335d6e..b5c21e37a675c 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.1.26 +- Fiber: + . Fixed bug GH-11121 (ReflectionFiber segfault). (danog, trowski, bwoebi) + - Opcache: . Added warning when JIT cannot be enabled. (danog) . Fixed bug GH-8143 (Crashes in zend_accel_inheritance_cache_find since diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 59aa63ba21b43..c80d65868d37e 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -554,6 +554,10 @@ static zend_always_inline zend_fiber_transfer zend_fiber_resume(zend_fiber *fibe { zend_fiber *previous = EG(active_fiber); + if (previous) { + previous->execute_data = EG(current_execute_data); + } + fiber->caller = EG(current_fiber_context); EG(active_fiber) = fiber; @@ -571,6 +575,7 @@ static zend_always_inline zend_fiber_transfer zend_fiber_suspend(zend_fiber *fib zend_fiber_context *caller = fiber->caller; fiber->previous = EG(current_fiber_context); fiber->caller = NULL; + fiber->execute_data = EG(current_execute_data); return zend_fiber_switch_to(caller, value, false); } @@ -741,7 +746,6 @@ ZEND_METHOD(Fiber, suspend) ZEND_ASSERT(fiber->context.status == ZEND_FIBER_STATUS_RUNNING || fiber->context.status == ZEND_FIBER_STATUS_SUSPENDED); - fiber->execute_data = EG(current_execute_data); fiber->stack_bottom->prev_execute_data = NULL; zend_fiber_transfer transfer = zend_fiber_suspend(fiber, value); diff --git a/ext/reflection/tests/ReflectionFiber_bug_gh11121_1.phpt b/ext/reflection/tests/ReflectionFiber_bug_gh11121_1.phpt new file mode 100644 index 0000000000000..de0c9abec9ee5 --- /dev/null +++ b/ext/reflection/tests/ReflectionFiber_bug_gh11121_1.phpt @@ -0,0 +1,62 @@ +--TEST-- +GH-11121: Segfault when using ReflectionFiber +--FILE-- +getTrace()); + }))->start(); +} + +$f = new Fiber(function() { f(); max(...[1,2,3,4,5,6,7,8,9,10,11,12]); g(); }); +$f->start(); +$f->resume(); + +?> +--EXPECTF-- +array(3) { + [0]=> + array(7) { + ["file"]=> + string(%d) "%sReflectionFiber_bug_gh11121_1.php" + ["line"]=> + int(10) + ["function"]=> + string(5) "start" + ["class"]=> + string(5) "Fiber" + ["object"]=> + object(Fiber)#3 (0) { + } + ["type"]=> + string(2) "->" + ["args"]=> + array(0) { + } + } + [1]=> + array(4) { + ["file"]=> + string(%d) "%sReflectionFiber_bug_gh11121_1.php" + ["line"]=> + int(13) + ["function"]=> + string(1) "g" + ["args"]=> + array(0) { + } + } + [2]=> + array(2) { + ["function"]=> + string(9) "{closure}" + ["args"]=> + array(0) { + } + } +} diff --git a/ext/reflection/tests/ReflectionFiber_bug_gh11121_2.phpt b/ext/reflection/tests/ReflectionFiber_bug_gh11121_2.phpt new file mode 100644 index 0000000000000..b7affb2ca0b1c --- /dev/null +++ b/ext/reflection/tests/ReflectionFiber_bug_gh11121_2.phpt @@ -0,0 +1,63 @@ +--TEST-- +GH-11121: Segfault when using ReflectionFiber +--FILE-- +getTrace()); + }))->start(); +} + +$f = new Fiber(function() { f(); g(); }); +$f->start(); +$f->resume(); + +?> +--EXPECTF-- +array(3) { + [0]=> + array(7) { + ["file"]=> + string(%d) "%sReflectionFiber_bug_gh11121_2.php" + ["line"]=> + int(11) + ["function"]=> + string(5) "start" + ["class"]=> + string(5) "Fiber" + ["object"]=> + object(Fiber)#3 (0) { + } + ["type"]=> + string(2) "->" + ["args"]=> + array(0) { + } + } + [1]=> + array(4) { + ["file"]=> + string(%d) "%sReflectionFiber_bug_gh11121_2.php" + ["line"]=> + int(14) + ["function"]=> + string(1) "g" + ["args"]=> + array(0) { + } + } + [2]=> + array(2) { + ["function"]=> + string(9) "{closure}" + ["args"]=> + array(0) { + } + } +} From 7e4a3236d92bc4bcad9ad6661d96f3da92d9c4d3 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 11 Oct 2023 00:11:16 +0200 Subject: [PATCH 08/66] Fix GH-12392: Segmentation fault on SoapClient::__getTypes There are two issues: - UAF because the hashmap resized while being iterated over, yet the local variables used internally in the macros are not updated. - The hashmap being iterated over is modified: entries are deleted after other entries have been added. This causes the deletion to fail sometimes because indices of buckets have shifted. Fix it by using a while loop iteration and HashPosition position tracker instead. Issue exists on PHP 8.1 too, but is much harder to trigger. The test file reproduces the issue reliably on PHP 8.2 and up. Closes GH-12409. --- NEWS | 4 +++ ext/soap/php_schema.c | 18 +++++++---- ext/soap/tests/gh12392.phpt | 28 +++++++++++++++++ ext/soap/tests/gh12392.wsdl | 61 +++++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 ext/soap/tests/gh12392.phpt create mode 100644 ext/soap/tests/gh12392.wsdl diff --git a/NEWS b/NEWS index b5c21e37a675c..0ba555c819b54 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,10 @@ PHP NEWS . Fixed bug GH-8143 (Crashes in zend_accel_inheritance_cache_find since upgrading to 8.1.3 due to corrupt on-disk file cache). (turchanov) +- SOAP: + . Fixed bug GH-12392 (Segmentation fault on SoapClient::__getTypes). + (nielsdos) + 26 Oct 2023, PHP 8.1.25 - Core: diff --git a/ext/soap/php_schema.c b/ext/soap/php_schema.c index e93679a55ea39..521c5d0f1d9ed 100644 --- a/ext/soap/php_schema.c +++ b/ext/soap/php_schema.c @@ -2261,17 +2261,23 @@ static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type) schema_content_model_fixup(ctx, type->model); } if (type->attributes) { - zend_string *str_key; - zend_ulong index; + HashPosition pos; + zend_hash_internal_pointer_reset_ex(type->attributes, &pos); - ZEND_HASH_FOREACH_KEY_PTR(type->attributes, index, str_key, attr) { - if (str_key) { + while ((attr = zend_hash_get_current_data_ptr_ex(type->attributes, &pos)) != NULL) { + zend_string *str_key; + zend_ulong index; + + if (zend_hash_get_current_key_ex(type->attributes, &str_key, &index, &pos) == HASH_KEY_IS_STRING) { schema_attribute_fixup(ctx, attr); + zend_result result = zend_hash_move_forward_ex(type->attributes, &pos); + ZEND_ASSERT(result == SUCCESS); } else { schema_attributegroup_fixup(ctx, attr, type->attributes); - zend_hash_index_del(type->attributes, index); + zend_result result = zend_hash_index_del(type->attributes, index); + ZEND_ASSERT(result == SUCCESS); } - } ZEND_HASH_FOREACH_END(); + } } } diff --git a/ext/soap/tests/gh12392.phpt b/ext/soap/tests/gh12392.phpt new file mode 100644 index 0000000000000..8a234ba025be9 --- /dev/null +++ b/ext/soap/tests/gh12392.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-12392 (Segmentation fault on SoapClient::__getTypes) +--EXTENSIONS-- +soap +--FILE-- + WSDL_CACHE_NONE]); +echo 'Client created!' . "\n"; + +$types = $client->__getTypes(); +echo 'Got types!' . "\n"; + +var_dump($types); + +?> +--EXPECT-- +Client created! +Got types! +array(1) { + [0]=> + string(62) "struct dummy { + string foo; + string a; + string b; + string c; +}" +} diff --git a/ext/soap/tests/gh12392.wsdl b/ext/soap/tests/gh12392.wsdl new file mode 100644 index 0000000000000..5e9a7ea094fb8 --- /dev/null +++ b/ext/soap/tests/gh12392.wsdl @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 4332546bbf67e7f1cdfeed23ab719fad149524dc Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 10 Oct 2023 13:06:10 +0200 Subject: [PATCH 09/66] Move ARM build to CircleCI Closes GH-12415 --- .circleci/config.yml | 197 +++++++++++++++++ .cirrus.yml | 200 ------------------ .github/workflows/push.yml | 2 + .../tests/pdo_mysql___construct.phpt | 2 +- ext/standard/tests/file/bug52820.phpt | 2 +- 5 files changed, 201 insertions(+), 202 deletions(-) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000000000..2320d2baca9c2 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,197 @@ +version: 2.1 + +jobs: + arm: + resource_class: arm.medium + docker: + - image: cimg/base:current-22.04 + - image: mysql:8 + environment: + MYSQL_ALLOW_EMPTY_PASSWORD: true + MYSQL_ROOT_PASSWORD: '' + MYSQL_DATABASE: test + - image: postgres:16 + environment: + POSTGRES_PASSWORD: postgres + POSTGRES_DB: test + environment: + LANGUAGE: '' + LANG: en_US.UTF-8 + MYSQL_TEST_HOST: '127.0.0.1' + MYSQL_TEST_PASSWD: '' + MYSQL_TEST_USER: root + PDO_MYSQL_TEST_DSN: 'mysql:host=127.0.0.1;dbname=test' + PDO_MYSQL_TEST_PASS: '' + PDO_MYSQL_TEST_USER: root + PDO_PGSQL_TEST_DSN: 'pgsql:host=127.0.0.1 port=5432 dbname=test user=postgres password=postgres' + steps: + - checkout + - run: + name: apt + command: | + export DEBIAN_FRONTEND=noninteractive + sudo apt-get update -y + sudo apt-get install -y \ + gcc \ + g++ \ + autoconf \ + bison \ + re2c \ + locales \ + locales-all \ + ldap-utils \ + openssl \ + slapd \ + libgmp-dev \ + libicu-dev \ + libtidy-dev \ + libenchant-2-dev \ + libaspell-dev \ + libpspell-dev \ + libsasl2-dev \ + libxpm-dev \ + libzip-dev \ + libbz2-dev \ + libsqlite3-dev \ + libwebp-dev \ + libonig-dev \ + libkrb5-dev \ + libgssapi-krb5-2 \ + libcurl4-openssl-dev \ + libxml2-dev \ + libxslt1-dev \ + libpq-dev \ + libreadline-dev \ + libldap2-dev \ + libsodium-dev \ + libargon2-0-dev \ + libmm-dev \ + libsnmp-dev \ + snmpd \ + `#snmp-mibs-downloader` \ + freetds-dev \ + `#unixodbc-dev` \ + libc-client-dev \ + dovecot-core \ + dovecot-pop3d \ + dovecot-imapd \ + sendmail \ + firebird-dev \ + liblmdb-dev \ + libtokyocabinet-dev \ + libdb-dev \ + libqdbm-dev \ + libjpeg-dev \ + libpng-dev \ + libfreetype6-dev + - run: + name: ./configure + command: | + ./buildconf -f + ./configure \ + --enable-debug \ + --enable-zts \ + --enable-option-checking=fatal \ + --prefix=/usr \ + --enable-phpdbg \ + --enable-fpm \ + --enable-opcache \ + --with-pdo-mysql=mysqlnd \ + --with-mysqli=mysqlnd \ + --with-pgsql \ + --with-pdo-pgsql \ + --with-pdo-sqlite \ + --enable-intl \ + --without-pear \ + --enable-gd \ + --with-jpeg \ + --with-webp \ + --with-freetype \ + --with-xpm \ + --enable-exif \ + --with-zip \ + --with-zlib \ + --with-zlib-dir=/usr \ + --enable-soap \ + --enable-xmlreader \ + --with-xsl \ + --with-tidy \ + --enable-sysvsem \ + --enable-sysvshm \ + --enable-shmop \ + --enable-pcntl \ + --with-readline \ + --enable-mbstring \ + --with-curl \ + --with-gettext \ + --enable-sockets \ + --with-bz2 \ + --with-openssl \ + --with-gmp \ + --enable-bcmath \ + --enable-calendar \ + --enable-ftp \ + --with-pspell=/usr \ + --with-enchant=/usr \ + --with-kerberos \ + --enable-sysvmsg \ + --with-ffi \ + --enable-zend-test \ + --enable-dl-test=shared \ + --with-ldap \ + --with-ldap-sasl \ + --with-password-argon2 \ + --with-mhash \ + --with-sodium \ + --enable-dba \ + --with-cdb \ + --enable-flatfile \ + --enable-inifile \ + --with-tcadb \ + --with-lmdb \ + --with-qdbm \ + --with-snmp \ + `#--with-unixODBC` \ + --with-imap \ + --with-kerberos \ + --with-imap-ssl \ + `#--with-pdo-odbc=unixODBC,/usr` \ + `#--with-pdo-oci=shared,instantclient,/opt/oracle/instantclient` \ + `#--with-oci8=shared,instantclient,/opt/oracle/instantclient` \ + --with-config-file-path=/etc \ + --with-config-file-scan-dir=/etc/php.d \ + --with-pdo-firebird \ + `#--with-pdo-dblib` \ + --disable-phpdbg \ + `#--enable-werror` + - run: + name: make + command: make -j2 > /dev/null + - run: + name: make install + command: | + sudo make install + sudo mkdir -p /etc/php.d + sudo chmod 777 /etc/php.d + echo opcache.enable_cli=1 > /etc/php.d/opcache.ini + echo opcache.protect_memory=1 >> /etc/php.d/opcache.ini + - run: + name: Test + command: | + sapi/cli/php run-tests.php \ + -d zend_extension=opcache.so \ + -d opcache.enable_cli=1 \ + -d opcache.jit_buffer_size=16M \ + -d opcache.jit=tracing \ + -P -q -x -j2 \ + -g FAIL,BORK,LEAK,XLEAK \ + --offline \ + --show-diff \ + --show-slow 1000 \ + --set-timeout 120 \ + --repeat 2 + +workflows: + push-workflow: + jobs: + - arm diff --git a/.cirrus.yml b/.cirrus.yml index 9ef70fb59191c..dc66631d98072 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -27,203 +27,3 @@ freebsd_task: - export SKIP_IO_CAPTURE_TESTS=1 - export CI_NO_IPV6=1 - sapi/cli/php run-tests.php -P -q -j2 -g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP --offline --show-diff --show-slow 1000 --set-timeout 120 -d zend_extension=opcache.so - -arm_task: - name: ARM_DEBUG_NTS - only_if: $CIRRUS_CRON == 'nightly' || $CIRRUS_CHANGE_TITLE =~ '.*\[ci arm\].*' - arm_container: - image: debian:11 - additional_containers: - - name: mysql - image: mysql:8 - port: 3306 - cpu: 1.0 - memory: 1G - env: - MYSQL_ALLOW_EMPTY_PASSWORD: true - MYSQL_ROOT_PASSWORD: "" - MYSQL_DATABASE: "test" - - name: postgres - image: postgres:latest - port: 5432 - env: - POSTGRES_PASSWORD: "postgres" - POSTGRES_DB: "test" - install_script: - - export DEBIAN_FRONTEND=noninteractive - - apt-get update -y - - >- - apt-get install -y - gcc - g++ - autoconf - bison - re2c - locales - locales-all - ldap-utils - openssl - slapd - libgmp-dev - libicu-dev - libtidy-dev - libenchant-2-dev - libaspell-dev - libpspell-dev - libsasl2-dev - libxpm-dev - libzip-dev - libbz2-dev - libsqlite3-dev - libwebp-dev - libonig-dev - libkrb5-dev - libgssapi-krb5-2 - libcurl4-openssl-dev - libxml2-dev - libxslt1-dev - libpq-dev - libreadline-dev - libldap2-dev - libsodium-dev - libargon2-0-dev - libmm-dev - libsnmp-dev - snmpd - `#snmp-mibs-downloader` - freetds-dev - `#unixodbc-dev` - libc-client-dev - dovecot-core - dovecot-pop3d - dovecot-imapd - sendmail - firebird-dev - liblmdb-dev - libtokyocabinet-dev - libdb-dev - libqdbm-dev - libjpeg-dev - libpng-dev - libfreetype6-dev - build_script: - - ./buildconf -f - - >- - ./configure - --enable-debug - --enable-zts - --enable-option-checking=fatal - --prefix=/usr - --enable-phpdbg - --enable-fpm - --enable-opcache - --with-pdo-mysql=mysqlnd - --with-mysqli=mysqlnd - --with-pgsql - --with-pdo-pgsql - --with-pdo-sqlite - --enable-intl - --without-pear - --enable-gd - --with-jpeg - --with-webp - --with-freetype - --with-xpm - --enable-exif - --with-zip - --with-zlib - --with-zlib-dir=/usr - --enable-soap - --enable-xmlreader - --with-xsl - --with-tidy - --enable-sysvsem - --enable-sysvshm - --enable-shmop - --enable-pcntl - --with-readline - --enable-mbstring - --with-curl - --with-gettext - --enable-sockets - --with-bz2 - --with-openssl - --with-gmp - --enable-bcmath - --enable-calendar - --enable-ftp - --with-pspell=/usr - --with-enchant=/usr - --with-kerberos - --enable-sysvmsg - --with-ffi - --enable-zend-test - --enable-dl-test=shared - --with-ldap - --with-ldap-sasl - --with-password-argon2 - --with-mhash - --with-sodium - --enable-dba - --with-cdb - --enable-flatfile - --enable-inifile - --with-tcadb - --with-lmdb - --with-qdbm - --with-snmp - `#--with-unixODBC` - --with-imap - --with-kerberos - --with-imap-ssl - `#--with-pdo-odbc=unixODBC,/usr` - `#--with-pdo-oci=shared,instantclient,/opt/oracle/instantclient` - `#--with-oci8=shared,instantclient,/opt/oracle/instantclient` - --with-config-file-path=/etc - --with-config-file-scan-dir=/etc/php.d - --with-pdo-firebird - `#--with-pdo-dblib` - --disable-phpdbg - `#--enable-werror` - - make -j2 > /dev/null - - make install - - mkdir -p /etc/php.d - - echo opcache.enable_cli=1 > /etc/php.d/opcache.ini - - echo opcache.protect_memory=1 >> /etc/php.d/opcache.ini - # Specify opcache.preload_user as we're running as root. - - echo opcache.preload_user=root >> /etc/php.d/opcache.ini - tests_script: - - export SKIP_IO_CAPTURE_TESTS=1 - - export CI_NO_IPV6=1 - - export MYSQL_TEST_HOST=127.0.0.1 - - export MYSQL_TEST_USER=root - - export MYSQL_TEST_PASSWD= - - export PDO_MYSQL_TEST_DSN="mysql:host=127.0.0.1;dbname=test" - - export PDO_MYSQL_TEST_USER=root - - export PDO_MYSQL_TEST_PASS= - - export PDO_PGSQL_TEST_DSN="pgsql:host=127.0.0.1 port=5432 dbname=test user=postgres password=postgres" - - >- - sapi/cli/php run-tests.php - -d zend_extension=opcache.so - -d opcache.enable_cli=1 - -d opcache.jit_buffer_size=16M - -d opcache.jit=function - -P -q -x -j2 - -g FAIL,BORK,LEAK,XLEAK - --offline - --show-diff - --show-slow 1000 - --set-timeout 120 - - >- - sapi/cli/php run-tests.php - -d zend_extension=opcache.so - -d opcache.enable_cli=1 - -d opcache.jit_buffer_size=16M - -d opcache.jit=tracing - -P -q -x -j2 - -g FAIL,BORK,LEAK,XLEAK - --offline - --show-diff - --show-slow 1000 - --set-timeout 120 - --repeat 2 diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 37bdccd884a90..3cd2fbad0f73e 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -12,6 +12,7 @@ on: - .cirrus.yml - .travis.yml - travis/* + - .circleci/* branches: - PHP-7.4 - PHP-8.0 @@ -29,6 +30,7 @@ on: - .cirrus.yml - .travis.yml - travis/* + - .circleci/* branches: - '**' concurrency: diff --git a/ext/pdo_mysql/tests/pdo_mysql___construct.phpt b/ext/pdo_mysql/tests/pdo_mysql___construct.phpt index 1f009185267c5..aa52764dea2c7 100644 --- a/ext/pdo_mysql/tests/pdo_mysql___construct.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql___construct.phpt @@ -6,7 +6,7 @@ pdo_mysql --FILE-- --FILE-- Date: Thu, 12 Oct 2023 14:04:13 +0200 Subject: [PATCH 10/66] CircleCI: Increase no_output_timeout to 30m --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9280c26beb84e..332751fb53bd0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -177,6 +177,7 @@ jobs: echo opcache.protect_memory=1 >> /etc/php.d/opcache.ini - run: name: Test + no_output_timeout: 30m command: | sapi/cli/php run-tests.php \ -d zend_extension=opcache.so \ From 734afa0ba8169b74a85326575323f0afbd1cf7ef Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 13 Oct 2023 11:41:52 +0200 Subject: [PATCH 11/66] Fix JIT on nightly The JIT was accidentally disabled in nightly on lower branches because jit_buffer_size woudln't be passed from nightly.yml on master anymore. --- .github/actions/test-linux/action.yml | 1 + .github/actions/test-macos/action.yml | 1 + .github/workflows/nightly.yml | 6 ------ .github/workflows/push.yml | 2 -- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/actions/test-linux/action.yml b/.github/actions/test-linux/action.yml index 7d66d2235208d..1dfba39478740 100644 --- a/.github/actions/test-linux/action.yml +++ b/.github/actions/test-linux/action.yml @@ -31,6 +31,7 @@ runs: export SKIP_IO_CAPTURE_TESTS=1 sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \ -d opcache.jit=${{ inputs.jitType }} \ + -d opcache.jit_buffer_size=16M \ -j$(/usr/bin/nproc) \ -g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP \ --offline \ diff --git a/.github/actions/test-macos/action.yml b/.github/actions/test-macos/action.yml index 6036ce1e5a9b6..3bf0fdb7097af 100644 --- a/.github/actions/test-macos/action.yml +++ b/.github/actions/test-macos/action.yml @@ -16,6 +16,7 @@ runs: export CI_NO_IPV6=1 sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \ -d opcache.jit=${{ inputs.jitType }} \ + -d opcache.jit_buffer_size=16M \ -j$(sysctl -n hw.ncpu) \ -g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP \ --offline \ diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 7283f10672da3..ae6877c40228a 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -89,7 +89,6 @@ jobs: ${{ matrix.run_tests_parameters }} -d zend_extension=opcache.so -d opcache.enable_cli=1 - -d opcache.jit_buffer_size=16M - name: Test OpCache uses: ./.github/actions/test-linux with: @@ -108,7 +107,6 @@ jobs: ${{ matrix.run_tests_parameters }} -d zend_extension=opcache.so -d opcache.enable_cli=1 - -d opcache.jit_buffer_size=16M - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files - name: Notify Slack @@ -171,7 +169,6 @@ jobs: ${{ matrix.run_tests_parameters }} -d zend_extension=opcache.so -d opcache.enable_cli=1 - -d opcache.jit_buffer_size=16M - name: Test OpCache uses: ./.github/actions/test-linux with: @@ -187,7 +184,6 @@ jobs: ${{ matrix.run_tests_parameters }} -d zend_extension=opcache.so -d opcache.enable_cli=1 - -d opcache.jit_buffer_size=16M - name: Notify Slack if: failure() uses: ./.github/actions/notify-slack @@ -233,7 +229,6 @@ jobs: -d zend_extension=opcache.so -d opcache.enable_cli=1 -d opcache.protect_memory=1 - -d opcache.jit_buffer_size=16M - name: Test OpCache uses: ./.github/actions/test-macos with: @@ -249,7 +244,6 @@ jobs: -d zend_extension=opcache.so -d opcache.enable_cli=1 -d opcache.protect_memory=1 - -d opcache.jit_buffer_size=16M - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files - name: Notify Slack diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 3cd2fbad0f73e..52f70f809e9ce 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -91,7 +91,6 @@ jobs: runTestsParameters: >- -d zend_extension=opcache.so -d opcache.enable_cli=1 - -d opcache.jit_buffer_size=16M - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files MACOS_DEBUG_NTS: @@ -124,7 +123,6 @@ jobs: -d zend_extension=opcache.so -d opcache.enable_cli=1 -d opcache.protect_memory=1 - -d opcache.jit_buffer_size=16M - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files WINDOWS: From d7de0ceca6f8af6d4daaf627d5b48ef50dd091c6 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 11 Oct 2023 20:51:52 +0200 Subject: [PATCH 12/66] Fix registerNodeClass with abstract class crashing This always results in a segfault when trying to instantiate, so this never worked. At least throw an error instead of segfaulting to prevent developers from being confused. Closes GH-12420. --- NEWS | 3 +++ ext/dom/document.c | 4 ++++ .../registerNodeClass_abstract_class.phpt | 24 +++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 ext/dom/tests/registerNodeClass_abstract_class.phpt diff --git a/NEWS b/NEWS index 0ba555c819b54..4c8dbb38b19d9 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.1.26 +- DOM: + . Fix registerNodeClass with abstract class crashing. (nielsdos) + - Fiber: . Fixed bug GH-11121 (ReflectionFiber segfault). (danog, trowski, bwoebi) diff --git a/ext/dom/document.c b/ext/dom/document.c index 64da4f051be2c..38bb4553a11a1 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -2096,6 +2096,10 @@ PHP_METHOD(DOMDocument, registerNodeClass) } if (ce == NULL || instanceof_function(ce, basece)) { + if (UNEXPECTED(ce != NULL && (ce->ce_flags & ZEND_ACC_ABSTRACT))) { + zend_argument_value_error(2, "must not be an abstract class"); + RETURN_THROWS(); + } DOM_GET_OBJ(docp, id, xmlDocPtr, intern); dom_set_doc_classmap(intern->document, basece, ce); RETURN_TRUE; diff --git a/ext/dom/tests/registerNodeClass_abstract_class.phpt b/ext/dom/tests/registerNodeClass_abstract_class.phpt new file mode 100644 index 0000000000000..24124d712ea09 --- /dev/null +++ b/ext/dom/tests/registerNodeClass_abstract_class.phpt @@ -0,0 +1,24 @@ +--TEST-- +registerNodeClass() with an abstract class should fail +--EXTENSIONS-- +dom +--FILE-- +registerNodeClass("DOMElement", "Test"); +} catch (ValueError $e) { + echo "ValueError: ", $e->getMessage(), "\n"; +} + +$dom->createElement("foo"); + +?> +--EXPECT-- +ValueError: DOMDocument::registerNodeClass(): Argument #2 ($extendedClass) must not be an abstract class From 0217be4d5b5e9db768fd1b9edc6029645c81257c Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 22 Sep 2023 22:02:19 +0100 Subject: [PATCH 13/66] Fix GH-12232: FPM: segfault dynamically loading extension without opcache Also fixes incorrect assertion in ini init that php_dl is always temporary. Closes GH-12277 --- NEWS | 4 ++ Zend/zend_ini.c | 1 - sapi/fpm/fpm/fpm_php.c | 2 + .../tests/gh12232-php-value-extension.phpt | 51 +++++++++++++++++++ sapi/fpm/tests/tester.inc | 11 ++++ 5 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 sapi/fpm/tests/gh12232-php-value-extension.phpt diff --git a/NEWS b/NEWS index 4c8dbb38b19d9..395cc3129f9a1 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,10 @@ PHP NEWS - Fiber: . Fixed bug GH-11121 (ReflectionFiber segfault). (danog, trowski, bwoebi) +- FPM: + . Fixed bug GH-12232 (FPM: segfault dynamically loading extension without + opcache). (Jakub Zelenka) + - Opcache: . Added warning when JIT cannot be enabled. (danog) . Fixed bug GH-8143 (Crashes in zend_accel_inheritance_cache_find since diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c index 1b4710eb503a0..866e1b9c2097c 100644 --- a/Zend/zend_ini.c +++ b/Zend/zend_ini.c @@ -211,7 +211,6 @@ ZEND_API zend_result zend_register_ini_entries_ex(const zend_ini_entry_def *ini_ * lead to death. */ if (directives != EG(ini_directives)) { - ZEND_ASSERT(module_type == MODULE_TEMPORARY); directives = EG(ini_directives); } else { ZEND_ASSERT(module_type == MODULE_PERSISTENT); diff --git a/sapi/fpm/fpm/fpm_php.c b/sapi/fpm/fpm/fpm_php.c index 92b189668206e..a9ad0433ba4dd 100644 --- a/sapi/fpm/fpm/fpm_php.c +++ b/sapi/fpm/fpm/fpm_php.c @@ -87,7 +87,9 @@ int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode) /* {{{ */ if (!strcmp(name, "extension") && *value) { zval zv; + zend_interned_strings_switch_storage(0); php_dl(value, MODULE_PERSISTENT, &zv, 1); + zend_interned_strings_switch_storage(1); return Z_TYPE(zv) == IS_TRUE; } diff --git a/sapi/fpm/tests/gh12232-php-value-extension.phpt b/sapi/fpm/tests/gh12232-php-value-extension.phpt new file mode 100644 index 0000000000000..207bd7a677974 --- /dev/null +++ b/sapi/fpm/tests/gh12232-php-value-extension.phpt @@ -0,0 +1,51 @@ +--TEST-- +FPM: gh12232 - loading shared ext in FPM config +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$tester->request()->expectBody(['bool(true)', 'string(5) "hello"', 'string(4) "test"']); +$tester->request()->expectBody(['bool(true)', 'string(5) "hello"', 'string(4) "test"']); +$tester->terminate(); +$tester->expectLogTerminatingNotices(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + + Date: Sun, 15 Oct 2023 00:13:57 +0200 Subject: [PATCH 14/66] Add missing module dependency for xsl This module cannot work without the DOM extension. Closes GH-12441. --- NEWS | 3 +++ ext/xsl/php_xsl.c | 1 + 2 files changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 395cc3129f9a1..d697dae5ee6de 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,9 @@ PHP NEWS . Fixed bug GH-12392 (Segmentation fault on SoapClient::__getTypes). (nielsdos) +- XSL: + . Add missing module dependency. (nielsdos) + 26 Oct 2023, PHP 8.1.25 - Core: diff --git a/ext/xsl/php_xsl.c b/ext/xsl/php_xsl.c index 1e98a6ce88bbe..6330ea5906535 100644 --- a/ext/xsl/php_xsl.c +++ b/ext/xsl/php_xsl.c @@ -29,6 +29,7 @@ static zend_object_handlers xsl_object_handlers; static const zend_module_dep xsl_deps[] = { ZEND_MOD_REQUIRED("libxml") + ZEND_MOD_REQUIRED("dom") ZEND_MOD_END }; From dabced0fbb9a2f2bee6536f376dc31a210a6be58 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 16 Oct 2023 15:11:56 +0300 Subject: [PATCH 15/66] Fixed GH-12428: Assertion with function/tracing JIT --- ext/opcache/jit/zend_jit_helpers.c | 2 +- ext/opcache/tests/jit/gh12428.phpt | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/jit/gh12428.phpt diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 447e2269aa3d0..fc52986ea197e 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1938,7 +1938,7 @@ static void ZEND_FASTCALL zend_jit_fetch_obj_is_dynamic(zend_object *zobj, intpt if (EXPECTED(retval)) { intptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - ZVAL_COPY(result, retval); + ZVAL_COPY_DEREF(result, retval); return; } } diff --git a/ext/opcache/tests/jit/gh12428.phpt b/ext/opcache/tests/jit/gh12428.phpt new file mode 100644 index 0000000000000..48c6a30fc1b88 --- /dev/null +++ b/ext/opcache/tests/jit/gh12428.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-12428: Assertion with function/tracing JIT +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- +a; + $value->a ?? null; + } +} + +validate((object) []); +validate((object) []); +validate((object) ['b' => 0]); +?> +DONE +--EXPECT-- +DONE From 89eb1c64a9a690bb80685c85dc5d0e8947eaa461 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 17 Oct 2023 01:58:07 +0300 Subject: [PATCH 16/66] Fixed GH-11917: primitives seem to be passed via reference instead of by value under some conditions when JIT is enabled on windows (#12451) --- ext/opcache/jit/zend_jit_x86.dasc | 2 +- ext/opcache/tests/jit/gh11917.phpt | 61 ++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/jit/gh11917.phpt diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index dcb32d92b5e8b..e1bd5bfdbdfea 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -5157,7 +5157,7 @@ static int zend_jit_long_math_helper(dasm_State **Dst, result_reg = ZREG_R0; } else { /* ASSIGN_DIM_OP */ - if (sizeof(void*) == 4 + if (ZREG_FCARG1 == ZREG_RCX && (opcode == ZEND_SL || opcode == ZEND_SR) && Z_MODE(op2_addr) != IS_CONST_ZVAL) { result_reg = ZREG_R2; diff --git a/ext/opcache/tests/jit/gh11917.phpt b/ext/opcache/tests/jit/gh11917.phpt new file mode 100644 index 0000000000000..a66105d7a8f7a --- /dev/null +++ b/ext/opcache/tests/jit/gh11917.phpt @@ -0,0 +1,61 @@ +--TEST-- +GH-11917: primitives seem to be passed via reference instead of by value under some conditions when JIT is enabled on windows +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- +>= $split; + if (!$overflow) { + $remaining -= $split; + $overflow = $split <= $remaining ? 0 : $split - $remaining; + + if (!$remaining) { + $i++; + $remaining = 31; + $overflow = 0; + } + } elseif (++$i != $len) { + $tempmask = (1 << $overflow) - 1; + $digit |= ($val[$i] & $tempmask) << $remaining; + $val[$i] >>= $overflow; + $remaining = 31 - $overflow; + $overflow = $split <= $remaining ? 0 : $split - $remaining; + } + + $vals[] = $digit; + } + + while ($vals[count($vals) - 1] == 0) { + unset($vals[count($vals) - 1]); + } + + return array_reverse($vals); +} +?> +--EXPECT-- +48207660 +48207660 +48207660 +48207660 From 07d81592e944dd35eec12be362ae86bac12549e1 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 17 Oct 2023 18:09:44 +0200 Subject: [PATCH 17/66] Avoid JIT warning with opcache.jit_buffer_size=0 Closes GH-12460 --- ext/opcache/ZendAccelerator.c | 6 +++++- .../tests/jit_warning_with_zero_buffer.phpt | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/jit_warning_with_zero_buffer.phpt diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 93afd8e415dc5..530620f6259ff 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -3270,7 +3270,11 @@ static zend_result accel_post_startup(void) || zend_jit_startup(ZSMMG(reserved), jit_size, reattached) != SUCCESS) { JIT_G(enabled) = 0; JIT_G(on) = 0; - zend_accel_error(ACCEL_LOG_WARNING, "Could not enable JIT!"); + /* The JIT is implicitly disabled with opcache.jit_buffer_size=0, so we don't want to + * emit a warning here. */ + if (JIT_G(buffer_size) != 0) { + zend_accel_error(ACCEL_LOG_WARNING, "Could not enable JIT!"); + } } } #endif diff --git a/ext/opcache/tests/jit_warning_with_zero_buffer.phpt b/ext/opcache/tests/jit_warning_with_zero_buffer.phpt new file mode 100644 index 0000000000000..1b791e2f1ae8a --- /dev/null +++ b/ext/opcache/tests/jit_warning_with_zero_buffer.phpt @@ -0,0 +1,16 @@ +--TEST-- +JIT should not emit warning with opcache.jit_buffer_size=0 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit=tracing +opcache.jit_buffer_size=0 +opcache.log_verbosity_level=2 +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECT-- +bool(false) From e3a6dc123da68fd8443df4ff6b9ba47997d2d39b Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 18 Oct 2023 15:37:12 +0200 Subject: [PATCH 18/66] [skip ci] Set travis_wait timeout to 60m This was already done for master, but for some reason not for lower branches. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1c64ac74cb993..6c51e13a0fab5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -85,7 +85,7 @@ before_script: # Run PHPs run-tests.php script: - - travis_wait ./travis/test.sh -d opcache.jit_buffer_size=16M -d opcache.jit=tracing + - travis_wait 60 ./travis/test.sh -d opcache.jit_buffer_size=16M -d opcache.jit=tracing - sapi/cli/php -d extension_dir=`pwd`/modules -r 'dl("zend_test");' after_success: From 736032febfac6eb30db7d463d6ad1d124cb28417 Mon Sep 17 00:00:00 2001 From: SakiTakamachi Date: Tue, 17 Oct 2023 22:23:31 +0900 Subject: [PATCH 19/66] Fixed a bug in zend_memnistr with single character needle Fixes GH-12457 Closes GH-12458 --- NEWS | 2 ++ Zend/tests/gh12457.phpt | 33 +++++++++++++++++++++++++++++++++ Zend/zend_operators.h | 2 +- 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/gh12457.phpt diff --git a/NEWS b/NEWS index 87812c65bdd33..40206e4ee7c92 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,8 @@ PHP NEWS - Core: . Fixed double-free of non-interned enum case name. (ilutov) + . Fixed bug GH-12457 (Incorrect result of stripos with single character + needle). (SakiTakamachi) - DOM: . Fix registerNodeClass with abstract class crashing. (nielsdos) diff --git a/Zend/tests/gh12457.phpt b/Zend/tests/gh12457.phpt new file mode 100644 index 0000000000000..da9165f4befc3 --- /dev/null +++ b/Zend/tests/gh12457.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-12458 (Fix GH-12457: Fixed a bug in zend_memnistr) +--FILE-- + +--EXPECTF-- +Test case to ensure the issue is fixed. +int(2) +int(2) +int(2) +string(6) "BBBBBb" +string(7) "BBBBBbb" +string(8) "BBBBBbbb" + +Test cases to ensure the original functionality is not broken. +int(8) +int(8) +string(1) "c" +string(1) "C" diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 0fc503f2c12b4..e98956239ec3b 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -945,7 +945,7 @@ zend_memnistr(const char *haystack, const char *needle, size_t needle_len, const const char *p_upper = NULL; if (first_lower != first_upper) { // If the needle length is 1 we don't need to look beyond p_lower as it is a guaranteed match - size_t upper_search_length = end - (needle_len == 1 && p_lower != NULL ? p_lower : haystack); + size_t upper_search_length = needle_len == 1 && p_lower != NULL ? p_lower - haystack : end - haystack; p_upper = (const char *)memchr(haystack, first_upper, upper_search_length); } const char *p = !p_upper || (p_lower && p_lower < p_upper) ? p_lower : p_upper; From af3d2f7ec98d3ef59800bde01183a75182944052 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 19 Oct 2023 00:47:59 +0200 Subject: [PATCH 20/66] Fix double-free of doc_comment when overriding static property via trait When redeclaring an overridden static property with a trait we're removing the property from the class. However, because the property itself does not belong to the class we must not free its associated data. This issue is exposed by 9a250cc9d6 in PHP 8.3+ because duplicate static properties in traits are no longer skipped, but redeclared. Fixes GH-12468 --- NEWS | 4 ++++ Zend/tests/gh12468_1.phpt | 18 ++++++++++++++++++ Zend/tests/gh12468_2.phpt | 19 +++++++++++++++++++ Zend/zend_API.c | 4 ++-- 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/gh12468_1.phpt create mode 100644 Zend/tests/gh12468_2.phpt diff --git a/NEWS b/NEWS index d697dae5ee6de..521972251c268 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.1.26 +- Core: + . Fixed bug GH-12468 (Double-free of doc_comment when overriding static + property via trait). (ilutov) + - DOM: . Fix registerNodeClass with abstract class crashing. (nielsdos) diff --git a/Zend/tests/gh12468_1.phpt b/Zend/tests/gh12468_1.phpt new file mode 100644 index 0000000000000..a02a28c3e354c --- /dev/null +++ b/Zend/tests/gh12468_1.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-12468: Double-free of doc_comment when overriding static property via trait +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/gh12468_2.phpt b/Zend/tests/gh12468_2.phpt new file mode 100644 index 0000000000000..3097cf532e22c --- /dev/null +++ b/Zend/tests/gh12468_2.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-12468: Double-free of doc_comment when overriding static property via trait +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 1178133046679..5e89c91828683 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -4120,7 +4120,7 @@ ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, z (property_info_ptr->flags & ZEND_ACC_STATIC) != 0) { property_info->offset = property_info_ptr->offset; zval_ptr_dtor(&ce->default_static_members_table[property_info->offset]); - if (property_info_ptr->doc_comment) { + if (property_info_ptr->doc_comment && property_info_ptr->ce == ce) { zend_string_release(property_info_ptr->doc_comment); } zend_hash_del(&ce->properties_info, name); @@ -4145,7 +4145,7 @@ ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, z (property_info_ptr->flags & ZEND_ACC_STATIC) == 0) { property_info->offset = property_info_ptr->offset; zval_ptr_dtor(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]); - if (property_info_ptr->doc_comment) { + if (property_info_ptr->doc_comment && property_info_ptr->ce == ce) { zend_string_release_ex(property_info_ptr->doc_comment, 1); } zend_hash_del(&ce->properties_info, name); From 43e63168e920af5ba504c6b8e98678b9dc6a991e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 18 Oct 2023 22:20:50 +0200 Subject: [PATCH 21/66] Fix bug #66150: SOAP WSDL cache race condition causes Segmentation Fault When we have two processes both trying to cache a WSDL, they might start writing the data to the same temporary file, causing file corruption due to the race condition. Fix this by creating a temporary file first, and then moving it to the final location. If moving fails then we know another process finished caching first. This also fixes #67617 as a consequence of its implementation. Closes GH-12469. --- NEWS | 3 +++ ext/soap/php_sdl.c | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 521972251c268..90570d34231a1 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,9 @@ PHP NEWS - SOAP: . Fixed bug GH-12392 (Segmentation fault on SoapClient::__getTypes). (nielsdos) + . Fixed bug #66150 (SOAP WSDL cache race condition causes Segmentation + Fault). (nielsdos) + . Fixed bug #67617 (SOAP leaves incomplete cache file on ENOSPC). (nielsdos) - XSL: . Add missing module dependency. (nielsdos) diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index 3dd8e6c5d76e4..1848d5ecda35b 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -22,6 +22,7 @@ #include "ext/standard/md5.h" #include "zend_virtual_cwd.h" +#include "main/php_open_temporary_file.h" #include #include @@ -2119,7 +2120,10 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s HashTable tmp_bindings; HashTable tmp_functions; - f = open(fn,O_CREAT|O_WRONLY|O_EXCL|O_BINARY,S_IREAD|S_IWRITE); + /* To avoid race conditions, we first create a temporary file and then rename it atomically + * at the end of the function. (see bug #66150) */ + zend_string *temp_file_path; + f = php_open_temporary_fd_ex(SOAP_GLOBAL(cache_dir), "tmp.wsdl.", &temp_file_path, PHP_TMP_FILE_SILENT); if (f < 0) {return;} @@ -2371,13 +2375,21 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s } ZEND_HASH_FOREACH_END(); } - php_ignore_value(write(f, ZSTR_VAL(buf.s), ZSTR_LEN(buf.s))); + bool valid_file = write(f, ZSTR_VAL(buf.s), ZSTR_LEN(buf.s)) == ZSTR_LEN(buf.s); close(f); + + /* Make sure that incomplete files (e.g. due to disk space issues, see bug #66150) are not utilised. */ + if (valid_file) { + /* This is allowed to fail, this means that another process was raced to create the file. */ + (void) VCWD_RENAME(ZSTR_VAL(temp_file_path), fn); + } + smart_str_free(&buf); zend_hash_destroy(&tmp_functions); zend_hash_destroy(&tmp_bindings); zend_hash_destroy(&tmp_encoders); zend_hash_destroy(&tmp_types); + zend_string_release_ex(temp_file_path, false); } From abf562c4172ec3c52b07006474e1cd536e6b6e50 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 19 Oct 2023 16:41:29 +0200 Subject: [PATCH 22/66] Fix incorrect uri check in SOAP caching If i == 0 then the check will compare 0 bytes. We are supposed to check if the uri is identical. Closes GH-12479. --- NEWS | 1 + ext/soap/php_sdl.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 90570d34231a1..defce40d78619 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,7 @@ PHP NEWS . Fixed bug #66150 (SOAP WSDL cache race condition causes Segmentation Fault). (nielsdos) . Fixed bug #67617 (SOAP leaves incomplete cache file on ENOSPC). (nielsdos) + . Fix incorrect uri check in SOAP caching. (nielsdos) - XSL: . Add missing module dependency. (nielsdos) diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index 1848d5ecda35b..e7ea112317830 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -1537,7 +1537,7 @@ static HashTable* sdl_deserialize_parameters(encodePtr *encoders, sdlTypePtr *ty return ht; } -static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t, time_t *cached) +static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, size_t uri_len, time_t t, time_t *cached) { sdlPtr sdl; time_t old_t; @@ -1584,7 +1584,7 @@ static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t, time *cached = old_t; WSDL_CACHE_GET_INT(i, &in); - if (i == 0 && strncmp(in, uri, i) != 0) { + if (i != uri_len || strncmp(in, uri, i) != 0) { unlink(fn); efree(buf); return NULL; @@ -3244,7 +3244,7 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, zend_long cache_wsdl) } memcpy(key+len,md5str,sizeof(md5str)); - if ((sdl = get_sdl_from_cache(key, uri, t-SOAP_GLOBAL(cache_ttl), &cached)) != NULL) { + if ((sdl = get_sdl_from_cache(key, uri, uri_len, t-SOAP_GLOBAL(cache_ttl), &cached)) != NULL) { t = cached; efree(key); goto cache_in_memory; From deebb68612dc3c606845346993d938e09050be2d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 19 Oct 2023 15:07:20 +0200 Subject: [PATCH 23/66] Fix segfault and assertion failure with refcounted props and arrays Closes GH-12478. --- ext/soap/php_encoding.c | 4 +- .../tests/bugs/segfault_assertion_props.phpt | 51 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 ext/soap/tests/bugs/segfault_assertion_props.phpt diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 3a4626aa5beee..a5fbd3df9dd9c 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -1561,10 +1561,12 @@ static zval *to_zval_object_ex(zval *ret, encodeTypePtr type, xmlNodePtr data, z if (Z_TYPE_P(prop) != IS_ARRAY) { /* Convert into array */ array_init(&arr); - Z_ADDREF_P(prop); + Z_TRY_ADDREF_P(prop); add_next_index_zval(&arr, prop); set_zval_property(ret, (char*)trav->name, &arr); prop = &arr; + } else { + SEPARATE_ARRAY(prop); } /* Add array element */ add_next_index_zval(prop, &tmpVal); diff --git a/ext/soap/tests/bugs/segfault_assertion_props.phpt b/ext/soap/tests/bugs/segfault_assertion_props.phpt new file mode 100644 index 0000000000000..9d496d72967b0 --- /dev/null +++ b/ext/soap/tests/bugs/segfault_assertion_props.phpt @@ -0,0 +1,51 @@ +--TEST-- +Segfault and assertion failure with refcounted props and arrays +--INI-- +soap.wsdl_cache_enabled=0 +--EXTENSIONS-- +soap +--FILE-- + + + + Hello + World + + +EOF; + } +} + +trait A { + public $a = [self::class . 'a']; + public $b = self::class . 'b'; +} + +class DummyClass { + use A; +} + +$client = new TestSoapClient(__DIR__."/../classmap.wsdl", ['classmap' => ['Struct' => 'DummyClass']]); +var_dump($client->dotest2("???")); +?> +--EXPECT-- +object(DummyClass)#2 (2) { + ["a"]=> + array(2) { + [0]=> + string(11) "DummyClassa" + [1]=> + string(5) "Hello" + } + ["b"]=> + array(2) { + [0]=> + string(11) "DummyClassb" + [1]=> + string(5) "World" + } +} From 01d61605d3a354019a11f977488d6441cd636e01 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 19 Oct 2023 15:07:20 +0200 Subject: [PATCH 24/66] Fix segfault and assertion failure with refcounted props and arrays Closes GH-12478. --- NEWS | 2 + ext/soap/php_encoding.c | 4 +- .../tests/bugs/segfault_assertion_props.phpt | 51 +++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 ext/soap/tests/bugs/segfault_assertion_props.phpt diff --git a/NEWS b/NEWS index defce40d78619..6f21f2f796723 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,8 @@ PHP NEWS Fault). (nielsdos) . Fixed bug #67617 (SOAP leaves incomplete cache file on ENOSPC). (nielsdos) . Fix incorrect uri check in SOAP caching. (nielsdos) + . Fix segfault and assertion failure with refcounted props and arrays. + (nielsdos) - XSL: . Add missing module dependency. (nielsdos) diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 3a4626aa5beee..a5fbd3df9dd9c 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -1561,10 +1561,12 @@ static zval *to_zval_object_ex(zval *ret, encodeTypePtr type, xmlNodePtr data, z if (Z_TYPE_P(prop) != IS_ARRAY) { /* Convert into array */ array_init(&arr); - Z_ADDREF_P(prop); + Z_TRY_ADDREF_P(prop); add_next_index_zval(&arr, prop); set_zval_property(ret, (char*)trav->name, &arr); prop = &arr; + } else { + SEPARATE_ARRAY(prop); } /* Add array element */ add_next_index_zval(prop, &tmpVal); diff --git a/ext/soap/tests/bugs/segfault_assertion_props.phpt b/ext/soap/tests/bugs/segfault_assertion_props.phpt new file mode 100644 index 0000000000000..9d496d72967b0 --- /dev/null +++ b/ext/soap/tests/bugs/segfault_assertion_props.phpt @@ -0,0 +1,51 @@ +--TEST-- +Segfault and assertion failure with refcounted props and arrays +--INI-- +soap.wsdl_cache_enabled=0 +--EXTENSIONS-- +soap +--FILE-- + + + + Hello + World + + +EOF; + } +} + +trait A { + public $a = [self::class . 'a']; + public $b = self::class . 'b'; +} + +class DummyClass { + use A; +} + +$client = new TestSoapClient(__DIR__."/../classmap.wsdl", ['classmap' => ['Struct' => 'DummyClass']]); +var_dump($client->dotest2("???")); +?> +--EXPECT-- +object(DummyClass)#2 (2) { + ["a"]=> + array(2) { + [0]=> + string(11) "DummyClassa" + [1]=> + string(5) "Hello" + } + ["b"]=> + array(2) { + [0]=> + string(11) "DummyClassb" + [1]=> + string(5) "World" + } +} From 83a242ec0cb8a6633f51b82845978e1eb9bdb883 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sat, 21 Oct 2023 15:16:32 +0100 Subject: [PATCH 25/66] Fix GH-12489: Missing sigbio creation checking in openssl_cms_verify Closes GH-12490 --- NEWS | 4 ++++ ext/openssl/openssl.c | 5 ++++- ext/openssl/tests/gh12489.phpt | 36 ++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 ext/openssl/tests/gh12489.phpt diff --git a/NEWS b/NEWS index 6f21f2f796723..3155cda7ad9f8 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,10 @@ PHP NEWS . Fixed bug GH-8143 (Crashes in zend_accel_inheritance_cache_find since upgrading to 8.1.3 due to corrupt on-disk file cache). (turchanov) +- OpenSSL: + Fixed bug GH-12489 (Missing sigbio creation checking in openssl_cms_verify). + (Jakub Zelenka) + - SOAP: . Fixed bug GH-12392 (Segmentation fault on SoapClient::__getTypes). (nielsdos) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 10af453c89519..31baa2d0e0250 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -5900,12 +5900,15 @@ PHP_FUNCTION(openssl_cms_verify) goto clean_exit; } if (sigfile && (flags & CMS_DETACHED)) { - sigbio = php_openssl_bio_new_file(sigfile, sigfile_len, 1, PHP_OPENSSL_BIO_MODE_R(flags)); if (encoding == ENCODING_SMIME) { php_error_docref(NULL, E_WARNING, "Detached signatures not possible with S/MIME encoding"); goto clean_exit; } + sigbio = php_openssl_bio_new_file(sigfile, sigfile_len, 1, PHP_OPENSSL_BIO_MODE_R(flags)); + if (sigbio == NULL) { + goto clean_exit; + } } else { sigbio = in; /* non-detached signature */ } diff --git a/ext/openssl/tests/gh12489.phpt b/ext/openssl/tests/gh12489.phpt new file mode 100644 index 0000000000000..4ebeb09784db9 --- /dev/null +++ b/ext/openssl/tests/gh12489.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-12489: Missing sigbio creation checking in openssl_cms_verify +--EXTENSIONS-- +openssl +--FILE-- + "test@test", "Subject" => "testing openssl_cms_sign()"); +$headers = array("test@test", "testing openssl_cms_sign()"); + +var_dump(openssl_cms_sign($infile, $outfile, openssl_x509_read($single_cert), $privkey, $headers, + OPENSSL_CMS_DETACHED|OPENSSL_CMS_BINARY,OPENSSL_ENCODING_PEM)); +ini_set('open_basedir', __DIR__); +var_dump(openssl_cms_verify($infile,OPENSSL_CMS_NOVERIFY|OPENSSL_CMS_DETACHED|OPENSSL_CMS_BINARY, + NULL, array(), NULL, $vout, NULL, "../test.cms", OPENSSL_ENCODING_PEM)); +var_dump(openssl_error_string()); +?> +--CLEAN-- + +--EXPECTF-- +bool(true) + +Warning: openssl_cms_verify(): open_basedir restriction in effect. File(%s) is not within the allowed path(s): (%s) in %s on line %d +bool(false) +bool(false) From 52aa0d9ecc7ab8b0b74f142e7c1020caa281fbba Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sat, 23 Sep 2023 21:03:31 +0100 Subject: [PATCH 26/66] Fix bug #75708: getimagesize with "&$imageinfo" fails on StreamWrappers Closes GH-12444 --- NEWS | 4 ++ ext/standard/image.c | 16 ++++++- ext/standard/tests/image/bug75708.jpg | Bin 0 -> 34619 bytes ext/standard/tests/image/bug75708.phpt | 56 +++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/image/bug75708.jpg create mode 100644 ext/standard/tests/image/bug75708.phpt diff --git a/NEWS b/NEWS index 3155cda7ad9f8..350d1f7dc7cb1 100644 --- a/NEWS +++ b/NEWS @@ -35,6 +35,10 @@ PHP NEWS . Fix segfault and assertion failure with refcounted props and arrays. (nielsdos) +- Streams: + . Fixed bug #75708 (getimagesize with "&$imageinfo" fails on StreamWrappers). + (Jakub Zelenka) + - XSL: . Add missing module dependency. (nielsdos) diff --git a/ext/standard/image.c b/ext/standard/image.c index 85ecda2f3d70b..5200295f3af28 100644 --- a/ext/standard/image.c +++ b/ext/standard/image.c @@ -425,6 +425,20 @@ static int php_skip_variable(php_stream * stream) } /* }}} */ +static size_t php_read_stream_all_chunks(php_stream *stream, char *buffer, size_t length) +{ + size_t read_total = 0; + do { + ssize_t read_now = php_stream_read(stream, buffer, length - read_total); + read_total += read_now; + if (read_now < stream->chunk_size && read_total != length) { + return 0; + } + } while (read_total < length); + + return read_total; +} + /* {{{ php_read_APP */ static int php_read_APP(php_stream * stream, unsigned int marker, zval *info) { @@ -441,7 +455,7 @@ static int php_read_APP(php_stream * stream, unsigned int marker, zval *info) buffer = emalloc(length); - if (php_stream_read(stream, buffer, (size_t) length) != length) { + if (php_read_stream_all_chunks(stream, buffer, length) != length) { efree(buffer); return 0; } diff --git a/ext/standard/tests/image/bug75708.jpg b/ext/standard/tests/image/bug75708.jpg new file mode 100644 index 0000000000000000000000000000000000000000..26cb754fab10a47209ad1a252d2a6f7c5631c60d GIT binary patch literal 34619 zcmeHw37Dm2b>?4HUA;F{Lp2~m_^C!|vG%R2DmIY^%#a+4^ z#z-I{(ocM%(HM0mA}uDGF(x|V5@*CM(Wo=yj;IrZI%15O5SNH3)Vyc?zT1mQQ0K`r z>4NIIb??7?-#PDj&wI}I-CK)aT>P7)>)BWAydr7CS8rQyk}N*hb;gb(rI{qzx%0AQ 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 W>I4II>1<%2&0X)j{hrN>5By&wp=$X6 literal 0 HcmV?d00001 diff --git a/ext/standard/tests/image/bug75708.phpt b/ext/standard/tests/image/bug75708.phpt new file mode 100644 index 0000000000000..956a99b6af6b8 --- /dev/null +++ b/ext/standard/tests/image/bug75708.phpt @@ -0,0 +1,56 @@ +--TEST-- +Bug #75708 (getimagesize with "&$imageinfo" fails on StreamWrappers) +--FILE-- +handle = fopen(str_replace('fs://', __DIR__ . '/', $file), $mode); + return true; + } + function stream_read($count) { + return fread($this->handle, $count); + } + function stream_eof() { + return feof($this->handle); + } + function stream_seek($offset, $whence) { + return fseek($this->handle, $offset, $whence) === 0; + } + function stream_stat() { + return fstat($this->handle); + } + function url_stat($file) { + return stat(str_replace('fs://', '', $file)); + } + function stream_tell() { + return ftell($this->handle); + } + function stream_close() { + fclose($this->handle); + } +} + +stream_register_wrapper('fs', 'FSStreamWrapper'); + +var_dump(getimagesize('fs://bug75708.jpg', $info)); + +?> +--EXPECT-- +array(7) { + [0]=> + int(10) + [1]=> + int(10) + [2]=> + int(2) + [3]=> + string(22) "width="10" height="10"" + ["bits"]=> + int(8) + ["channels"]=> + int(3) + ["mime"]=> + string(10) "image/jpeg" +} + From 006032b6f0d0b773c0660e905a338cc19b00cbe6 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sun, 22 Oct 2023 15:31:00 +0100 Subject: [PATCH 27/66] Fix failing test for bug #75708 --- ext/standard/tests/image/bug75708.phpt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/standard/tests/image/bug75708.phpt b/ext/standard/tests/image/bug75708.phpt index 956a99b6af6b8..3c81c67cf5ddb 100644 --- a/ext/standard/tests/image/bug75708.phpt +++ b/ext/standard/tests/image/bug75708.phpt @@ -4,6 +4,10 @@ Bug #75708 (getimagesize with "&$imageinfo" fails on StreamWrappers) handle = fopen(str_replace('fs://', __DIR__ . '/', $file), $mode); return true; From e0ca4dca5b1c704381ac42d55cb1a16634741ec9 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 23 Oct 2023 10:50:55 +0300 Subject: [PATCH 28/66] Fixed GH-12494: Zend/tests/arginfo_zpp_mismatch.phpt causes a segfault withJIT + --repeat 2 --- ext/opcache/zend_shared_alloc.c | 2 +- ext/opcache/zend_shared_alloc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c index 37f6fea9199a7..f8644121572b5 100644 --- a/ext/opcache/zend_shared_alloc.c +++ b/ext/opcache/zend_shared_alloc.c @@ -252,7 +252,7 @@ int zend_shared_alloc_startup(size_t requested_size, size_t reserved_size) free(ZSMMG(shared_segments)); ZSMMG(shared_segments) = tmp_shared_segments; - ZSMMG(shared_memory_state).positions = (int *)zend_shared_alloc(sizeof(int) * ZSMMG(shared_segments_count)); + ZSMMG(shared_memory_state).positions = (size_t *)zend_shared_alloc(sizeof(size_t) * ZSMMG(shared_segments_count)); if (!ZSMMG(shared_memory_state).positions) { zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Insufficient shared memory!"); return ALLOC_FAILURE; diff --git a/ext/opcache/zend_shared_alloc.h b/ext/opcache/zend_shared_alloc.h index 4e090b98ddadf..3b2da46cb3b33 100644 --- a/ext/opcache/zend_shared_alloc.h +++ b/ext/opcache/zend_shared_alloc.h @@ -95,7 +95,7 @@ typedef struct _handler_entry { } zend_shared_memory_handler_entry; typedef struct _zend_shared_memory_state { - int *positions; /* current positions for each segment */ + size_t *positions; /* current positions for each segment */ size_t shared_free; /* amount of free shared memory */ } zend_shared_memory_state; From e270ee3008829fa50142ff39b2f6e5d2fa9cc665 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 23 Oct 2023 12:10:11 +0300 Subject: [PATCH 29/66] memory_consumption must be page aligned --- ext/opcache/zend_accelerator_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 3d4a9f8c68750..2c6f14f9ea588 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -71,7 +71,7 @@ static ZEND_INI_MH(OnUpdateMemoryConsumption) return FAILURE; } if (UNEXPECTED(memsize > ZEND_LONG_MAX / (1024 * 1024))) { - *p = ZEND_LONG_MAX; + *p = ZEND_LONG_MAX & ~(1024 * 1024 - 1); } else { *p = memsize * (1024 * 1024); } From 76c41d27f9277eb8210d0058f19d0a7cfa7d7a66 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 24 Oct 2023 14:20:35 +0300 Subject: [PATCH 30/66] Fixed GH-12482: Abortion with tracing JIT --- ext/opcache/jit/zend_jit_arm64.dasc | 2 +- ext/opcache/jit/zend_jit_x86.dasc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 0a0bd23c3160a..013600baf8d1d 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -14932,7 +14932,7 @@ static bool zend_jit_fetch_indirect_var(dasm_State **Dst, const zend_op *opline, if (opline->op1_type != IS_VAR || (opline-1)->result_type != IS_VAR || (opline-1)->result.var != opline->op1.var || - (opline-1)->op2_type == IS_VAR || + (opline-1)->op1_type == IS_VAR || (opline-1)->op2_type == IS_TMP_VAR) { | GET_ZVAL_PTR FCARG1x, var_addr, TMP1 } else if ((opline-1)->opcode == ZEND_FETCH_DIM_W || (opline-1)->opcode == ZEND_FETCH_DIM_RW) { diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index e1bd5bfdbdfea..31b8bfa2dea6a 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -15885,7 +15885,7 @@ static bool zend_jit_fetch_indirect_var(dasm_State **Dst, const zend_op *opline, if (opline->op1_type != IS_VAR || (opline-1)->result_type != IS_VAR || (opline-1)->result.var != opline->op1.var || - (opline-1)->op2_type == IS_VAR || + (opline-1)->op1_type == IS_VAR || (opline-1)->op2_type == IS_TMP_VAR) { | GET_ZVAL_PTR FCARG1a, var_addr } else if ((opline-1)->opcode == ZEND_FETCH_DIM_W || (opline-1)->opcode == ZEND_FETCH_DIM_RW) { From aa45df484903b1e24c348493cf1cda9cc56e44cd Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 24 Oct 2023 18:48:29 +0300 Subject: [PATCH 31/66] Fixed incorrect type inference --- Zend/Optimizer/zend_inference.c | 4 ++- ext/opcache/tests/jit/gh12482.phpt | 57 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/jit/gh12482.phpt diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 4cc9f70c27f05..ea144bbb34cce 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -3415,7 +3415,9 @@ static zend_always_inline int _zend_update_type_info( UPDATE_SSA_TYPE(tmp, ssa_op->result_def); break; case ZEND_FETCH_THIS: - UPDATE_SSA_OBJ_TYPE(op_array->scope, 1, ssa_op->result_def); + if (!(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) { + UPDATE_SSA_OBJ_TYPE(op_array->scope, 1, ssa_op->result_def); + } UPDATE_SSA_TYPE(MAY_BE_RCN|MAY_BE_OBJECT, ssa_op->result_def); break; case ZEND_FETCH_OBJ_R: diff --git a/ext/opcache/tests/jit/gh12482.phpt b/ext/opcache/tests/jit/gh12482.phpt new file mode 100644 index 0000000000000..021f7ce4526a3 --- /dev/null +++ b/ext/opcache/tests/jit/gh12482.phpt @@ -0,0 +1,57 @@ +--TEST-- +GH-12482: Invalid type inference +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit_hot_func=2 +--FILE-- +x = 42; + return $cloned; + } +} +class A { + use T; + public $a = 1; + public $b = 2; + public $c = 3; + public $x = 4; +} +class B { + use T; + public $x = 5; +} +$a = new A; +var_dump($a->foo()); +var_dump($a->foo()); +$b = new B; +var_dump($b->foo()); +?> +--EXPECT-- +object(A)#2 (4) { + ["a"]=> + int(1) + ["b"]=> + int(2) + ["c"]=> + int(3) + ["x"]=> + int(42) +} +object(A)#2 (4) { + ["a"]=> + int(1) + ["b"]=> + int(2) + ["c"]=> + int(3) + ["x"]=> + int(42) +} +object(B)#3 (1) { + ["x"]=> + int(42) +} From 900f0cab9f7ddc6b4154720f5a32b8f0346d56e1 Mon Sep 17 00:00:00 2001 From: icy17 <1061499390@qq.com> Date: Tue, 24 Oct 2023 16:09:40 +0800 Subject: [PATCH 32/66] Fix null pointer dereferences in case of allocation failure Closes GH-12506. --- NEWS | 7 +++++++ ext/dom/document.c | 3 +++ ext/xmlreader/php_xmlreader.c | 3 +++ ext/xmlwriter/php_xmlwriter.c | 3 +++ 4 files changed, 16 insertions(+) diff --git a/NEWS b/NEWS index 350d1f7dc7cb1..83594808d8027 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,7 @@ PHP NEWS - DOM: . Fix registerNodeClass with abstract class crashing. (nielsdos) + . Add missing NULL pointer error check. (icy17) - Fiber: . Fixed bug GH-11121 (ReflectionFiber segfault). (danog, trowski, bwoebi) @@ -39,6 +40,12 @@ PHP NEWS . Fixed bug #75708 (getimagesize with "&$imageinfo" fails on StreamWrappers). (Jakub Zelenka) +- XMLReader: + . Add missing NULL pointer error check. (icy17) + +- XMLWriter: + . Add missing NULL pointer error check. (icy17) + - XSL: . Add missing module dependency. (nielsdos) diff --git a/ext/dom/document.c b/ext/dom/document.c index 38bb4553a11a1..59f00897a69aa 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -1148,6 +1148,9 @@ char *_dom_get_valid_file_path(char *source, char *resolved_path, int resolved_p int isFileUri = 0; uri = xmlCreateURI(); + if (uri == NULL) { + return NULL; + } escsource = xmlURIEscapeStr((xmlChar *) source, (xmlChar *) ":"); xmlParseURIReference(uri, (char *) escsource); xmlFree(escsource); diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c index 12be9ada01194..3484cbdc5d9aa 100644 --- a/ext/xmlreader/php_xmlreader.c +++ b/ext/xmlreader/php_xmlreader.c @@ -211,6 +211,9 @@ char *_xmlreader_get_valid_file_path(char *source, char *resolved_path, int reso int isFileUri = 0; uri = xmlCreateURI(); + if (uri == NULL) { + return NULL; + } escsource = xmlURIEscapeStr((xmlChar *)source, (xmlChar *)":"); xmlParseURIReference(uri, (const char *)escsource); xmlFree(escsource); diff --git a/ext/xmlwriter/php_xmlwriter.c b/ext/xmlwriter/php_xmlwriter.c index 24ce414034af5..2966747fc52da 100644 --- a/ext/xmlwriter/php_xmlwriter.c +++ b/ext/xmlwriter/php_xmlwriter.c @@ -110,6 +110,9 @@ static char *_xmlwriter_get_valid_file_path(char *source, char *resolved_path, i int isFileUri = 0; uri = xmlCreateURI(); + if (uri == NULL) { + return NULL; + } escsource = xmlURIEscapeStr((xmlChar *)source, (xmlChar *) ":"); xmlParseURIReference(uri, (char *)escsource); xmlFree(escsource); From 98908db72b34dccdec4d4a1d9a47786690a99243 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 24 Oct 2023 19:35:55 +0200 Subject: [PATCH 33/66] [ci skip] NEWS --- NEWS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 83594808d8027..45ed412eef12d 100644 --- a/NEWS +++ b/NEWS @@ -23,8 +23,8 @@ PHP NEWS upgrading to 8.1.3 due to corrupt on-disk file cache). (turchanov) - OpenSSL: - Fixed bug GH-12489 (Missing sigbio creation checking in openssl_cms_verify). - (Jakub Zelenka) + . Fixed bug GH-12489 (Missing sigbio creation checking in openssl_cms_verify). + (Jakub Zelenka) - SOAP: . Fixed bug GH-12392 (Segmentation fault on SoapClient::__getTypes). From fbf4e196dadcbe3047608be258d9cf45e3d773f6 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 25 Oct 2023 15:15:13 +0300 Subject: [PATCH 34/66] Fixed regression intoduced by 76c41d27f9277eb8210d0058f19d0a7cfa7d7a66 --- ext/opcache/jit/zend_jit_arm64.dasc | 1 + ext/opcache/jit/zend_jit_x86.dasc | 1 + 2 files changed, 2 insertions(+) diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 013600baf8d1d..1583706855d41 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -14933,6 +14933,7 @@ static bool zend_jit_fetch_indirect_var(dasm_State **Dst, const zend_op *opline, (opline-1)->result_type != IS_VAR || (opline-1)->result.var != opline->op1.var || (opline-1)->op1_type == IS_VAR || + (opline-1)->op2_type == IS_VAR || (opline-1)->op2_type == IS_TMP_VAR) { | GET_ZVAL_PTR FCARG1x, var_addr, TMP1 } else if ((opline-1)->opcode == ZEND_FETCH_DIM_W || (opline-1)->opcode == ZEND_FETCH_DIM_RW) { diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 31b8bfa2dea6a..b3989a4ae254d 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -15886,6 +15886,7 @@ static bool zend_jit_fetch_indirect_var(dasm_State **Dst, const zend_op *opline, (opline-1)->result_type != IS_VAR || (opline-1)->result.var != opline->op1.var || (opline-1)->op1_type == IS_VAR || + (opline-1)->op2_type == IS_VAR || (opline-1)->op2_type == IS_TMP_VAR) { | GET_ZVAL_PTR FCARG1a, var_addr } else if ((opline-1)->opcode == ZEND_FETCH_DIM_W || (opline-1)->opcode == ZEND_FETCH_DIM_RW) { From 9f7f3b2034546d90860862f669ae6b801e23ed67 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 24 Oct 2023 20:20:05 +0200 Subject: [PATCH 35/66] Fix incorrect dtor for persistent sdl->encoders Closes GH-12515. --- NEWS | 1 + ext/soap/php_sdl.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 45ed412eef12d..9d8e4f553ff23 100644 --- a/NEWS +++ b/NEWS @@ -35,6 +35,7 @@ PHP NEWS . Fix incorrect uri check in SOAP caching. (nielsdos) . Fix segfault and assertion failure with refcounted props and arrays. (nielsdos) + . Fix potential crash with an edge case of persistent encoders. (nielsdos) - Streams: . Fixed bug #75708 (getimagesize with "&$imageinfo" fails on StreamWrappers). diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index e7ea112317830..038515087fafc 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -155,7 +155,7 @@ encodePtr get_encoder(sdlPtr sdl, const char *ns, const char *type) } if (sdl->encoders == NULL) { sdl->encoders = pemalloc(sizeof(HashTable), sdl->is_persistent); - zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, sdl->is_persistent); + zend_hash_init(sdl->encoders, 0, NULL, sdl->is_persistent ? delete_encoder_persistent : delete_encoder, sdl->is_persistent); } zend_hash_str_update_ptr(sdl->encoders, nscat, len, new_enc); enc = new_enc; From 27797a26caa8368b6158e7b11cbbc661fc495772 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 18 Oct 2023 20:18:40 +0200 Subject: [PATCH 36/66] Fix bug #75306: Memleak in SoapClient Setting the stream context via php_stream_context_to_zval() will increase the reference count. So if the new context is created, then it will end up with a reference count of 2 while it should be 1. Credits to cmb for the analysis. I arrived at the same patch as he did. Closes GH-12523. --- NEWS | 1 + ext/soap/php_sdl.c | 5 ++++- ext/soap/tests/bug75306.phpt | 20 ++++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 ext/soap/tests/bug75306.phpt diff --git a/NEWS b/NEWS index 9d8e4f553ff23..1ded7f9918d62 100644 --- a/NEWS +++ b/NEWS @@ -36,6 +36,7 @@ PHP NEWS . Fix segfault and assertion failure with refcounted props and arrays. (nielsdos) . Fix potential crash with an edge case of persistent encoders. (nielsdos) + . Fixed bug #75306 (Memleak in SoapClient). (nielsdos) - Streams: . Fixed bug #75708 (getimagesize with "&$imageinfo" fails on StreamWrappers). diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index 038515087fafc..651eab23b7aad 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -3255,6 +3255,9 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, zend_long cache_wsdl) tmp = Z_CLIENT_STREAM_CONTEXT_P(this_ptr); if (Z_TYPE_P(tmp) == IS_RESOURCE) { context = php_stream_context_from_zval(tmp, 0); + /* Share a reference with new_context down below. + * For new contexts, the reference is only in new_context so that doesn't need extra refcounting. */ + GC_ADDREF(context->res); } tmp = Z_CLIENT_USER_AGENT_P(this_ptr); @@ -3323,7 +3326,7 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, zend_long cache_wsdl) } if (context) { - php_stream_context_to_zval(context, &new_context); + ZVAL_RES(&new_context, context->res); php_libxml_switch_context(&new_context, &orig_context); } diff --git a/ext/soap/tests/bug75306.phpt b/ext/soap/tests/bug75306.phpt new file mode 100644 index 0000000000000..7501fde59e6b8 --- /dev/null +++ b/ext/soap/tests/bug75306.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #75306 (Memleak in SoapClient) +--EXTENSIONS-- +soap +--FILE-- + WSDL_CACHE_NONE); +// Need a warm-up for globals +for ($i = 0; $i < 10; $i++) { + $client = new SoapClient("ext/soap/tests/test.wsdl", $options); +} +$usage = memory_get_usage(); +for ($i = 0; $i < 10; $i++) { + $client = new SoapClient("ext/soap/tests/test.wsdl", $options); +} +$usage_delta = memory_get_usage() - $usage; +var_dump($usage_delta); +?> +--EXPECT-- +int(0) From 5f46d86955992d73a4845bd51d620726fde35a08 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 26 Oct 2023 23:58:29 +0300 Subject: [PATCH 37/66] Fixed GH-12509: JIT assertion when running php-parser tests --- Zend/Optimizer/zend_inference.c | 6 ++++++ ext/opcache/tests/jit/gh12509.phpt | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 ext/opcache/tests/jit/gh12509.phpt diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index ea144bbb34cce..97b5aa3ede632 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -1746,6 +1746,12 @@ static uint32_t get_ssa_alias_types(zend_ssa_alias_kind alias) { } \ if (__var >= 0) { \ zend_ssa_var *__ssa_var = &ssa_vars[__var]; \ + if (__ssa_var->var < op_array->num_args) { \ + if (__type & MAY_BE_RC1) { \ + /* TODO: may be captured by exception backtreace */ \ + __type |= MAY_BE_RCN; \ + } \ + } \ if (__ssa_var->var < op_array->last_var) { \ if (__type & (MAY_BE_REF|MAY_BE_RCN)) { \ __type |= MAY_BE_RC1 | MAY_BE_RCN; \ diff --git a/ext/opcache/tests/jit/gh12509.phpt b/ext/opcache/tests/jit/gh12509.phpt new file mode 100644 index 0000000000000..ae8bdee661967 --- /dev/null +++ b/ext/opcache/tests/jit/gh12509.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-12509: JIT assertion when running php-parser tests +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- + +--EXPECT-- +array(3) { + [1]=> + int(1) + [2]=> + int(2) + [3]=> + int(3) +} \ No newline at end of file From 83a505e85f99186cf87b61d49cf1bafd931d655f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Sat, 14 Oct 2023 23:48:00 +0200 Subject: [PATCH 38/66] Fix GH-11374: Different preg_match result with -d pcre.jit=0 This is a backport of https://github.com/PCRE2Project/pcre2/pull/300. Closes GH-12439. --- NEWS | 4 +++ ext/pcre/pcre2lib/pcre2_match.c | 2 +- ext/pcre/tests/gh11374.phpt | 60 +++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 ext/pcre/tests/gh11374.phpt diff --git a/NEWS b/NEWS index 1ded7f9918d62..68b54c0619f79 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,10 @@ PHP NEWS . Fixed bug GH-12489 (Missing sigbio creation checking in openssl_cms_verify). (Jakub Zelenka) +- PCRE: + . Fixed bug GH-11374 (Backport upstream fix, Different preg_match result + with -d pcre.jit=0). (mvorisek) + - SOAP: . Fixed bug GH-12392 (Segmentation fault on SoapClient::__getTypes). (nielsdos) diff --git a/ext/pcre/pcre2lib/pcre2_match.c b/ext/pcre/pcre2lib/pcre2_match.c index f28cdbb47a515..e62659a556145 100644 --- a/ext/pcre/pcre2lib/pcre2_match.c +++ b/ext/pcre/pcre2lib/pcre2_match.c @@ -5640,7 +5640,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode); { P = (heapframe *)((char *)N - frame_size); memcpy((char *)F + offsetof(heapframe, ovector), P->ovector, - P->offset_top * sizeof(PCRE2_SIZE)); + Foffset_top * sizeof(PCRE2_SIZE)); Foffset_top = P->offset_top; Fcapture_last = P->capture_last; Fcurrent_recurse = P->current_recurse; diff --git a/ext/pcre/tests/gh11374.phpt b/ext/pcre/tests/gh11374.phpt new file mode 100644 index 0000000000000..07f8f4bccfd0a --- /dev/null +++ b/ext/pcre/tests/gh11374.phpt @@ -0,0 +1,60 @@ +--TEST-- +GH-11374 (PCRE regular expression without JIT enabled gives different result) +--FILE-- + + (?: + (?:\{ (?&types) \}) + | (a) + ) + (\*?) + ) +'; + +ini_set('pcre.jit', '0'); +$res = preg_match('{^' . $regex . '$}x', '{a}', $matches, PREG_OFFSET_CAPTURE); +ini_set('pcre.jit', '1'); +// regex must be different to prevent regex cache, so just add 2nd "x" modifier +$res2 = preg_match('{^' . $regex . '$}xx', '{a}', $matches2, PREG_OFFSET_CAPTURE); + +var_dump($matches === $matches2); +print_r($matches); + +?> +--EXPECT-- +bool(true) +Array +( + [0] => Array + ( + [0] => {a} + [1] => 0 + ) + + [types] => Array + ( + [0] => {a} + [1] => 0 + ) + + [1] => Array + ( + [0] => {a} + [1] => 0 + ) + + [2] => Array + ( + [0] => + [1] => -1 + ) + + [3] => Array + ( + [0] => + [1] => 3 + ) + +) From 04b35a44ce335a1578a41cc60a888dab6a5a9508 Mon Sep 17 00:00:00 2001 From: sji Date: Sat, 28 Oct 2023 21:59:06 +0900 Subject: [PATCH 39/66] Fix segfault caused by weak references to FFI objects (#12488) Thank you! --- ext/ffi/ffi.c | 13 ++++++++++ ext/ffi/tests/weak_reference_001.phpt | 17 +++++++++++++ ext/ffi/tests/weak_reference_002.phpt | 36 +++++++++++++++++++++++++++ ext/ffi/tests/weak_reference_003.phpt | 17 +++++++++++++ ext/ffi/tests/weak_reference_004.phpt | 36 +++++++++++++++++++++++++++ 5 files changed, 119 insertions(+) create mode 100644 ext/ffi/tests/weak_reference_001.phpt create mode 100644 ext/ffi/tests/weak_reference_002.phpt create mode 100644 ext/ffi/tests/weak_reference_003.phpt create mode 100644 ext/ffi/tests/weak_reference_004.phpt diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index efb4524c76b1a..a2779b65b120c 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -24,6 +24,7 @@ #include "php_scandir.h" #include "zend_exceptions.h" #include "zend_closures.h" +#include "zend_weakrefs.h" #include "main/SAPI.h" #include "ffi_arginfo.h" @@ -2143,6 +2144,10 @@ static void zend_ffi_ctype_free_obj(zend_object *object) /* {{{ */ zend_ffi_ctype *ctype = (zend_ffi_ctype*)object; zend_ffi_type_dtor(ctype->type); + + if (UNEXPECTED(GC_FLAGS(object) & IS_OBJ_WEAKLY_REFERENCED)) { + zend_weakrefs_notify(object); + } } /* }}} */ @@ -2369,6 +2374,10 @@ static void zend_ffi_free_obj(zend_object *object) /* {{{ */ zend_hash_destroy(ffi->tags); efree(ffi->tags); } + + if (UNEXPECTED(GC_FLAGS(object) & IS_OBJ_WEAKLY_REFERENCED)) { + zend_weakrefs_notify(object); + } } /* }}} */ @@ -2377,6 +2386,10 @@ static void zend_ffi_cdata_free_obj(zend_object *object) /* {{{ */ zend_ffi_cdata *cdata = (zend_ffi_cdata*)object; zend_ffi_cdata_dtor(cdata); + + if (UNEXPECTED(GC_FLAGS(object) & IS_OBJ_WEAKLY_REFERENCED)) { + zend_weakrefs_notify(object); + } } /* }}} */ diff --git a/ext/ffi/tests/weak_reference_001.phpt b/ext/ffi/tests/weak_reference_001.phpt new file mode 100644 index 0000000000000..56f0be981f629 --- /dev/null +++ b/ext/ffi/tests/weak_reference_001.phpt @@ -0,0 +1,17 @@ +--TEST-- +Weak reference to \FFI +--EXTENSIONS-- +ffi +--INI-- +ffi.enable=1 +--FILE-- +get() === $ffi); +unset($ffi); +var_dump($ref->get() === null); +?> +--EXPECTF-- +bool(true) +bool(true) diff --git a/ext/ffi/tests/weak_reference_002.phpt b/ext/ffi/tests/weak_reference_002.phpt new file mode 100644 index 0000000000000..5c36cfa703455 --- /dev/null +++ b/ext/ffi/tests/weak_reference_002.phpt @@ -0,0 +1,36 @@ +--TEST-- +Weak reference to \FFI\CData +--EXTENSIONS-- +ffi +--INI-- +ffi.enable=1 +--FILE-- +get() === $cdata_value); +var_dump($ref_array->get() === $cdata_array); +var_dump($ref_free->get() === $cdata_free); + +unset($cdata_value); +unset($cdata_array); +unset($cdata_free); + +var_dump($ref_value->get() === null); +var_dump($ref_array->get() === null); +var_dump($ref_free->get() === null); +?> +--EXPECTF-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) diff --git a/ext/ffi/tests/weak_reference_003.phpt b/ext/ffi/tests/weak_reference_003.phpt new file mode 100644 index 0000000000000..15b9397a6856b --- /dev/null +++ b/ext/ffi/tests/weak_reference_003.phpt @@ -0,0 +1,17 @@ +--TEST-- +Weak reference to \FFI\CType +--EXTENSIONS-- +ffi +--INI-- +ffi.enable=1 +--FILE-- +get() === $ctype); +unset($ctype); +var_dump($ref->get() === null); +?> +--EXPECTF-- +bool(true) +bool(true) diff --git a/ext/ffi/tests/weak_reference_004.phpt b/ext/ffi/tests/weak_reference_004.phpt new file mode 100644 index 0000000000000..500776fa21865 --- /dev/null +++ b/ext/ffi/tests/weak_reference_004.phpt @@ -0,0 +1,36 @@ +--TEST-- +Using FFI Types for keys of a WeakMap +--EXTENSIONS-- +ffi +--INI-- +ffi.enable=1 +--FILE-- + +--EXPECTF-- +bool(true) +bool(true) From bbfadd32e8c50259c7cf25615e67f82c12f57b6d Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Sat, 28 Oct 2023 15:02:20 +0200 Subject: [PATCH 40/66] [ci skip] NEWS --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index 68b54c0619f79..ee42cf7c4eb5f 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ PHP NEWS - Core: . Fixed bug GH-12468 (Double-free of doc_comment when overriding static property via trait). (ilutov) + . Fixed segfault caused by weak references to FFI objects. (sj-i) - DOM: . Fix registerNodeClass with abstract class crashing. (nielsdos) From ae9118a7e431e96d2bc907d77a9e33d99acf8885 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Sat, 28 Oct 2023 15:04:13 +0200 Subject: [PATCH 41/66] [ci skip] NEWS --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index ee76548d210cd..39cac4703683b 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,7 @@ PHP NEWS needle). (SakiTakamachi) . Fixed bug GH-12468 (Double-free of doc_comment when overriding static property via trait). (ilutov) + . Fixed segfault caused by weak references to FFI objects. (sj-i) - DOM: . Fix registerNodeClass with abstract class crashing. (nielsdos) From 39f3374be5611cdea90c3fe9b69ba7622244c8bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sun, 29 Oct 2023 12:17:48 +0100 Subject: [PATCH 42/66] fix: don't delete an unitialized timer (#12537) --- Zend/zend_max_execution_timer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Zend/zend_max_execution_timer.c b/Zend/zend_max_execution_timer.c index b1c83e9cbb3a6..480631dcb169a 100644 --- a/Zend/zend_max_execution_timer.c +++ b/Zend/zend_max_execution_timer.c @@ -41,12 +41,13 @@ ZEND_API void zend_max_execution_timer_init(void) /* {{{ */ sev.sigev_signo = SIGRTMIN; sev.sigev_notify_thread_id = (pid_t) syscall(SYS_gettid); - EG(pid) = getpid(); // Measure wall time instead of CPU time as originally planned now that it is possible https://github.com/php/php-src/pull/6504#issuecomment-1370303727 if (timer_create(CLOCK_BOOTTIME, &sev, &EG(max_execution_timer_timer)) != 0) { zend_strerror_noreturn(E_ERROR, errno, "Could not create timer"); } + EG(pid) = getpid(); + # ifdef MAX_EXECUTION_TIMERS_DEBUG fprintf(stderr, "Timer %#jx created on thread %d\n", (uintmax_t) EG(max_execution_timer_timer), sev.sigev_notify_thread_id); # endif From 29dbc4ae83ba06c16d2ba37a5689352b7e3e057d Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Sun, 29 Oct 2023 12:19:56 +0100 Subject: [PATCH 43/66] [ci skip] NEWS --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index ee42cf7c4eb5f..6dac57d6a3baa 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,7 @@ PHP NEWS . Fixed bug GH-12468 (Double-free of doc_comment when overriding static property via trait). (ilutov) . Fixed segfault caused by weak references to FFI objects. (sj-i) + . Fixed max_execution_time: don't delete an unitialized timer. (Kévin Dunglas) - DOM: . Fix registerNodeClass with abstract class crashing. (nielsdos) From c7fda3b46f90d0c75f5b73e8d69cd90a4c2a42c3 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Sun, 29 Oct 2023 12:20:31 +0100 Subject: [PATCH 44/66] [ci skip] NEWS --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index 39cac4703683b..c1f6557de1003 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ PHP NEWS . Fixed bug GH-12468 (Double-free of doc_comment when overriding static property via trait). (ilutov) . Fixed segfault caused by weak references to FFI objects. (sj-i) + . Fixed max_execution_time: don't delete an unitialized timer. (Kévin Dunglas) - DOM: . Fix registerNodeClass with abstract class crashing. (nielsdos) From 3bf5d89efb0f8bb770963c96aec9a2eda9dd0813 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 29 Oct 2023 13:49:20 +0100 Subject: [PATCH 45/66] Fix memory leak in error path of zend_register_list_destructors_ex --- Zend/zend_list.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Zend/zend_list.c b/Zend/zend_list.c index b3409e33ce845..369eb08d16107 100644 --- a/Zend/zend_list.c +++ b/Zend/zend_list.c @@ -275,6 +275,7 @@ ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_fu ZVAL_PTR(&zv, lde); if (zend_hash_next_index_insert(&list_destructors, &zv) == NULL) { + free(lde); return FAILURE; } return list_destructors.nNextFreeElement-1; From b280f1f9647812b490826507efd575cfbad84537 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 30 Oct 2023 11:27:22 +0100 Subject: [PATCH 46/66] Run FreeBSD on push With ARM build moved to CircleCI, we should have enough credits to keep FreeBSD on Cirrus on every commit. --- .cirrus.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index dc66631d98072..b04d91b9d45b2 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -3,7 +3,6 @@ env: freebsd_task: name: FREEBSD_DEBUG_NTS - only_if: $CIRRUS_CRON == 'nightly' || $CIRRUS_CHANGE_TITLE =~ '.*\[ci freebsd\].*' freebsd_instance: image_family: freebsd-13-2 env: From c3d2f519d06fbb817ade6e4f165f687bd9b375e3 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 30 Oct 2023 16:50:30 +0100 Subject: [PATCH 47/66] [skip ci] Update mysql 5.7 patch --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index ae6877c40228a..9e8441ba09b72 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -619,7 +619,7 @@ jobs: - name: Build mysql-5.7 uses: ./.github/actions/build-libmysqlclient with: - libmysql: mysql-5.7.41-linux-glibc2.12-x86_64.tar.gz + libmysql: mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz withMysqli: ${{ matrix.branch.ref == 'PHP-8.1' }} - name: Test mysql-5.7 uses: ./.github/actions/test-libmysqlclient From b0bac336b3e7228aa12af910e1e61a732b734ca0 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 30 Oct 2023 17:46:11 +0100 Subject: [PATCH 48/66] [skip ci] Fix laravel community build FilesystemTest::testSharedGet() uses too much memory and crashes GA. It was already ignored by adding the `@skip` attribute, but the code changed and the replacement stopped working. Closes GH-12570 --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 9e8441ba09b72..acc0973f00036 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -341,7 +341,7 @@ jobs: git rev-parse HEAD php /usr/bin/composer install --no-progress --ignore-platform-reqs # Hack to disable a test that hangs - php -r '$c = file_get_contents("tests/Filesystem/FilesystemTest.php"); $c = str_replace("*/\n public function testSharedGet()", "* @group skip\n */\n public function testSharedGet()", $c); file_put_contents("tests/Filesystem/FilesystemTest.php", $c);' + php -r '$c = file_get_contents("tests/Filesystem/FilesystemTest.php"); $c = str_replace("public function testSharedGet()", "/** @group skip */\n public function testSharedGet()", $c); file_put_contents("tests/Filesystem/FilesystemTest.php", $c);' export ASAN_OPTIONS=exitcode=139 php vendor/bin/phpunit --exclude-group skip || EXIT_CODE=$? if [ $EXIT_CODE -gt 128 ]; then From abe3673d1fd09a35c25b4da6248f7e8c106aa37e Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 30 Oct 2023 23:36:12 +0300 Subject: [PATCH 49/66] Fix memory leak after GC inside a foreach loop (#12572) Fixes oss-fuzz #54515 --- Zend/tests/gc_047.phpt | 20 ++++++++++++++++++++ Zend/zend_gc.c | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/gc_047.phpt diff --git a/Zend/tests/gc_047.phpt b/Zend/tests/gc_047.phpt new file mode 100644 index 0000000000000..08403d1e99bc9 --- /dev/null +++ b/Zend/tests/gc_047.phpt @@ -0,0 +1,20 @@ +--TEST-- +GC 047: Leak after GC inside a foreach loop +--INI-- +zend.enable_gc=1 +--FILE-- + +--EXPECT-- +int(2) diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index f062747eaeb63..c9034ba5e34c6 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -1696,7 +1696,7 @@ static void zend_gc_root_tmpvars(void) { } uint32_t kind = range->var & ZEND_LIVE_MASK; - if (kind == ZEND_LIVE_TMPVAR) { + if (kind == ZEND_LIVE_TMPVAR || kind == ZEND_LIVE_LOOP) { uint32_t var_num = range->var & ~ZEND_LIVE_MASK; zval *var = ZEND_CALL_VAR(ex, var_num); if (Z_REFCOUNTED_P(var)) { From b3b46a44c58804ec2557974efe1bc943efed011c Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 31 Oct 2023 07:51:36 +0300 Subject: [PATCH 50/66] Fixed GH-12511: Use must be in next opline assertion with patched infection --- Zend/Optimizer/zend_inference.c | 17 ++++++++++++++--- ext/opcache/tests/opt/inference_022.phpt | 17 +++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 ext/opcache/tests/opt/inference_022.phpt diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 97b5aa3ede632..c65104cee787b 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -3312,10 +3312,18 @@ static zend_always_inline int _zend_update_type_info( zend_uchar opcode; if (!ssa_opcodes) { - ZEND_ASSERT(j == (opline - op_array->opcodes) + 1 && "Use must be in next opline"); + if (j != (opline - op_array->opcodes) + 1) { + /* Use must be in next opline */ + tmp |= key_type | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; + break; + } opcode = op_array->opcodes[j].opcode; } else { - ZEND_ASSERT(ssa_opcodes[j] == opline + 1 && "Use must be in next opline"); + if (ssa_opcodes[j] != opline + 1) { + /* Use must be in next opline */ + tmp |= key_type | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; + break; + } opcode = ssa_opcodes[j]->opcode; } switch (opcode) { @@ -3374,7 +3382,10 @@ static zend_always_inline int _zend_update_type_info( EMPTY_SWITCH_DEFAULT_CASE() } j = zend_ssa_next_use(ssa->ops, ssa_op->result_def, j); - ZEND_ASSERT(j < 0 && "There should only be one use"); + if (j >= 0) { + tmp |= key_type | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; + break; + } } } if (((tmp & MAY_BE_ARRAY) && (tmp & MAY_BE_ARRAY_KEY_ANY)) diff --git a/ext/opcache/tests/opt/inference_022.phpt b/ext/opcache/tests/opt/inference_022.phpt new file mode 100644 index 0000000000000..b745499f6021a --- /dev/null +++ b/ext/opcache/tests/opt/inference_022.phpt @@ -0,0 +1,17 @@ +--TEST-- +Type inference 022: FETCH_DIM_W +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECT-- +DONE From 52bb39e661ff0dfc346be7fb30e7bd79593f93dd Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 27 Oct 2023 00:28:22 +0300 Subject: [PATCH 51/66] Backport implementation of iterative Pearce's SCC finding algoritm (#12528) Fixes GH-11795 --- Zend/Optimizer/zend_inference.c | 289 ++++++++++++++++++++++++++++---- 1 file changed, 261 insertions(+), 28 deletions(-) diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index c65104cee787b..49dd44ff89085 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -77,11 +77,12 @@ #define CHECK_SCC_VAR(var2) \ do { \ if (!ssa->vars[var2].no_val) { \ - if (dfs[var2] < 0) { \ - zend_ssa_check_scc_var(op_array, ssa, var2, index, dfs, root, stack); \ + if (ssa->vars[var2].scc < 0) { \ + zend_ssa_check_scc_var(op_array, ssa, var2, index, stack); \ } \ - if (ssa->vars[var2].scc < 0 && dfs[root[var]] >= dfs[root[var2]]) { \ - root[var] = root[var2]; \ + if (ssa->vars[var2].scc < ssa->vars[var].scc) { \ + ssa->vars[var].scc = ssa->vars[var2].scc; \ + is_root = 0; \ } \ } \ } while (0) @@ -172,15 +173,17 @@ static inline bool sub_will_overflow(zend_long a, zend_long b) { } #endif -static void zend_ssa_check_scc_var(const zend_op_array *op_array, zend_ssa *ssa, int var, int *index, int *dfs, int *root, zend_worklist_stack *stack) /* {{{ */ +#if 0 +/* Recursive Pearce's SCC algorithm implementation */ +static void zend_ssa_check_scc_var(const zend_op_array *op_array, zend_ssa *ssa, int var, int *index, zend_worklist_stack *stack) /* {{{ */ { + int is_root = 1; #ifdef SYM_RANGE zend_ssa_phi *p; #endif - dfs[var] = *index; + ssa->vars[var].scc = *index; (*index)++; - root[var] = var; FOR_EACH_VAR_USAGE(var, CHECK_SCC_VAR); @@ -193,17 +196,20 @@ static void zend_ssa_check_scc_var(const zend_op_array *op_array, zend_ssa *ssa, } #endif - if (root[var] == var) { - ssa->vars[var].scc = ssa->sccs; + if (is_root) { + ssa->sccs--; while (stack->len > 0) { int var2 = zend_worklist_stack_peek(stack); - if (dfs[var2] <= dfs[var]) { + if (ssa->vars[var2].scc < ssa->vars[var].scc) { break; } zend_worklist_stack_pop(stack); ssa->vars[var2].scc = ssa->sccs; + (*index)--; } - ssa->sccs++; + ssa->vars[var].scc = ssa->sccs; + ssa->vars[var].scc_entry = 1; + (*index)--; } else { zend_worklist_stack_push(stack, var); } @@ -212,50 +218,277 @@ static void zend_ssa_check_scc_var(const zend_op_array *op_array, zend_ssa *ssa, ZEND_API int zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */ { - int index = 0, *dfs, *root; + int index = 0; zend_worklist_stack stack; int j; - ALLOCA_FLAG(dfs_use_heap) - ALLOCA_FLAG(root_use_heap) ALLOCA_FLAG(stack_use_heap) - dfs = do_alloca(sizeof(int) * ssa->vars_count, dfs_use_heap); - memset(dfs, -1, sizeof(int) * ssa->vars_count); - root = do_alloca(sizeof(int) * ssa->vars_count, root_use_heap); ZEND_WORKLIST_STACK_ALLOCA(&stack, ssa->vars_count, stack_use_heap); - /* Find SCCs using Tarjan's algorithm. */ + /* Find SCCs using Pearce's algorithm. */ + ssa->sccs = ssa->vars_count; for (j = 0; j < ssa->vars_count; j++) { - if (!ssa->vars[j].no_val && dfs[j] < 0) { - zend_ssa_check_scc_var(op_array, ssa, j, &index, dfs, root, &stack); + if (!ssa->vars[j].no_val && ssa->vars[j].scc < 0) { + zend_ssa_check_scc_var(op_array, ssa, j, &index, &stack); + } + } + + if (ssa->sccs) { + /* Shift SCC indexes. */ + for (j = 0; j < ssa->vars_count; j++) { + if (ssa->vars[j].scc >= 0) { + ssa->vars[j].scc -= ssa->sccs; + } } } + ssa->sccs = ssa->vars_count - ssa->sccs; - /* Revert SCC order. This results in a topological order. */ for (j = 0; j < ssa->vars_count; j++) { if (ssa->vars[j].scc >= 0) { - ssa->vars[j].scc = ssa->sccs - (ssa->vars[j].scc + 1); + int var = j; + FOR_EACH_VAR_USAGE(var, CHECK_SCC_ENTRY); } } + ZEND_WORKLIST_STACK_FREE_ALLOCA(&stack, stack_use_heap); + return SUCCESS; +} +/* }}} */ + +#else +/* Iterative Pearce's SCC algorithm implementation */ + +typedef struct _zend_scc_iterator { + int state; + int last; + union { + int use; + zend_ssa_phi *phi; + }; +} zend_scc_iterator; + +static int zend_scc_next(const zend_op_array *op_array, zend_ssa *ssa, int var, zend_scc_iterator *iterator) /* {{{ */ +{ + zend_ssa_phi *phi; + int use, var2; + + switch (iterator->state) { + case 0: goto state_0; + case 1: use = iterator->use; goto state_1; + case 2: use = iterator->use; goto state_2; + case 3: use = iterator->use; goto state_3; + case 4: use = iterator->use; goto state_4; + case 5: use = iterator->use; goto state_5; + case 6: use = iterator->use; goto state_6; + case 7: use = iterator->use; goto state_7; + case 8: use = iterator->use; goto state_8; + case 9: phi = iterator->phi; goto state_9; +#ifdef SYM_RANGE + case 10: phi = iterator->phi; goto state_10; +#endif + case 11: goto state_11; + } + +state_0: + use = ssa->vars[var].use_chain; + while (use >= 0) { + iterator->use = use; + var2 = ssa->ops[use].op1_def; + if (var2 >= 0 && !ssa->vars[var2].no_val) { + iterator->state = 1; + return var2; + } +state_1: + var2 = ssa->ops[use].op2_def; + if (var2 >= 0 && !ssa->vars[var2].no_val) { + iterator->state = 2; + return var2; + } +state_2: + var2 = ssa->ops[use].result_def; + if (var2 >= 0 && !ssa->vars[var2].no_val) { + iterator->state = 3; + return var2; + } +state_3: + if (op_array->opcodes[use].opcode == ZEND_OP_DATA) { + var2 = ssa->ops[use-1].op1_def; + if (var2 >= 0 && !ssa->vars[var2].no_val) { + iterator->state = 4; + return var2; + } +state_4: + var2 = ssa->ops[use-1].op2_def; + if (var2 >= 0 && !ssa->vars[var2].no_val) { + iterator->state = 5; + return var2; + } +state_5: + var2 = ssa->ops[use-1].result_def; + if (var2 >= 0 && !ssa->vars[var2].no_val) { + iterator->state = 8; + return var2; + } + } else if ((uint32_t)use+1 < op_array->last && + op_array->opcodes[use+1].opcode == ZEND_OP_DATA) { + var2 = ssa->ops[use+1].op1_def; + if (var2 >= 0 && !ssa->vars[var2].no_val) { + iterator->state = 6; + return var2; + } +state_6: + var2 = ssa->ops[use+1].op2_def; + if (var2 >= 0 && !ssa->vars[var2].no_val) { + iterator->state = 7; + return var2; + } +state_7: + var2 = ssa->ops[use+1].result_def; + if (var2 >= 0 && !ssa->vars[var2].no_val) { + iterator->state = 8; + return var2; + } + } +state_8: + use = zend_ssa_next_use(ssa->ops, var, use); + } + + phi = ssa->vars[var].phi_use_chain; + while (phi) { + var2 = phi->ssa_var; + if (!ssa->vars[var2].no_val) { + iterator->state = 9; + iterator->phi = phi; + return var2; + } +state_9: + phi = zend_ssa_next_use_phi(ssa, var, phi); + } + +#ifdef SYM_RANGE + /* Process symbolic control-flow constraints */ + phi = ssa->vars[var].sym_use_chain; + while (phi) { + var2 = phi->ssa_var; + if (!ssa->vars[var2].no_val) { + iterator->state = 10; + iterator->phi = phi; + return var2; + } +state_10: + phi = phi->sym_use_chain; + } +#endif + + iterator->state = 11; +state_11: + return -1; +} +/* }}} */ + +static void zend_ssa_check_scc_var(const zend_op_array *op_array, zend_ssa *ssa, int var, int *index, zend_worklist_stack *stack, zend_worklist_stack *vstack, zend_scc_iterator *iterators) /* {{{ */ +{ +restart: + zend_worklist_stack_push(vstack, var); + iterators[var].state = 0; + iterators[var].last = -1; + ssa->vars[var].scc_entry = 1; + ssa->vars[var].scc = *index; + (*index)++; + + while (vstack->len > 0) { + var = zend_worklist_stack_peek(vstack); + while (1) { + int var2; + + if (iterators[var].last >= 0) { + /* finish edge */ + var2 = iterators[var].last; + if (ssa->vars[var2].scc < ssa->vars[var].scc) { + ssa->vars[var].scc = ssa->vars[var2].scc; + ssa->vars[var].scc_entry = 0; + } + } + var2 = zend_scc_next(op_array, ssa, var, iterators + var); + iterators[var].last = var2; + if (var2 < 0) break; + /* begin edge */ + if (ssa->vars[var2].scc < 0) { + var = var2; + goto restart; + } + } + + /* finish visiting */ + zend_worklist_stack_pop(vstack); + if (ssa->vars[var].scc_entry) { + ssa->sccs--; + while (stack->len > 0) { + int var2 = zend_worklist_stack_peek(stack); + if (ssa->vars[var2].scc < ssa->vars[var].scc) { + break; + } + zend_worklist_stack_pop(stack); + ssa->vars[var2].scc = ssa->sccs; + (*index)--; + } + ssa->vars[var].scc = ssa->sccs; + (*index)--; + } else { + zend_worklist_stack_push(stack, var); + } + } +} +/* }}} */ + +ZEND_API int zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */ +{ + int index = 0; + zend_worklist_stack stack, vstack; + zend_scc_iterator *iterators; + int j; + ALLOCA_FLAG(stack_use_heap) + ALLOCA_FLAG(vstack_use_heap) + ALLOCA_FLAG(iterators_use_heap) + + iterators = do_alloca(sizeof(zend_scc_iterator) * ssa->vars_count, iterators_use_heap); + ZEND_WORKLIST_STACK_ALLOCA(&vstack, ssa->vars_count, vstack_use_heap); + ZEND_WORKLIST_STACK_ALLOCA(&stack, ssa->vars_count, stack_use_heap); + + /* Find SCCs using Pearce's algorithm. */ + ssa->sccs = ssa->vars_count; + for (j = 0; j < ssa->vars_count; j++) { + if (!ssa->vars[j].no_val && ssa->vars[j].scc < 0) { + zend_ssa_check_scc_var(op_array, ssa, j, &index, &stack, &vstack, iterators); + } + } + + if (ssa->sccs) { + /* Shift SCC indexes. */ + for (j = 0; j < ssa->vars_count; j++) { + if (ssa->vars[j].scc >= 0) { + ssa->vars[j].scc -= ssa->sccs; + } + } + } + ssa->sccs = ssa->vars_count - ssa->sccs; + for (j = 0; j < ssa->vars_count; j++) { if (ssa->vars[j].scc >= 0) { int var = j; - if (root[j] == j) { - ssa->vars[j].scc_entry = 1; - } FOR_EACH_VAR_USAGE(var, CHECK_SCC_ENTRY); } } ZEND_WORKLIST_STACK_FREE_ALLOCA(&stack, stack_use_heap); - free_alloca(root, root_use_heap); - free_alloca(dfs, dfs_use_heap); - + ZEND_WORKLIST_STACK_FREE_ALLOCA(&vstack, vstack_use_heap); + free_alloca(iterators, iterators_use_heap); return SUCCESS; } /* }}} */ +#endif + ZEND_API int zend_ssa_find_false_dependencies(const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */ { zend_ssa_var *ssa_vars = ssa->vars; From 455a967934f45b0f0a5d5e184a8dd0ed91a18601 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 30 Oct 2023 17:54:30 +0300 Subject: [PATCH 52/66] Backport fix for incorrect assumption about in-memory zval type --- ext/opcache/jit/zend_jit_trace.c | 41 ++++++++++++----------- ext/opcache/tests/jit/assign_dim_017.phpt | 20 +++++++++++ 2 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 ext/opcache/tests/jit/assign_dim_017.phpt diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 0e103c83570a8..4a57986130666 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -4935,14 +4935,11 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par } op2_addr = OP2_REG_ADDR(); op2_info = OP2_INFO(); - if (ra - && ssa_op->op2_def >= 0 - && (!ssa->vars[ssa_op->op2_def].no_val - || (zend_jit_trace_type_to_info(STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->op2.var))) & MAY_BE_ANY) != - (op2_info & MAY_BE_ANY))) { - op2_def_addr = OP2_DEF_REG_ADDR(); - } else { + + if (ssa_op->op2_def < 0 || (Z_MODE(op2_addr) == IS_REG && ssa->vars[ssa_op->op2_def].no_val)) { op2_def_addr = op2_addr; + } else { + op2_def_addr = OP2_DEF_REG_ADDR(); } CHECK_OP2_TRACE_TYPE(); op1_info = OP1_INFO(); @@ -5038,12 +5035,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par ZEND_FALLTHROUGH; case ZEND_QM_ASSIGN: op1_addr = OP1_REG_ADDR(); - if (ra - && ssa_op->op1_def >= 0 - && !ssa->vars[ssa_op->op1_def].no_val) { - op1_def_addr = OP1_DEF_REG_ADDR(); - } else { + if (ssa_op->op1_def < 0 || (Z_MODE(op1_addr) == IS_REG && ssa->vars[ssa_op->op1_def].no_val)) { op1_def_addr = op1_addr; + } else { + op1_def_addr = OP1_DEF_REG_ADDR(); } op1_info = OP1_INFO(); CHECK_OP1_TRACE_TYPE(); @@ -5134,12 +5129,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par break; } op1_addr = OP1_REG_ADDR(); - if (ra - && ssa_op->op1_def >= 0 - && !ssa->vars[ssa_op->op1_def].no_val) { - op1_def_addr = OP1_DEF_REG_ADDR(); - } else { + if (ssa_op->op1_def < 0 || (Z_MODE(op1_addr) == IS_REG && ssa->vars[ssa_op->op1_def].no_val)) { op1_def_addr = op1_addr; + } else { + op1_def_addr = OP1_DEF_REG_ADDR(); } op1_info = OP1_INFO(); CHECK_OP1_TRACE_TYPE(); @@ -6353,7 +6346,14 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var), type, (gen_handler || type == IS_UNKNOWN || !ra || (!ra[ssa_op->op1_def] && - (opline->opcode == ZEND_ASSIGN || !ssa->vars[ssa_op->op1_def].no_val)))); + !(ssa->vars[ssa_op->op1_def].no_val && + Z_MODE(OP1_REG_ADDR()) == IS_REG && + (opline->opcode == ZEND_QM_ASSIGN || + opline->opcode == ZEND_SEND_VAR || + opline->opcode == ZEND_SEND_VAR_EX || + opline->opcode == ZEND_SEND_VAR_NO_REF || + opline->opcode == ZEND_SEND_VAR_NO_REF_EX || + opline->opcode == ZEND_SEND_FUNC_ARG))))); if (type != IS_UNKNOWN) { ssa->var_info[ssa_op->op1_def].type &= ~MAY_BE_GUARD; if (ra && ra[ssa_op->op1_def]) { @@ -6399,7 +6399,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par } SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op2.var), type, (gen_handler || type == IS_UNKNOWN || !ra || - (!ra[ssa_op->op2_def] && !ssa->vars[ssa_op->op2_def].no_val))); + (!ra[ssa_op->op2_def] && + !(ssa->vars[ssa_op->op2_def].no_val && + Z_MODE(OP2_REG_ADDR()) == IS_REG && + opline->opcode == ZEND_ASSIGN)))); if (type != IS_UNKNOWN) { ssa->var_info[ssa_op->op2_def].type &= ~MAY_BE_GUARD; if (ra && ra[ssa_op->op2_def]) { diff --git a/ext/opcache/tests/jit/assign_dim_017.phpt b/ext/opcache/tests/jit/assign_dim_017.phpt new file mode 100644 index 0000000000000..cc5eef1265c59 --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_017.phpt @@ -0,0 +1,20 @@ +--TEST-- +JIT ASSIGN_DIM: 017 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- + +DONE +--EXPECT-- +DONE \ No newline at end of file From d4e40dc0e1dc48533fc42ec167d99f8cad64ae37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Tue, 31 Oct 2023 10:06:56 +0100 Subject: [PATCH 53/66] Fix GH-12558 Escape \N in generated stubs (#12562) --- NEWS | 2 ++ build/gen_stub.php | 6 +++--- ext/zend_test/test.c | 9 +++++++++ ext/zend_test/test.stub.php | 5 +++++ ext/zend_test/test_arginfo.h | 22 +++++++++++++++++++++- ext/zend_test/tests/gen_stub_test_01.phpt | 4 ++++ 6 files changed, 44 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index c1f6557de1003..a09e308174154 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ PHP NEWS property via trait). (ilutov) . Fixed segfault caused by weak references to FFI objects. (sj-i) . Fixed max_execution_time: don't delete an unitialized timer. (Kévin Dunglas) + . Fixed bug GH-12558 (Arginfo soft-breaks with namespaced class return type + if the class name starts with N). (kocsismate) - DOM: . Fix registerNodeClass with abstract class crashing. (nielsdos) diff --git a/build/gen_stub.php b/build/gen_stub.php index 7df5290883691..0c745c8c03068 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -527,10 +527,10 @@ public function toOptimizerTypeMask(): string { } public function toEscapedName(): string { - // Escape backslashes, and also encode \u and \U to avoid compilation errors in generated macros + // Escape backslashes, and also encode \u, \U, and \N to avoid compilation errors in generated macros return str_replace( - ['\\', '\\u', '\\U'], - ['\\\\', '\\\\165', '\\\\125'], + ['\\', '\\u', '\\U', '\\N'], + ['\\\\', '\\\\165', '\\\\125', '\\\\116'], $this->name ); } diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 88b7d5d904eef..4371459a910bd 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -52,6 +52,7 @@ static zend_class_entry *zend_test_child_class_with_method_with_parameter_attrib static zend_class_entry *zend_test_forbid_dynamic_call; static zend_class_entry *zend_test_ns_foo_class; static zend_class_entry *zend_test_ns_unlikely_compile_error_class; +static zend_class_entry *zend_test_ns_not_unlikely_compile_error_class; static zend_class_entry *zend_test_ns2_foo_class; static zend_class_entry *zend_test_ns2_ns_foo_class; static zend_class_entry *zend_test_unit_enum; @@ -636,6 +637,13 @@ static ZEND_METHOD(ZendTestNS_UnlikelyCompileError, method) RETURN_NULL(); } +static ZEND_METHOD(ZendTestNS_NotUnlikelyCompileError, method) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + RETURN_NULL(); +} + static ZEND_METHOD(ZendTestNS2_Foo, method) { ZEND_PARSE_PARAMETERS_NONE(); @@ -818,6 +826,7 @@ PHP_MINIT_FUNCTION(zend_test) zend_test_ns_foo_class = register_class_ZendTestNS_Foo(); zend_test_ns_unlikely_compile_error_class = register_class_ZendTestNS_UnlikelyCompileError(); + zend_test_ns_not_unlikely_compile_error_class = register_class_ZendTestNS_NotUnlikelyCompileError(); zend_test_ns2_foo_class = register_class_ZendTestNS2_Foo(); zend_test_ns2_ns_foo_class = register_class_ZendTestNS2_ZendSubNS_Foo(); diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index 5ebe6b574b666..eaed7e2794aeb 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -190,6 +190,11 @@ class UnlikelyCompileError { public function method(): ?UnlikelyCompileError {} } + class NotUnlikelyCompileError { + /* This method signature would create a compile error due to the string + * "ZendTestNS\NotUnlikelyCompileError" in the generated macro call */ + public function method(): ?NotUnlikelyCompileError {} + } } namespace ZendTestNS2 { diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index 5a3af3879d7d6..72b89ef33342f 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: fa6d8c58bdef20c6c9c8db75dbb6ede775324193 */ + * Stub hash: 37c6d5e5e28a60b3d1cf89c1a2f82a0196fceae7 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -171,6 +171,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ZendTestNS_UnlikelyCompileError_method, 0, 0, ZendTestNS\\\125nlikelyCompileError, 1) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ZendTestNS_NotUnlikelyCompileError_method, 0, 0, ZendTestNS\\\116otUnlikelyCompileError, 1) +ZEND_END_ARG_INFO() + #define arginfo_class_ZendTestNS2_Foo_method arginfo_zend_test_void_return #define arginfo_class_ZendTestNS2_ZendSubNS_Foo_method arginfo_zend_test_void_return @@ -225,6 +228,7 @@ static ZEND_METHOD(ZendTestForbidDynamicCall, call); static ZEND_METHOD(ZendTestForbidDynamicCall, callStatic); static ZEND_METHOD(ZendTestNS_Foo, method); static ZEND_METHOD(ZendTestNS_UnlikelyCompileError, method); +static ZEND_METHOD(ZendTestNS_NotUnlikelyCompileError, method); static ZEND_METHOD(ZendTestNS2_Foo, method); static ZEND_METHOD(ZendTestNS2_ZendSubNS_Foo, method); @@ -364,6 +368,12 @@ static const zend_function_entry class_ZendTestNS_UnlikelyCompileError_methods[] }; +static const zend_function_entry class_ZendTestNS_NotUnlikelyCompileError_methods[] = { + ZEND_ME(ZendTestNS_NotUnlikelyCompileError, method, arginfo_class_ZendTestNS_NotUnlikelyCompileError_method, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + + static const zend_function_entry class_ZendTestNS2_Foo_methods[] = { ZEND_ME(ZendTestNS2_Foo, method, arginfo_class_ZendTestNS2_Foo_method, ZEND_ACC_PUBLIC) ZEND_FE_END @@ -698,6 +708,16 @@ static zend_class_entry *register_class_ZendTestNS_UnlikelyCompileError(void) return class_entry; } +static zend_class_entry *register_class_ZendTestNS_NotUnlikelyCompileError(void) +{ + zend_class_entry ce, *class_entry; + + INIT_NS_CLASS_ENTRY(ce, "ZendTestNS", "NotUnlikelyCompileError", class_ZendTestNS_NotUnlikelyCompileError_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + + return class_entry; +} + static zend_class_entry *register_class_ZendTestNS2_Foo(void) { zend_class_entry ce, *class_entry; diff --git a/ext/zend_test/tests/gen_stub_test_01.phpt b/ext/zend_test/tests/gen_stub_test_01.phpt index 0a020a6f3457c..0f5d525322d62 100644 --- a/ext/zend_test/tests/gen_stub_test_01.phpt +++ b/ext/zend_test/tests/gen_stub_test_01.phpt @@ -11,6 +11,8 @@ $foo->foo = new \ZendTestNS2\ZendSubNS\Foo(); var_dump($foo); $foo = new \ZendTestNS\UnlikelyCompileError(); var_dump($foo); +$foo = new \ZendTestNS\NotUnlikelyCompileError(); +var_dump($foo); ?> --EXPECTF-- object(ZendTestNS2\Foo)#%d (%d) { @@ -24,3 +26,5 @@ object(ZendTestNS2\Foo)#%d (%d) { } object(ZendTestNS\UnlikelyCompileError)#%d (%d) { } +object(ZendTestNS\NotUnlikelyCompileError)#%d (%d) { +} From 0e8205bd9abd681e12db4fed4b47c9490b16f8a2 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 31 Oct 2023 11:48:08 +0100 Subject: [PATCH 54/66] Use attribute for ignoring Laravel test Apparently `@group` stopped working. --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index acc0973f00036..f945ec23c9e3e 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -341,7 +341,7 @@ jobs: git rev-parse HEAD php /usr/bin/composer install --no-progress --ignore-platform-reqs # Hack to disable a test that hangs - php -r '$c = file_get_contents("tests/Filesystem/FilesystemTest.php"); $c = str_replace("public function testSharedGet()", "/** @group skip */\n public function testSharedGet()", $c); file_put_contents("tests/Filesystem/FilesystemTest.php", $c);' + php -r '$c = file_get_contents("tests/Filesystem/FilesystemTest.php"); $c = str_replace("public function testSharedGet()", "#[\\PHPUnit\\Framework\\Attributes\\Group('"'"'skip'"'"')]\n public function testSharedGet()", $c); file_put_contents("tests/Filesystem/FilesystemTest.php", $c);' export ASAN_OPTIONS=exitcode=139 php vendor/bin/phpunit --exclude-group skip || EXIT_CODE=$? if [ $EXIT_CODE -gt 128 ]; then From 19dfe05f16ce3317fe36e41fa7857de59a771cae Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 1 Nov 2023 09:54:58 +0300 Subject: [PATCH 55/66] Fixed inorrect QM_ASSIGN elimination Fixes oss-fuzz #63771 --- Zend/Optimizer/block_pass.c | 1 + ext/opcache/tests/opt/block_pass_006.phpt | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 ext/opcache/tests/opt/block_pass_006.phpt diff --git a/Zend/Optimizer/block_pass.c b/Zend/Optimizer/block_pass.c index 72441c000e660..f0aaeb229351b 100644 --- a/Zend/Optimizer/block_pass.c +++ b/Zend/Optimizer/block_pass.c @@ -172,6 +172,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array && opline->opcode != ZEND_SWITCH_LONG && opline->opcode != ZEND_SWITCH_STRING && opline->opcode != ZEND_MATCH + && opline->opcode != ZEND_MATCH_ERROR && zend_optimizer_update_op1_const(op_array, opline, &c)) { VAR_SOURCE(op1) = NULL; if (opline->opcode != ZEND_JMP_NULL diff --git a/ext/opcache/tests/opt/block_pass_006.phpt b/ext/opcache/tests/opt/block_pass_006.phpt new file mode 100644 index 0000000000000..e70689c65abc1 --- /dev/null +++ b/ext/opcache/tests/opt/block_pass_006.phpt @@ -0,0 +1,15 @@ +--TEST-- +Block Pass 006: Inorrect QM_ASSIGN elimination +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- +''}){} +?> +--EXPECTF-- +Fatal error: Uncaught Error: Undefined constant "c" in %sblock_pass_006.php:2 +Stack trace: +#0 {main} + thrown in %sblock_pass_006.php on line 2 From fe3a819e325e3f468d482c8ad1249de14610e093 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 1 Nov 2023 16:13:17 +0300 Subject: [PATCH 56/66] Fixed GH-12564: The negative fiber.stack_size setting leads to crash --- Zend/tests/fibers/negative_stack_size.phpt | 16 ++++++++++++++++ Zend/zend.c | 7 ++++++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/fibers/negative_stack_size.phpt diff --git a/Zend/tests/fibers/negative_stack_size.phpt b/Zend/tests/fibers/negative_stack_size.phpt new file mode 100644 index 0000000000000..591a8f28878d1 --- /dev/null +++ b/Zend/tests/fibers/negative_stack_size.phpt @@ -0,0 +1,16 @@ +--TEST-- +fiber.stack_size must be a positive number +--FILE-- +start(); +} catch (Throwable $e) { + echo "Exception: " . $e->getMessage()."\n"; +} +?> +DONE +--EXPECTF-- +Warning: fiber.stack_size must be a positive number in %snegative_stack_size.php on line 2 +DONE diff --git a/Zend/zend.c b/Zend/zend.c index 351e9ac5eea75..e6f92410c0881 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -177,7 +177,12 @@ static ZEND_INI_MH(OnSetExceptionStringParamMaxLen) /* {{{ */ static ZEND_INI_MH(OnUpdateFiberStackSize) /* {{{ */ { if (new_value) { - EG(fiber_stack_size) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + zend_long tmp = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + if (tmp < 0) { + zend_error(E_WARNING, "fiber.stack_size must be a positive number"); + return FAILURE; + } + EG(fiber_stack_size) = tmp; } else { EG(fiber_stack_size) = ZEND_FIBER_DEFAULT_C_STACK_SIZE; } From 0da1356c669a1396e02929724a72ee897d48c54c Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 30 Oct 2023 13:42:50 +0000 Subject: [PATCH 57/66] ext/intl: change when the locale is invalid for the 8.1/8.2 serie. does not throws an exception as it's considered as a too string change, but the code user still needs to double check. --- NEWS | 4 ++++ ext/intl/dateformat/dateformat_create.cpp | 3 +-- ext/intl/tests/gh12282.phpt | 15 ++++++++------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/NEWS b/NEWS index 6dac57d6a3baa..119d59b8906c6 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,10 @@ PHP NEWS . Fixed bug GH-12232 (FPM: segfault dynamically loading extension without opcache). (Jakub Zelenka) +- Intl: + . Removed the BC break on IntlDateFormatter::construct which threw an + exception with an invalid locale. (David Carlier) + - Opcache: . Added warning when JIT cannot be enabled. (danog) . Fixed bug GH-8143 (Crashes in zend_accel_inheritance_cache_find since diff --git a/ext/intl/dateformat/dateformat_create.cpp b/ext/intl/dateformat/dateformat_create.cpp index e14eb4f1a2f8a..5c96f41fadf35 100644 --- a/ext/intl/dateformat/dateformat_create.cpp +++ b/ext/intl/dateformat/dateformat_create.cpp @@ -113,8 +113,7 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handlin locale = Locale::createFromName(locale_str); /* get*Name accessors being set does not preclude being bogus */ if (locale.isBogus() || strlen(locale.getISO3Language()) == 0) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: invalid locale", 0); - return FAILURE; + goto error; } /* process calendar */ diff --git a/ext/intl/tests/gh12282.phpt b/ext/intl/tests/gh12282.phpt index 62d090ba6166b..a30899a08c7d0 100644 --- a/ext/intl/tests/gh12282.phpt +++ b/ext/intl/tests/gh12282.phpt @@ -5,17 +5,18 @@ intl --FILE-- getMessage(); -} +)); +Locale::setDefault('xx'); +var_dump(new IntlDateFormatter(Locale::getDefault())); --EXPECT-- -datefmt_create: invalid locale: U_ILLEGAL_ARGUMENT_ERROR +object(IntlDateFormatter)#1 (0) { +} +object(IntlDateFormatter)#1 (0) { +} From 798b9d097b7ca83878983792378a1b9a39800f9d Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 2 Nov 2023 08:09:29 +0300 Subject: [PATCH 58/66] Fixed GH-10008: Narrowing occurred during type inference of ZEND_ADD_ARRAY_ELEMENT --- Zend/Optimizer/zend_inference.c | 3 ++- ext/opcache/tests/opt/gh10008.phpt | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/opt/gh10008.phpt diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 49dd44ff89085..084a7abf9f7a7 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -2530,7 +2530,8 @@ static zend_always_inline int _zend_update_type_info( * unreachable code. Propagate the empty result early, so that that the following * code may assume that operands have at least one type. */ if (!(t1 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_CLASS)) - || !(t2 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_CLASS))) { + || !(t2 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_CLASS)) + || (ssa_op->result_use >= 0 && !(RES_USE_INFO() & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_CLASS)))) { tmp = 0; if (ssa_op->result_def >= 0 && !(ssa_var_info[ssa_op->result_def].type & MAY_BE_REF)) { UPDATE_SSA_TYPE(tmp, ssa_op->result_def); diff --git a/ext/opcache/tests/opt/gh10008.phpt b/ext/opcache/tests/opt/gh10008.phpt new file mode 100644 index 0000000000000..02f6feff9b023 --- /dev/null +++ b/ext/opcache/tests/opt/gh10008.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-10008: Narrowing occurred during type inference of ZEND_ADD_ARRAY_ELEMENT +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--EXTENSIONS-- +opcache +--FILE-- + $bool_or_int, $string_key => 123]; + } + + $bool_or_int = 0; + } +} +?> +DONE +--EXPECT-- +DONE From 77a497d56af17875763994a69917bf8033f77629 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 2 Nov 2023 14:14:12 +0300 Subject: [PATCH 59/66] Don't JIT after fatal errors --- ext/opcache/jit/zend_jit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index d969f744e6b4b..4d2baddb90090 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -5113,7 +5113,7 @@ ZEND_EXT_API void zend_jit_activate(void) ZEND_EXT_API void zend_jit_deactivate(void) { - if (zend_jit_profile_counter) { + if (zend_jit_profile_counter && !CG(unclean_shutdown)) { zend_class_entry *ce; zend_shared_alloc_lock(); @@ -5131,9 +5131,9 @@ ZEND_EXT_API void zend_jit_deactivate(void) zend_jit_protect(); SHM_PROTECT(); zend_shared_alloc_unlock(); - - zend_jit_profile_counter = 0; } + + zend_jit_profile_counter = 0; } static void zend_jit_restart_preloaded_op_array(zend_op_array *op_array) From 20c9c4a367dc9cadb29f7475f1a01b45203e4172 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 2 Nov 2023 01:35:21 +0100 Subject: [PATCH 60/66] Fix validation logic of php:function() callbacks in dom and xsl Two issues: - Assumed that at least 1 argument (function name) was provided. - Incorrect error path for the non-callable case. Closes GH-12593. --- NEWS | 2 + ext/dom/tests/php_function_edge_cases.phpt | 27 +++++++++++++ ext/dom/xpath.c | 11 +++++- ext/xsl/tests/php_function_edge_cases.phpt | 45 ++++++++++++++++++++++ ext/xsl/xsltprocessor.c | 9 ++++- 5 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 ext/dom/tests/php_function_edge_cases.phpt create mode 100644 ext/xsl/tests/php_function_edge_cases.phpt diff --git a/NEWS b/NEWS index 119d59b8906c6..44aac9186672c 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,7 @@ PHP NEWS - DOM: . Fix registerNodeClass with abstract class crashing. (nielsdos) . Add missing NULL pointer error check. (icy17) + . Fix validation logic of php:function() callbacks. (nielsdos) - Fiber: . Fixed bug GH-11121 (ReflectionFiber segfault). (danog, trowski, bwoebi) @@ -60,6 +61,7 @@ PHP NEWS - XSL: . Add missing module dependency. (nielsdos) + . Fix validation logic of php:function() callbacks. (nielsdos) 26 Oct 2023, PHP 8.1.25 diff --git a/ext/dom/tests/php_function_edge_cases.phpt b/ext/dom/tests/php_function_edge_cases.phpt new file mode 100644 index 0000000000000..1091b50ce19bd --- /dev/null +++ b/ext/dom/tests/php_function_edge_cases.phpt @@ -0,0 +1,27 @@ +--TEST-- +php:function() edge cases +--EXTENSIONS-- +dom +--FILE-- +loadHTML('hello'); +$xpath = new DOMXpath($doc); +$xpath->registerNamespace("php", "http://php.net/xpath"); +$xpath->registerPHPFunctions(); +try { + $xpath->query("//a[php:function(3)]"); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + $xpath->query("//a[php:function()]"); +} catch (Throwable $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Handler name must be a string +Function name must be passed as the first argument diff --git a/ext/dom/xpath.c b/ext/dom/xpath.c index 62e11f6b99bfb..73ceb49362781 100644 --- a/ext/dom/xpath.c +++ b/ext/dom/xpath.c @@ -70,12 +70,17 @@ static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, return; } + if (UNEXPECTED(nargs == 0)) { + zend_throw_error(NULL, "Function name must be passed as the first argument"); + return; + } + fci.param_count = nargs - 1; if (fci.param_count > 0) { fci.params = safe_emalloc(fci.param_count, sizeof(zval), 0); } /* Reverse order to pop values off ctxt stack */ - for (i = nargs - 2; i >= 0; i--) { + for (i = fci.param_count - 1; i >= 0; i--) { obj = valuePop(ctxt); switch (obj->type) { case XPATH_STRING: @@ -128,11 +133,12 @@ static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, fci.size = sizeof(fci); + /* Last element of the stack is the function name */ obj = valuePop(ctxt); if (obj->stringval == NULL) { zend_type_error("Handler name must be a string"); xmlXPathFreeObject(obj); - goto cleanup; + goto cleanup_no_callable; } ZVAL_STRING(&fci.function_name, (char *) obj->stringval); xmlXPathFreeObject(obj); @@ -177,6 +183,7 @@ static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, cleanup: zend_string_release_ex(callable, 0); zval_ptr_dtor_nogc(&fci.function_name); +cleanup_no_callable: if (fci.param_count > 0) { for (i = 0; i < nargs - 1; i++) { zval_ptr_dtor(&fci.params[i]); diff --git a/ext/xsl/tests/php_function_edge_cases.phpt b/ext/xsl/tests/php_function_edge_cases.phpt new file mode 100644 index 0000000000000..23a06b111bb50 --- /dev/null +++ b/ext/xsl/tests/php_function_edge_cases.phpt @@ -0,0 +1,45 @@ +--TEST-- +php:function() edge cases +--EXTENSIONS-- +xsl +--FILE-- +loadXML(' + + + + + '); + + $inputdom = new DomDocument(); + $inputdom->loadXML(' + '); + + $proc = new XsltProcessor(); + $proc->registerPhpFunctions(); + $xsl = $proc->importStylesheet($xsl); + try { + $proc->transformToDoc($inputdom); + } catch (Exception $e) { + echo $e->getMessage(), "\n"; + } +} + +try { + test(""); +} catch (Throwable $e) { + echo $e->getMessage(), "\n"; +} + +test("3"); + +?> +--EXPECTF-- +Function name must be passed as the first argument + +Warning: XSLTProcessor::transformToDoc(): Handler name must be a string in %s on line %d diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c index 0ddef864f050f..22d56c41faebc 100644 --- a/ext/xsl/xsltprocessor.c +++ b/ext/xsl/xsltprocessor.c @@ -141,12 +141,17 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t return; } + if (UNEXPECTED(nargs == 0)) { + zend_throw_error(NULL, "Function name must be passed as the first argument"); + return; + } + fci.param_count = nargs - 1; if (fci.param_count > 0) { args = safe_emalloc(fci.param_count, sizeof(zval), 0); } /* Reverse order to pop values off ctxt stack */ - for (i = nargs - 2; i >= 0; i--) { + for (i = fci.param_count - 1; i >= 0; i--) { obj = valuePop(ctxt); if (obj == NULL) { ZVAL_NULL(&args[i]); @@ -221,7 +226,7 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t fci.params = NULL; } - + /* Last element of the stack is the function name */ obj = valuePop(ctxt); if (obj == NULL || obj->stringval == NULL) { php_error_docref(NULL, E_WARNING, "Handler name must be a string"); From 6bf40413989098029067c5219b787ac40720ed98 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 2 Nov 2023 16:17:31 +0300 Subject: [PATCH 61/66] Backport fix for HASH/PACKED array inference through MAY_BE_ARRAY_EMPTY flag (#12591) * Fixed HASH/PACKED array inference through MAY_BE_ARRAY_EMPTY flag This fixes GH-12527 * typo --- Zend/Optimizer/ssa_integrity.c | 4 ++-- Zend/Optimizer/zend_dump.c | 33 +++++++++++++++++++++--------- Zend/Optimizer/zend_func_info.c | 11 +++++++--- Zend/Optimizer/zend_inference.c | 32 +++++++++++++++++++---------- Zend/Optimizer/zend_inference.h | 1 - Zend/zend_type_info.h | 8 +++++--- ext/opcache/tests/jit/gh12527.phpt | 28 +++++++++++++++++++++++++ 7 files changed, 87 insertions(+), 30 deletions(-) create mode 100644 ext/opcache/tests/jit/gh12527.phpt diff --git a/Zend/Optimizer/ssa_integrity.c b/Zend/Optimizer/ssa_integrity.c index 779edd2934843..321041d241834 100644 --- a/Zend/Optimizer/ssa_integrity.c +++ b/Zend/Optimizer/ssa_integrity.c @@ -170,10 +170,10 @@ void ssa_verify_integrity(zend_op_array *op_array, zend_ssa *ssa, const char *ex } } FOREACH_PHI_USE_END(); - if ((type & MAY_BE_ARRAY_KEY_ANY) && !(type & MAY_BE_ARRAY_OF_ANY)) { + if ((type & (MAY_BE_ARRAY_KEY_ANY-MAY_BE_ARRAY_EMPTY)) && !(type & MAY_BE_ARRAY_OF_ANY)) { FAIL("var " VARFMT " has array key type but not value type\n", VAR(i)); } - if ((type & MAY_BE_ARRAY_OF_ANY) && !(type & MAY_BE_ARRAY_KEY_ANY)) { + if ((type & MAY_BE_ARRAY_OF_ANY) && !(type & (MAY_BE_ARRAY_KEY_ANY-MAY_BE_ARRAY_EMPTY))) { FAIL("var " VARFMT " has array value type but not key type\n", VAR(i)); } if ((type & MAY_BE_REF) && ssa->var_info[i].ce) { diff --git a/Zend/Optimizer/zend_dump.c b/Zend/Optimizer/zend_dump.c index 41146bdad97ec..d62f7caef2c22 100644 --- a/Zend/Optimizer/zend_dump.c +++ b/Zend/Optimizer/zend_dump.c @@ -239,21 +239,34 @@ static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_inst } if (info & MAY_BE_ARRAY) { if (first) first = 0; else fprintf(stderr, ", "); - if (!(info & MAY_BE_ARRAY_KEY_STRING) || (info & MAY_BE_PACKED_GUARD)) { - if (MAY_BE_PACKED_ONLY(info)) { - if (info & MAY_BE_PACKED_GUARD) { - fprintf(stderr, "!"); - } + if (info & MAY_BE_PACKED_GUARD) { + fprintf(stderr, "!"); + } + if (MAY_BE_EMPTY_ONLY(info)) { + fprintf(stderr, "empty "); + } else if (MAY_BE_PACKED_ONLY(info)) { + fprintf(stderr, "packed "); + } else if (MAY_BE_HASH_ONLY(info)) { + fprintf(stderr, "hash "); + } else if ((info & MAY_BE_ARRAY_KEY_ANY) != MAY_BE_ARRAY_KEY_ANY && (info & MAY_BE_ARRAY_KEY_ANY) != 0) { + bool afirst = 1; + fprintf(stderr, "["); + if (info & MAY_BE_ARRAY_EMPTY) { + if (afirst) afirst = 0; else fprintf(stderr, ", "); + fprintf(stderr, "empty "); + } + if (MAY_BE_PACKED(info)) { + if (afirst) afirst = 0; else fprintf(stderr, ", "); fprintf(stderr, "packed "); - } else if (MAY_BE_HASH_ONLY(info)) { - if (info & MAY_BE_PACKED_GUARD) { - fprintf(stderr, "!"); - } + } + if (MAY_BE_HASH(info)) { + if (afirst) afirst = 0; else fprintf(stderr, ", "); fprintf(stderr, "hash "); } + fprintf(stderr, "] "); } fprintf(stderr, "array"); - if ((info & MAY_BE_ARRAY_KEY_ANY) != 0 && + if ((info & (MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING)) != 0 && ((info & MAY_BE_ARRAY_KEY_LONG) == 0 || (info & MAY_BE_ARRAY_KEY_STRING) == 0)) { bool afirst = 1; diff --git a/Zend/Optimizer/zend_func_info.c b/Zend/Optimizer/zend_func_info.c index f125f4956b11e..e2c746bbf539c 100644 --- a/Zend/Optimizer/zend_func_info.c +++ b/Zend/Optimizer/zend_func_info.c @@ -61,7 +61,7 @@ static uint32_t zend_range_info(const zend_call_info *call_info, const zend_ssa uint32_t t2 = _ssa_op1_info(op_array, ssa, call_info->arg_info[1].opline, &ssa->ops[call_info->arg_info[1].opline - op_array->opcodes]); uint32_t t3 = 0; - uint32_t tmp = MAY_BE_RC1 | MAY_BE_ARRAY; + uint32_t tmp = MAY_BE_RC1 | MAY_BE_ARRAY | MAY_BE_ARRAY_EMPTY; if (call_info->num_args == 3) { t3 = _ssa_op1_info(op_array, ssa, call_info->arg_info[2].opline, @@ -87,7 +87,7 @@ static uint32_t zend_range_info(const zend_call_info *call_info, const zend_ssa return tmp; } else { /* May throw */ - return MAY_BE_RC1 | MAY_BE_ARRAY | MAY_BE_ARRAY_PACKED | MAY_BE_ARRAY_OF_LONG | MAY_BE_ARRAY_OF_DOUBLE | MAY_BE_ARRAY_OF_STRING; + return MAY_BE_RC1 | MAY_BE_ARRAY | MAY_BE_ARRAY_EMPTY | MAY_BE_ARRAY_PACKED | MAY_BE_ARRAY_OF_LONG | MAY_BE_ARRAY_OF_DOUBLE | MAY_BE_ARRAY_OF_STRING; } } @@ -120,7 +120,12 @@ uint32_t zend_get_internal_func_info( if (info->info_func) { return call_info ? info->info_func(call_info, ssa) : 0; } else { - return info->info; + uint32_t ret = info->info; + + if (ret & MAY_BE_ARRAY) { + ret |= MAY_BE_ARRAY_EMPTY; + } + return ret; } } diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index ffbcd19e9d580..794f630ac920c 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -2105,16 +2105,22 @@ ZEND_API uint32_t ZEND_FASTCALL zend_array_type_info(const zval *zv) tmp |= MAY_BE_RCN; } - ZEND_HASH_FOREACH_STR_KEY_VAL(ht, str, val) { - if (str) { - tmp |= MAY_BE_ARRAY_KEY_STRING; - } else { - tmp |= MAY_BE_ARRAY_KEY_LONG; - } - tmp |= 1 << (Z_TYPE_P(val) + MAY_BE_ARRAY_SHIFT); - } ZEND_HASH_FOREACH_END(); - if (HT_IS_PACKED(ht)) { - tmp &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH); + if (zend_hash_num_elements(ht) == 0) { + tmp |= MAY_BE_ARRAY_EMPTY; + } else if (HT_IS_PACKED(ht)) { + tmp |= MAY_BE_ARRAY_PACKED; + ZEND_HASH_PACKED_FOREACH_VAL(ht, val) { + tmp |= 1 << (Z_TYPE_P(val) + MAY_BE_ARRAY_SHIFT); + } ZEND_HASH_FOREACH_END(); + } else { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(ht, str, val) { + if (str) { + tmp |= MAY_BE_ARRAY_STRING_HASH; + } else { + tmp |= MAY_BE_ARRAY_NUMERIC_HASH; + } + tmp |= 1 << (Z_TYPE_P(val) + MAY_BE_ARRAY_SHIFT); + } ZEND_HASH_FOREACH_END(); } return tmp; } @@ -2222,6 +2228,7 @@ static uint32_t assign_dim_array_result_type( if (tmp & MAY_BE_ARRAY_KEY_ANY) { tmp |= (value_type & MAY_BE_ANY) << MAY_BE_ARRAY_SHIFT; } + tmp &= ~MAY_BE_ARRAY_EMPTY; return tmp; } @@ -3656,6 +3663,9 @@ static zend_always_inline zend_result _zend_update_type_info( break; } } + if (opline->opcode != ZEND_FETCH_DIM_FUNC_ARG) { + tmp &= ~MAY_BE_ARRAY_EMPTY; + } } if (((tmp & MAY_BE_ARRAY) && (tmp & MAY_BE_ARRAY_KEY_ANY)) || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG @@ -3829,7 +3839,7 @@ static zend_always_inline zend_result _zend_update_type_info( UPDATE_SSA_TYPE(MAY_BE_LONG, ssa_op->result_def); break; case ZEND_FUNC_GET_ARGS: - UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN| MAY_BE_ARRAY | MAY_BE_ARRAY_PACKED | MAY_BE_ARRAY_OF_ANY, ssa_op->result_def); + UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ARRAY|MAY_BE_ARRAY_EMPTY|MAY_BE_ARRAY_PACKED|MAY_BE_ARRAY_OF_ANY, ssa_op->result_def); break; case ZEND_GET_CLASS: case ZEND_GET_CALLED_CLASS: diff --git a/Zend/Optimizer/zend_inference.h b/Zend/Optimizer/zend_inference.h index 42dcd50920a5e..20e0e6d9ddb41 100644 --- a/Zend/Optimizer/zend_inference.h +++ b/Zend/Optimizer/zend_inference.h @@ -29,7 +29,6 @@ #define MAY_BE_PACKED_GUARD (1<<27) /* needs packed array guard */ #define MAY_BE_CLASS_GUARD (1<<27) /* needs class guard */ #define MAY_BE_GUARD (1<<28) /* needs type guard */ -//#define MAY_BE_IN_REG (1<<29) /* deprecated and not used */ #define MAY_HAVE_DTOR \ (MAY_BE_OBJECT|MAY_BE_RESOURCE \ diff --git a/Zend/zend_type_info.h b/Zend/zend_type_info.h index f9780181a4c67..eeab7bf0431da 100644 --- a/Zend/zend_type_info.h +++ b/Zend/zend_type_info.h @@ -59,15 +59,17 @@ #define MAY_BE_ARRAY_PACKED (1<<21) #define MAY_BE_ARRAY_NUMERIC_HASH (1<<22) /* hash with numeric keys */ #define MAY_BE_ARRAY_STRING_HASH (1<<23) /* hash with string keys */ +#define MAY_BE_ARRAY_EMPTY (1<<29) #define MAY_BE_ARRAY_KEY_LONG (MAY_BE_ARRAY_PACKED | MAY_BE_ARRAY_NUMERIC_HASH) #define MAY_BE_ARRAY_KEY_STRING MAY_BE_ARRAY_STRING_HASH -#define MAY_BE_ARRAY_KEY_ANY (MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_KEY_STRING) +#define MAY_BE_ARRAY_KEY_ANY (MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_KEY_STRING | MAY_BE_ARRAY_EMPTY) #define MAY_BE_PACKED(t) ((t) & MAY_BE_ARRAY_PACKED) #define MAY_BE_HASH(t) ((t) & (MAY_BE_ARRAY_NUMERIC_HASH | MAY_BE_ARRAY_KEY_STRING)) -#define MAY_BE_PACKED_ONLY(t) (MAY_BE_PACKED(t) && !MAY_BE_HASH(t)) -#define MAY_BE_HASH_ONLY(t) (MAY_BE_HASH(t) && !MAY_BE_PACKED(t)) +#define MAY_BE_PACKED_ONLY(t) (((t) & MAY_BE_ARRAY_KEY_ANY) == MAY_BE_ARRAY_PACKED) +#define MAY_BE_HASH_ONLY(t) (MAY_BE_HASH(t) && !((t) & (MAY_BE_ARRAY_PACKED|MAY_BE_ARRAY_EMPTY))) +#define MAY_BE_EMPTY_ONLY(t) (((t) & MAY_BE_ARRAY_KEY_ANY) == MAY_BE_ARRAY_EMPTY) #define MAY_BE_CLASS (1<<24) #define MAY_BE_INDIRECT (1<<25) diff --git a/ext/opcache/tests/jit/gh12527.phpt b/ext/opcache/tests/jit/gh12527.phpt new file mode 100644 index 0000000000000..31ccba485364a --- /dev/null +++ b/ext/opcache/tests/jit/gh12527.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-12527: Incorrect hash/packed inference +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- + $val) { + if (!$val) { + $a2["bad"][] = $key; + } else { + $a2[0][] = $key; + } + } + foreach ($a2 as $key => $val) { + var_dump($key); + } +} +foo([1, 2, 3]); +foo([1, 2, 3]); +foo([0, 0]); +?> +--EXPECT-- +int(0) +int(0) +string(3) "bad" From 7e5fb564d6d71522709f073607d59fc9c64a39a3 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 3 Nov 2023 01:03:50 +0300 Subject: [PATCH 62/66] Remove spaces --- Zend/Optimizer/zend_dump.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Zend/Optimizer/zend_dump.c b/Zend/Optimizer/zend_dump.c index d62f7caef2c22..12d7101e805ed 100644 --- a/Zend/Optimizer/zend_dump.c +++ b/Zend/Optimizer/zend_dump.c @@ -253,15 +253,15 @@ static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_inst fprintf(stderr, "["); if (info & MAY_BE_ARRAY_EMPTY) { if (afirst) afirst = 0; else fprintf(stderr, ", "); - fprintf(stderr, "empty "); + fprintf(stderr, "empty"); } if (MAY_BE_PACKED(info)) { if (afirst) afirst = 0; else fprintf(stderr, ", "); - fprintf(stderr, "packed "); + fprintf(stderr, "packed"); } if (MAY_BE_HASH(info)) { if (afirst) afirst = 0; else fprintf(stderr, ", "); - fprintf(stderr, "hash "); + fprintf(stderr, "hash"); } fprintf(stderr, "] "); } From e3d1beb0f18255cf1965d69b7456907c643aa9ff Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sun, 8 Oct 2023 22:21:31 +0100 Subject: [PATCH 63/66] Fix bug #76922: FastCGI terminates conn after FCGI_GET_VALUES Closes GH-12387 --- NEWS | 2 + main/fastcgi.c | 7 +- .../tests/bug76922-fcgi-get-value-conn.phpt | 43 ++++++++++ sapi/fpm/tests/fcgi.inc | 10 +-- sapi/fpm/tests/response.inc | 86 +++++++++++++++++++ sapi/fpm/tests/tester.inc | 32 +++++++ 6 files changed, 172 insertions(+), 8 deletions(-) create mode 100644 sapi/fpm/tests/bug76922-fcgi-get-value-conn.phpt diff --git a/NEWS b/NEWS index 2aec5ad5ad9ae..1679aa01621a6 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,8 @@ PHP NEWS - FPM: . Fixed bug GH-12232 (FPM: segfault dynamically loading extension without opcache). (Jakub Zelenka) + . Fixed bug #76922 (FastCGI terminates conn after FCGI_GET_VALUES). + (Jakub Zelenka) - Intl: . Removed the BC break on IntlDateFormatter::construct which threw an diff --git a/main/fastcgi.c b/main/fastcgi.c index a77491f1bf23d..df309df9fdc70 100644 --- a/main/fastcgi.c +++ b/main/fastcgi.c @@ -1202,7 +1202,7 @@ static int fcgi_read_request(fcgi_request *req) req->keep = 0; return 0; } - return 0; + return 2; } else { return 0; } @@ -1470,7 +1470,8 @@ int fcgi_accept_request(fcgi_request *req) return -1; } req->hook.on_read(); - if (fcgi_read_request(req)) { + int read_result = fcgi_read_request(req); + if (read_result == 1) { #ifdef _WIN32 if (is_impersonate && !req->tcp) { pipe = (HANDLE)_get_osfhandle(req->fd); @@ -1481,7 +1482,7 @@ int fcgi_accept_request(fcgi_request *req) } #endif return req->fd; - } else { + } else if (read_result == 0) { fcgi_close(req, 1, 1); } } diff --git a/sapi/fpm/tests/bug76922-fcgi-get-value-conn.phpt b/sapi/fpm/tests/bug76922-fcgi-get-value-conn.phpt new file mode 100644 index 0000000000000..20d3dd7b815c8 --- /dev/null +++ b/sapi/fpm/tests/bug76922-fcgi-get-value-conn.phpt @@ -0,0 +1,43 @@ +--TEST-- +FPM: bug76922 - FCGI conn termination after FCGI_GET_VALUES +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$tester->requestValues(connKeepAlive: true)->expectValue('FCGI_MPXS_CONNS', '0'); +$tester->request(connKeepAlive: true)->expectBody('1'); +$tester->requestValues(connKeepAlive: true)->expectValue('FCGI_MPXS_CONNS', '0'); +$tester->terminate(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + +_sock, $this->buildPacket(self::GET_VALUES, $request, 0)); $resp = $this->readPacket(); - if ($resp['type'] == self::GET_VALUES_RESULT) { - return $this->readNvpair($resp['content'], $resp['length']); + if (isset($resp['type']) && $resp['type'] == self::GET_VALUES_RESULT) { + return $this->readNvpair($resp['content'], $resp['contentLength']); } else { throw new \Exception('Unexpected response type, expecting GET_VALUES_RESULT'); } diff --git a/sapi/fpm/tests/response.inc b/sapi/fpm/tests/response.inc index cd5e19d708c52..29105caaffd99 100644 --- a/sapi/fpm/tests/response.inc +++ b/sapi/fpm/tests/response.inc @@ -434,3 +434,89 @@ class Response return false; } } + +class ValuesResponse +{ + /** + * @var array + */ + private array $values; + + /** + * @param string|array|null $values + */ + public function __construct($values = null) + { + if ( ! is_array($values)) { + if ( ! is_null($values) ) { + $this->error('Invalid values supplied', true); + } + $this->values = []; + } else { + $this->values = $values; + } + } + + /** + * Expect value. + * + * @param string $name + * @param mixed $value + * @return ValuesResponse + */ + public function expectValue(string $name, $value = null) + { + if ( ! isset($this->values[$name])) { + return $this->error("Value $name not found in values"); + } + if ( ! is_null($value) && $value !== $this->values[$name]) { + return $this->error("Value $name is {$this->values[$name]} but expected $value"); + } + return $this; + } + + /** + * Get values. + * + * @return array + */ + public function getValues() + { + return $this->values; + } + + /** + * Debug output data. + * + * @return ValuesResponse + */ + public function debugOutput() + { + echo ">>> ValuesResponse\n"; + echo "----------------- Values -----------------\n"; + var_dump($this->values); + echo "---------------------------------------\n\n"; + + return $this; + } + + /** + * Emit error message + * + * @param string $message + * @param bool $throw + * + * @return ValuesResponse + */ + private function error(string $message, $throw = false): bool + { + $errorMessage = "ERROR: $message\n"; + if ($throw) { + throw new \Exception($errorMessage); + } + $this->debugOutput(); + echo $errorMessage; + + return $this; + } +} diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc index 9c9f6b58653d3..e97a44bdbd7bf 100644 --- a/sapi/fpm/tests/tester.inc +++ b/sapi/fpm/tests/tester.inc @@ -868,6 +868,38 @@ class Tester } } + /** + * Execute request for getting FastCGI values. + * + * @param string|null $address + * @param bool $connKeepAlive + * + * @return ValuesResponse + * @throws \Exception + */ + public function requestValues( + string $address = null, + bool $connKeepAlive = false + ): ValuesResponse { + if ($this->hasError()) { + return new Response(null, true); + } + + try { + $valueResponse = new ValuesResponse( + $this->getClient($address, $connKeepAlive)->getValues(['FCGI_MPXS_CONNS']) + ); + if ($this->debug) { + $this->response->debugOutput(); + } + } catch (\Exception $exception) { + $this->error("Request for getting values failed", $exception); + $valueResponse = new ValuesResponse(); + } + + return $valueResponse; + } + /** * Get client. * From a8c6c6165b9c470577cab3db2a9ae3625cf17a84 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sat, 7 Oct 2023 13:59:40 +0100 Subject: [PATCH 64/66] Fix GH-9921: Loading ext in FPM config does not register module handlers Closes GH-12377 --- NEWS | 2 + Zend/zend_API.c | 8 ++- ext/dl_test/dl_test.c | 25 ++++++++- sapi/fpm/fpm/fpm_php.c | 31 ++++++++--- .../gh9921-php-value-ext-mod-handlers.phpt | 54 +++++++++++++++++++ 5 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 sapi/fpm/tests/gh9921-php-value-ext-mod-handlers.phpt diff --git a/NEWS b/NEWS index 44aac9186672c..ba16baf5930f0 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,8 @@ PHP NEWS . Fixed bug GH-11121 (ReflectionFiber segfault). (danog, trowski, bwoebi) - FPM: + . Fixed bug GH-9921 (Loading ext in FPM config does not register module + handlers). (Jakub Zelenka) . Fixed bug GH-12232 (FPM: segfault dynamically loading extension without opcache). (Jakub Zelenka) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 5e89c91828683..5fd38a25c8b78 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2271,7 +2271,8 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */ post_deactivate_count++; } } ZEND_HASH_FOREACH_END(); - module_request_startup_handlers = (zend_module_entry**)malloc( + module_request_startup_handlers = (zend_module_entry**)realloc( + module_request_startup_handlers, sizeof(zend_module_entry*) * (startup_count + 1 + shutdown_count + 1 + @@ -2303,7 +2304,8 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */ } } ZEND_HASH_FOREACH_END(); - class_cleanup_handlers = (zend_class_entry**)malloc( + class_cleanup_handlers = (zend_class_entry**)realloc( + class_cleanup_handlers, sizeof(zend_class_entry*) * (class_count + 1)); class_cleanup_handlers[class_count] = NULL; @@ -2329,7 +2331,9 @@ ZEND_API void zend_startup_modules(void) /* {{{ */ ZEND_API void zend_destroy_modules(void) /* {{{ */ { free(class_cleanup_handlers); + class_cleanup_handlers = NULL; free(module_request_startup_handlers); + module_request_startup_handlers = NULL; zend_hash_graceful_reverse_destroy(&module_registry); } /* }}} */ diff --git a/ext/dl_test/dl_test.c b/ext/dl_test/dl_test.c index 88a298b0ec88a..fed881b2e994c 100644 --- a/ext/dl_test/dl_test.c +++ b/ext/dl_test/dl_test.c @@ -69,6 +69,10 @@ PHP_MINIT_FUNCTION(dl_test) REGISTER_INI_ENTRIES(); } + if (getenv("PHP_DL_TEST_MODULE_DEBUG")) { + fprintf(stderr, "DL TEST MINIT\n"); + } + return SUCCESS; } /* }}} */ @@ -83,6 +87,10 @@ static PHP_MSHUTDOWN_FUNCTION(dl_test) UNREGISTER_INI_ENTRIES(); } + if (getenv("PHP_DL_TEST_MODULE_DEBUG")) { + fprintf(stderr, "DL TEST MSHUTDOWN\n"); + } + return SUCCESS; } /* }}} */ @@ -94,6 +102,21 @@ PHP_RINIT_FUNCTION(dl_test) ZEND_TSRMLS_CACHE_UPDATE(); #endif + if (getenv("PHP_DL_TEST_MODULE_DEBUG")) { + fprintf(stderr, "DL TEST RINIT\n"); + } + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_RSHUTDOWN_FUNCTION */ +PHP_RSHUTDOWN_FUNCTION(dl_test) +{ + if (getenv("PHP_DL_TEST_MODULE_DEBUG")) { + fprintf(stderr, "DL TEST RSHUTDOWN\n"); + } + return SUCCESS; } /* }}} */ @@ -127,7 +150,7 @@ zend_module_entry dl_test_module_entry = { PHP_MINIT(dl_test), PHP_MSHUTDOWN(dl_test), PHP_RINIT(dl_test), - NULL, + PHP_RSHUTDOWN(dl_test), PHP_MINFO(dl_test), PHP_DL_TEST_VERSION, PHP_MODULE_GLOBALS(dl_test), diff --git a/sapi/fpm/fpm/fpm_php.c b/sapi/fpm/fpm/fpm_php.c index a9ad0433ba4dd..dae98bdfc08f9 100644 --- a/sapi/fpm/fpm/fpm_php.c +++ b/sapi/fpm/fpm/fpm_php.c @@ -77,6 +77,11 @@ static void fpm_php_disable(char *value, int (*zend_disable)(const char *, size_ } /* }}} */ +#define FPM_PHP_INI_ALTERING_ERROR -1 +#define FPM_PHP_INI_APPLIED 1 +#define FPM_PHP_INI_EXTENSION_FAILED 0 +#define FPM_PHP_INI_EXTENSION_LOADED 2 + int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode) /* {{{ */ { @@ -90,45 +95,57 @@ int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode) /* {{{ */ zend_interned_strings_switch_storage(0); php_dl(value, MODULE_PERSISTENT, &zv, 1); zend_interned_strings_switch_storage(1); - return Z_TYPE(zv) == IS_TRUE; + return Z_TYPE(zv) == IS_TRUE ? FPM_PHP_INI_EXTENSION_LOADED : FPM_PHP_INI_EXTENSION_FAILED; } if (fpm_php_zend_ini_alter_master(name, name_len, value, value_len, mode, PHP_INI_STAGE_ACTIVATE) == FAILURE) { - return -1; + return FPM_PHP_INI_ALTERING_ERROR; } if (!strcmp(name, "disable_functions") && *value) { zend_disable_functions(value); - return 1; + return FPM_PHP_INI_APPLIED; } if (!strcmp(name, "disable_classes") && *value) { char *v = strdup(value); PG(disable_classes) = v; fpm_php_disable(v, zend_disable_class); - return 1; + return FPM_PHP_INI_APPLIED; } - return 1; + return FPM_PHP_INI_APPLIED; } /* }}} */ static int fpm_php_apply_defines(struct fpm_worker_pool_s *wp) /* {{{ */ { struct key_value_s *kv; + int apply_result; + bool extension_loaded = false; for (kv = wp->config->php_values; kv; kv = kv->next) { - if (fpm_php_apply_defines_ex(kv, ZEND_INI_USER) == -1) { + apply_result = fpm_php_apply_defines_ex(kv, ZEND_INI_USER); + if (apply_result == FPM_PHP_INI_ALTERING_ERROR) { zlog(ZLOG_ERROR, "Unable to set php_value '%s'", kv->key); + } else if (apply_result == FPM_PHP_INI_EXTENSION_LOADED) { + extension_loaded = true; } } for (kv = wp->config->php_admin_values; kv; kv = kv->next) { - if (fpm_php_apply_defines_ex(kv, ZEND_INI_SYSTEM) == -1) { + apply_result = fpm_php_apply_defines_ex(kv, ZEND_INI_SYSTEM); + if (apply_result == FPM_PHP_INI_ALTERING_ERROR) { zlog(ZLOG_ERROR, "Unable to set php_admin_value '%s'", kv->key); + } else if (apply_result == FPM_PHP_INI_EXTENSION_LOADED) { + extension_loaded = true; } } + if (extension_loaded) { + zend_collect_module_handlers(); + } + return 0; } /* }}} */ diff --git a/sapi/fpm/tests/gh9921-php-value-ext-mod-handlers.phpt b/sapi/fpm/tests/gh9921-php-value-ext-mod-handlers.phpt new file mode 100644 index 0000000000000..a7057373fdf90 --- /dev/null +++ b/sapi/fpm/tests/gh9921-php-value-ext-mod-handlers.phpt @@ -0,0 +1,54 @@ +--TEST-- +FPM: GH-9921 - loading shared ext in FPM config does not register module handlers +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$tester->request()->expectBody('bool(true)'); +$tester->expectLogPattern('/DL TEST MINIT/'); +$tester->expectLogPattern('/DL TEST RINIT/'); +$tester->expectLogPattern('/DL TEST RSHUTDOWN/'); +$tester->request()->expectBody('bool(true)'); +$tester->expectLogPattern('/DL TEST RINIT/'); +$tester->expectLogPattern('/DL TEST RSHUTDOWN/'); +$tester->terminate(); +$tester->expectLogTerminatingNotices(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + + Date: Sun, 5 Nov 2023 01:27:22 +0100 Subject: [PATCH 65/66] Fix unspecified behaviour in zend_alloc in heap->limit computation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Right-shifting a negative number is unspecified (i.e. implementation-defined) behaviour [1]. If we take a look at the generated assembly [2], we see that the wrong value is computed. Fix it by using Z_UL instead of Z_L. While we're at it, just change every occurrence of this pattern to use Z_UL instead of casting. [1] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf §6.5.7.5 [2] https://godbolt.org/z/4Y1qKKjsh Closes GH-12613. --- Zend/zend_alloc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 7fd41f3b1ab96..c41f6118607e2 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -1914,7 +1914,7 @@ static zend_mm_heap *zend_mm_init(void) heap->peak = 0; #endif #if ZEND_MM_LIMIT - heap->limit = ((size_t)Z_L(-1) >> (size_t)Z_L(1)); + heap->limit = (size_t)Z_L(-1) >> 1; heap->overflow = 0; #endif #if ZEND_MM_CUSTOM @@ -2859,7 +2859,7 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals) zend_mm_heap *mm_heap = alloc_globals->mm_heap = malloc(sizeof(zend_mm_heap)); memset(mm_heap, 0, sizeof(zend_mm_heap)); mm_heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_STD; - mm_heap->limit = ((size_t)Z_L(-1) >> (size_t)Z_L(1)); + mm_heap->limit = (size_t)Z_L(-1) >> 1; mm_heap->overflow = 0; if (!tracked) { @@ -3048,7 +3048,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void heap->peak = 0; #endif #if ZEND_MM_LIMIT - heap->limit = (Z_L(-1) >> Z_L(1)); + heap->limit = (size_t)Z_L(-1) >> 1; heap->overflow = 0; #endif #if ZEND_MM_CUSTOM From f1e88dfa82271aaaf0244f5156a3fe3cb1caaedc Mon Sep 17 00:00:00 2001 From: Sergey Panteleev Date: Tue, 21 Nov 2023 12:47:00 +0300 Subject: [PATCH 66/66] Update versions for PHP 8.2.13 --- NEWS | 2 +- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index aec27dd8614fe..5ed4df9be10ab 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.2.13 +23 Nov 2023, PHP 8.2.13 - Core: . Fixed double-free of non-interned enum case name. (ilutov) diff --git a/Zend/zend.h b/Zend/zend.h index 4ae4b2d8f0670..c6836bfddc999 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.2.13-dev" +#define ZEND_VERSION "4.2.13" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index c8521f8f04133..18a4644218255 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.2.13-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.2.13],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 41359e73d4d12..b5c4552406c00 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -3,6 +3,6 @@ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 2 #define PHP_RELEASE_VERSION 13 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.2.13-dev" +#define PHP_EXTRA_VERSION "" +#define PHP_VERSION "8.2.13" #define PHP_VERSION_ID 80213