From 902d39d57cd4451f7b8a23d55452ce8dbb4d7259 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 14 Aug 2023 11:38:59 +0200 Subject: [PATCH 01/11] Use per-branch matrix for windows nightly I forgot this in the last PR. --- .github/nightly_matrix.php | 21 +++++++++++++++++++++ .github/workflows/nightly.yml | 15 +++++++-------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/.github/nightly_matrix.php b/.github/nightly_matrix.php index fdd5860f53923..868ecb41375c5 100644 --- a/.github/nightly_matrix.php +++ b/.github/nightly_matrix.php @@ -78,6 +78,25 @@ function get_matrix_include(array $branches) { return $jobs; } +function get_windows_matrix_include(array $branches) { + $jobs = []; + foreach ($branches as $branch) { + $jobs[] = [ + 'branch' => $branch, + 'x64' => true, + 'zts' => true, + 'opcache' => true, + ]; + $jobs[] = [ + 'branch' => $branch, + 'x64' => false, + 'zts' => false, + 'opcache' => false, + ]; + } + return $jobs; +} + $trigger = $argv[1] ?? 'schedule'; $attempt = (int) ($argv[2] ?? 1); $discard_cache = ($trigger === 'schedule' && $attempt !== 1) || $trigger === 'workflow_dispatch'; @@ -87,6 +106,8 @@ function get_matrix_include(array $branches) { $branches = get_branches(); $matrix_include = get_matrix_include($branches); +$windows_matrix_include = get_windows_matrix_include($branches); echo '::set-output name=branches::' . json_encode($branches, JSON_UNESCAPED_SLASHES) . "\n"; echo '::set-output name=matrix-include::' . json_encode($matrix_include, JSON_UNESCAPED_SLASHES) . "\n"; +echo '::set-output name=windows-matrix-include::' . json_encode($windows_matrix_include, JSON_UNESCAPED_SLASHES) . "\n"; diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index e098c904e3d23..3e8ce86f9dda9 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -11,6 +11,7 @@ jobs: outputs: branches: ${{ steps.set-matrix.outputs.branches }} matrix-include: ${{ steps.set-matrix.outputs.matrix-include }} + windows-matrix-include: ${{ steps.set-matrix.outputs.windows-matrix-include }} steps: - uses: actions/checkout@v3 with: @@ -646,17 +647,13 @@ jobs: with: token: ${{ secrets.ACTION_MONITORING_SLACK }} WINDOWS: + needs: GENERATE_MATRIX + if: ${{ needs.GENERATE_MATRIX.outputs.branches != '[]' }} strategy: fail-fast: false matrix: - include: - - x64: true - zts: true - opcache: true - - x64: false - zts: false - opcache: false - name: "WINDOWS_${{ matrix.x64 && 'X64' || 'X86' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" + include: ${{ fromJson(needs.GENERATE_MATRIX.outputs.windows-matrix-include) }} + name: "${{ matrix.branch.name }}_WINDOWS_${{ matrix.x64 && 'X64' || 'X86' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" runs-on: windows-2019 env: PHP_BUILD_CACHE_BASE_DIR: C:\build-cache @@ -674,6 +671,8 @@ jobs: run: git config --global core.autocrlf false && git config --global core.eol lf - name: git checkout uses: actions/checkout@v3 + with: + ref: ${{ matrix.branch.ref }} - name: Setup uses: ./.github/actions/setup-windows - name: Build From 2012fd3f044a0a10c2ec6ffde823c84571dfb07f Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Fri, 21 Apr 2023 06:33:28 +0100 Subject: [PATCH 02/11] ci update freebsd image to the 13.2 image (#11110) --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index d29ed7e103a26..b3cc9d61f1d68 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -4,7 +4,7 @@ env: freebsd_task: name: FREEBSD_DEBUG_NTS freebsd_instance: - image_family: freebsd-13-0 + image_family: freebsd-13-2 env: ARCH: amd64 install_script: From b71c6b2c6c11547cf7bd11a6109b34e9cb0792b1 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 14 Aug 2023 01:41:54 +0200 Subject: [PATCH 03/11] Fix #81992: SplFixedArray::setSize() causes use-after-free Upon resizing, the elements are destroyed from lower index to higher index. When an element refers to an object with a destructor, it can refer to a lower (i.e. already destroyed) element, causing a uaf. Set refcounted zvals to NULL after destroying them to avoid a uaf. Closes GH-11959. --- NEWS | 4 +++ ext/spl/spl_fixedarray.c | 22 +++++++++++- ext/spl/tests/bug81992.phpt | 32 +++++++++++++++++ ext/spl/tests/bug81992b.phpt | 66 ++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 ext/spl/tests/bug81992.phpt create mode 100644 ext/spl/tests/bug81992b.phpt diff --git a/NEWS b/NEWS index b8bfcace9f65f..1970eca1c734c 100644 --- a/NEWS +++ b/NEWS @@ -55,6 +55,10 @@ PHP NEWS . Revert behaviour of receiving SIGCHLD signals back to the behaviour before 8.1.22. (nielsdos) +- SPL: + . Fixed bug #81992 (SplFixedArray::setSize() causes use-after-free). + (nielsdos) + - Standard: . Prevent int overflow on $decimals in number_format. (Marc Bennewitz) . Fixed bug GH-11870 (Fix off-by-one bug when truncating tempnam prefix) diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 2cf5e2360adbf..562806a5c284b 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -46,6 +46,8 @@ typedef struct _spl_fixedarray { zval *elements; /* True if this was modified after the last call to get_properties or the hash table wasn't rebuilt. */ bool should_rebuild_properties; + /* If positive, it's a resize within a resize and the value gives the desired size. If -1, it's not. */ + zend_long cached_resize; } spl_fixedarray; typedef struct _spl_fixedarray_methods { @@ -117,6 +119,7 @@ static void spl_fixedarray_init(spl_fixedarray *array, zend_long size) } else { spl_fixedarray_default_ctor(array); } + array->cached_resize = -1; } /* Copies the range [begin, end) into the fixedarray, beginning at `offset`. @@ -148,6 +151,7 @@ static void spl_fixedarray_copy_ctor(spl_fixedarray *to, spl_fixedarray *from) */ static void spl_fixedarray_dtor_range(spl_fixedarray *array, zend_long from, zend_long to) { + array->size = from; zval *begin = array->elements + from, *end = array->elements + to; while (begin != end) { zval_ptr_dtor(begin++); @@ -184,19 +188,35 @@ static void spl_fixedarray_resize(spl_fixedarray *array, zend_long size) return; } + if (UNEXPECTED(array->cached_resize >= 0)) { + /* We're already resizing, so just remember the desired size. + * The resize will happen later. */ + array->cached_resize = size; + return; + } + array->cached_resize = size; + /* clearing the array */ if (size == 0) { spl_fixedarray_dtor(array); array->elements = NULL; + array->size = 0; } else if (size > array->size) { array->elements = safe_erealloc(array->elements, size, sizeof(zval), 0); spl_fixedarray_init_elems(array, array->size, size); + array->size = size; } else { /* size < array->size */ + /* Size set in spl_fixedarray_dtor_range() */ spl_fixedarray_dtor_range(array, size, array->size); array->elements = erealloc(array->elements, sizeof(zval) * size); } - array->size = size; + /* If resized within the destructor, take the last resize command and perform it */ + zend_long cached_resize = array->cached_resize; + array->cached_resize = -1; + if (cached_resize != size) { + spl_fixedarray_resize(array, cached_resize); + } } static HashTable* spl_fixedarray_object_get_gc(zend_object *obj, zval **table, int *n) diff --git a/ext/spl/tests/bug81992.phpt b/ext/spl/tests/bug81992.phpt new file mode 100644 index 0000000000000..52235218a78f6 --- /dev/null +++ b/ext/spl/tests/bug81992.phpt @@ -0,0 +1,32 @@ +--TEST-- +Bug #81992 (SplFixedArray::setSize() causes use-after-free) +--FILE-- +getMessage(), "\n"; + } + try { + var_dump($obj[4]); + } catch (Throwable $e) { + echo $e->getMessage(), "\n"; + } + } +} + +$obj = new SplFixedArray(5); +$obj[0] = str_repeat("A", 10); +$obj[2] = str_repeat('B', 10); +$obj[3] = new InvalidDestructor(); +$obj[4] = str_repeat('C', 10); +$obj->setSize(2); +?> +--EXPECT-- +string(10) "AAAAAAAAAA" +Index invalid or out of range +Index invalid or out of range diff --git a/ext/spl/tests/bug81992b.phpt b/ext/spl/tests/bug81992b.phpt new file mode 100644 index 0000000000000..ba4736dfff1f3 --- /dev/null +++ b/ext/spl/tests/bug81992b.phpt @@ -0,0 +1,66 @@ +--TEST-- +Bug #81992 (SplFixedArray::setSize() causes use-after-free) - setSize variation +--FILE-- +obj->setSize($this->desiredSize); + echo "Destroyed, size is now still ", $this->obj->getSize(), "\n"; + } +} + +class DestructorLogger { + public function __construct(private int $id) {} + + public function __destruct() { + echo "Destroyed the logger with id ", $this->id, "\n"; + } +} + +function test(int $desiredSize) { + $obj = new SplFixedArray(5); + $obj[0] = str_repeat("A", 10); + $obj[1] = new DestructorLogger(1); + $obj[2] = str_repeat('B', 10); + $obj[3] = new InvalidDestructor($desiredSize, $obj); + $obj[4] = new DestructorLogger(4); + $obj->setSize(2); + echo "Size is now ", $obj->getSize(), "\n"; + echo "Done\n"; +} + +echo "--- Smaller size test ---\n"; +test(1); +echo "--- Equal size test ---\n"; +test(2); +echo "--- Larger size test ---\n"; +test(10); +?> +--EXPECT-- +--- Smaller size test --- +In destructor +Destroyed, size is now still 2 +Destroyed the logger with id 4 +Destroyed the logger with id 1 +Size is now 1 +Done +--- Equal size test --- +In destructor +Destroyed, size is now still 2 +Destroyed the logger with id 4 +Size is now 2 +Done +Destroyed the logger with id 1 +--- Larger size test --- +In destructor +Destroyed, size is now still 2 +Destroyed the logger with id 4 +Size is now 10 +Done +Destroyed the logger with id 1 From 6e3f93f2f8ecd222701a31dbf3109785dc4e2325 Mon Sep 17 00:00:00 2001 From: Patrick Allaert Date: Tue, 15 Aug 2023 21:09:58 +0200 Subject: [PATCH 04/11] PHP-8.1 is now for PHP 8.1.24-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 1970eca1c734c..58a89b81cc318 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.23 +?? ??? ????, PHP 8.1.24 + + + +31 Aug 2023, PHP 8.1.23 - CLI: . Fixed bug GH-11716 (cli server crashes on SIGINT when compiled with diff --git a/Zend/zend.h b/Zend/zend.h index 237adfe01ddad..5b27b725db262 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.23-dev" +#define ZEND_VERSION "4.1.24-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 6d6d44e0597c4..0c723046adfdc 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.23-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.24-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 b1c3d7c65affb..7c1327eb68217 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 23 +#define PHP_RELEASE_VERSION 24 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.23-dev" -#define PHP_VERSION_ID 80123 +#define PHP_VERSION "8.1.24-dev" +#define PHP_VERSION_ID 80124 From c1103a97725060e3fa1418d83e25875aa4a0f400 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Fri, 24 Mar 2023 13:52:20 +0000 Subject: [PATCH 05/11] Fix implicit/explicit port in mysqlnd --- NEWS | 4 +++- ext/mysqli/tests/gh8978.phpt | 29 +++++++++++++++++++++++++++++ ext/mysqlnd/mysqlnd_commands.c | 2 ++ ext/mysqlnd/mysqlnd_connection.c | 17 +++++++++-------- ext/mysqlnd/mysqlnd_vio.c | 1 - 5 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 ext/mysqli/tests/gh8978.phpt diff --git a/NEWS b/NEWS index 58a89b81cc318..0d2bd565067b8 100644 --- a/NEWS +++ b/NEWS @@ -2,7 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.1.24 - +- MySQLnd: + . Fixed bug GH-10270 (Invalid error message when connection via SSL fails: + "trying to connect via (null)"). (Kamil Tekiela) 31 Aug 2023, PHP 8.1.23 diff --git a/ext/mysqli/tests/gh8978.phpt b/ext/mysqli/tests/gh8978.phpt new file mode 100644 index 0000000000000..394c07ee954ff --- /dev/null +++ b/ext/mysqli/tests/gh8978.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug GH-8267 (Invalid error message when connection via SSL fails) +--EXTENSIONS-- +mysqli +--SKIPIF-- + +--FILE-- +getMessage()."\n"; +} + +echo 'done!'; +?> +--EXPECTF-- +Warning: failed loading cafile stream: `x509.ca' in %s +Cannot connect to MySQL using SSL +done! diff --git a/ext/mysqlnd/mysqlnd_commands.c b/ext/mysqlnd/mysqlnd_commands.c index 40821bb1efedd..ae64560850531 100644 --- a/ext/mysqlnd/mysqlnd_commands.c +++ b/ext/mysqlnd/mysqlnd_commands.c @@ -571,6 +571,8 @@ MYSQLND_METHOD(mysqlnd_command, enable_ssl)(MYSQLND_CONN_DATA * const conn, cons conn->vio->data->m.set_client_option(conn->vio, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify); if (FAIL == conn->vio->data->m.enable_ssl(conn->vio)) { + SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT); + SET_CLIENT_ERROR(conn->error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, "Cannot connect to MySQL using SSL"); goto end; } } diff --git a/ext/mysqlnd/mysqlnd_connection.c b/ext/mysqlnd/mysqlnd_connection.c index 4f720cdb15495..c905e38c8573d 100644 --- a/ext/mysqlnd/mysqlnd_connection.c +++ b/ext/mysqlnd/mysqlnd_connection.c @@ -289,7 +289,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, free_contents)(MYSQLND_CONN_DATA * conn) mysqlnd_set_persistent_string(&conn->unix_socket, NULL, 0, pers); DBG_INF_FMT("scheme=%s", conn->scheme.s); mysqlnd_set_persistent_string(&conn->scheme, NULL, 0, pers); - + if (conn->server_version) { mnd_pefree(conn->server_version, pers); conn->server_version = NULL; @@ -726,19 +726,20 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn, DBG_RETURN(PASS); } err: - if (transport.s) { - mnd_sprintf_free(transport.s); - transport.s = NULL; - } - - DBG_ERR_FMT("[%u] %.128s (trying to connect via %s)", conn->error_info->error_no, conn->error_info->error, conn->scheme.s); + DBG_ERR_FMT("[%u] %.128s (trying to connect via %s)", conn->error_info->error_no, conn->error_info->error, transport.s ? transport.s : conn->scheme.s); if (!conn->error_info->error_no) { + /* There was an unknown error if the connection failed but we have no error number */ char * msg; - mnd_sprintf(&msg, 0, "%s (trying to connect via %s)",conn->error_info->error, conn->scheme.s); + mnd_sprintf(&msg, 0, "Unknown error while trying to connect via %s", transport.s ? transport.s : conn->scheme.s); SET_CLIENT_ERROR(conn->error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, msg); mnd_sprintf_free(msg); } + if (transport.s) { + mnd_sprintf_free(transport.s); + transport.s = NULL; + } + conn->m->free_contents(conn); MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CONNECT_FAILURE); DBG_RETURN(FAIL); diff --git a/ext/mysqlnd/mysqlnd_vio.c b/ext/mysqlnd/mysqlnd_vio.c index 2bd77906a1b9a..cd9c714f23bb9 100644 --- a/ext/mysqlnd/mysqlnd_vio.c +++ b/ext/mysqlnd/mysqlnd_vio.c @@ -569,7 +569,6 @@ MYSQLND_METHOD(mysqlnd_vio, enable_ssl)(MYSQLND_VIO * const net) php_stream_xport_crypto_enable(net_stream, 1) < 0) { DBG_ERR("Cannot connect to MySQL by using SSL"); - php_error_docref(NULL, E_WARNING, "Cannot connect to MySQL by using SSL"); DBG_RETURN(FAIL); } net->data->ssl = TRUE; From f78d1d0d10284b3599a099b783b56f16b338f728 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sat, 12 Aug 2023 16:11:29 +0200 Subject: [PATCH 06/11] Fix segfault in format_default_value due to unexpected enum/object Evaluating constants at comptime can result in arrays that contain objects. This is problematic for printing the default value of constant ASTs containing objects, because we don't actually know what the constructor arguments were. Avoid this by not propagating array constants. Fixes GH-11937 Closes GH-11947 --- NEWS | 3 +++ Zend/zend_compile.c | 40 +++++++++++++++++++++++++++-- ext/reflection/php_reflection.c | 1 + ext/reflection/tests/gh11937_1.inc | 13 ++++++++++ ext/reflection/tests/gh11937_1.phpt | 30 ++++++++++++++++++++++ ext/reflection/tests/gh11937_2.inc | 4 +++ ext/reflection/tests/gh11937_2.phpt | 27 +++++++++++++++++++ 7 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 ext/reflection/tests/gh11937_1.inc create mode 100644 ext/reflection/tests/gh11937_1.phpt create mode 100644 ext/reflection/tests/gh11937_2.inc create mode 100644 ext/reflection/tests/gh11937_2.phpt diff --git a/NEWS b/NEWS index 0d2bd565067b8..010acdaf17c63 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.1.24 +- Core: + . Fixed bug GH-11937 (Constant ASTs containing objects). (ilutov) + - MySQLnd: . Fixed bug GH-10270 (Invalid error message when connection via SSL fails: "trying to connect via (null)"). (Kamil Tekiela) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index af9be18d10f5b..351c2708bf409 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1458,6 +1458,35 @@ ZEND_API zend_result zend_unmangle_property_name_ex(const zend_string *name, con } /* }}} */ +static bool array_is_const_ex(zend_array *array, uint32_t *max_checks) +{ + if (zend_hash_num_elements(array) > *max_checks) { + return false; + } + *max_checks -= zend_hash_num_elements(array); + + zval *element; + ZEND_HASH_FOREACH_VAL(array, element) { + if (Z_TYPE_P(element) < IS_ARRAY) { + continue; + } else if (Z_TYPE_P(element) == IS_ARRAY) { + if (!array_is_const_ex(array, max_checks)) { + return false; + } + } else if (UNEXPECTED(Z_TYPE_P(element) >=IS_OBJECT)) { + return false; + } + } ZEND_HASH_FOREACH_END(); + + return true; +} + +static bool array_is_const(zend_array *array) +{ + uint32_t max_checks = 50; + return array_is_const_ex(array, &max_checks); +} + static bool can_ct_eval_const(zend_constant *c) { if (ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED) { return 0; @@ -1468,9 +1497,13 @@ static bool can_ct_eval_const(zend_constant *c) { && (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) { return 1; } - if (Z_TYPE(c->value) < IS_OBJECT + if (Z_TYPE(c->value) < IS_ARRAY && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) { return 1; + } else if (Z_TYPE(c->value) == IS_ARRAY + && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) + && array_is_const(Z_ARR(c->value))) { + return 1; } return 0; } @@ -1690,7 +1723,10 @@ static bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend c = &cc->value; /* Substitute case-sensitive (or lowercase) persistent class constants */ - if (Z_TYPE_P(c) < IS_OBJECT) { + if (Z_TYPE_P(c) < IS_ARRAY) { + ZVAL_COPY_OR_DUP(zv, c); + return 1; + } else if (Z_TYPE_P(c) == IS_ARRAY && array_is_const(Z_ARR_P(c))) { ZVAL_COPY_OR_DUP(zv, c); return 1; } diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index d3d5914866a1e..876338f4ab127 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -639,6 +639,7 @@ static int format_default_value(smart_str *str, zval *value) { } ZEND_HASH_FOREACH_END(); smart_str_appendc(str, ']'); } else if (Z_TYPE_P(value) == IS_OBJECT) { + /* This branch may only be reached for default properties, which don't support arbitrary objects. */ zend_object *obj = Z_OBJ_P(value); zend_class_entry *class = obj->ce; ZEND_ASSERT(class->ce_flags & ZEND_ACC_ENUM); diff --git a/ext/reflection/tests/gh11937_1.inc b/ext/reflection/tests/gh11937_1.inc new file mode 100644 index 0000000000000..4d55213f2f831 --- /dev/null +++ b/ext/reflection/tests/gh11937_1.inc @@ -0,0 +1,13 @@ +getAttributes('Attr')[0]; + +?> +--EXPECT-- +array(2) { + [0]=> + enum(TestEnum::One) + [1]=> + enum(TestEnum::Two) +} +Attribute [ Attr ] { + - Arguments [1] { + Argument #0 [ new \Foo(TestEnum::CASES) ] + } +} diff --git a/ext/reflection/tests/gh11937_2.inc b/ext/reflection/tests/gh11937_2.inc new file mode 100644 index 0000000000000..d6e21e6ba5c55 --- /dev/null +++ b/ext/reflection/tests/gh11937_2.inc @@ -0,0 +1,4 @@ +getAttributes('Attr')[0]; + +?> +--EXPECT-- +array(1) { + [0]=> + object(Foo)#1 (0) { + } +} +Attribute [ Attr ] { + - Arguments [1] { + Argument #0 [ FOOS ] + } +} From dd01c74a6fd7813fc41c658005447f9e2fc9e586 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 17 Aug 2023 18:54:30 +0200 Subject: [PATCH 07/11] Remove redundant condition Never refactor code just before pushing --- Zend/zend_compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 351c2708bf409..75127b8b8d18a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1473,7 +1473,7 @@ static bool array_is_const_ex(zend_array *array, uint32_t *max_checks) if (!array_is_const_ex(array, max_checks)) { return false; } - } else if (UNEXPECTED(Z_TYPE_P(element) >=IS_OBJECT)) { + } else { return false; } } ZEND_HASH_FOREACH_END(); From ffd398b4feed1069ffd3dd0d0ceeeafd5d76994b Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 17 Aug 2023 18:45:10 +0100 Subject: [PATCH 08/11] Fix failing test on nightly --- ext/mysqli/tests/gh8978.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/mysqli/tests/gh8978.phpt b/ext/mysqli/tests/gh8978.phpt index 394c07ee954ff..92de63b381ca8 100644 --- a/ext/mysqli/tests/gh8978.phpt +++ b/ext/mysqli/tests/gh8978.phpt @@ -16,7 +16,7 @@ $mysql = mysqli_init(); mysqli_ssl_set($mysql, 'x509.key', 'x509.pem', 'x509.ca', null, null); try { // There should be no warning here, only exception - mysqli_real_connect($mysql, '127.0.0.1:3306', 'username', 'password', null, null, null, MYSQLI_CLIENT_SSL); + mysqli_real_connect($mysql, $host, $user, $passwd, null, $port, null, MYSQLI_CLIENT_SSL); } catch (mysqli_sql_exception $e) { echo $e->getMessage()."\n"; } From fc8d5c72e5e62a9486981960d4a94b39789044c4 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 19 Aug 2023 19:20:01 +0100 Subject: [PATCH 09/11] ext/iconv: fix build for netbsd. NetBSD still adopts the old iconv signature for buffer inputs. The next release will too so we can assume it will remain that way for a while. Close GH-12001 --- NEWS | 4 ++++ ext/iconv/iconv.c | 26 +++++++++++++++++--------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/NEWS b/NEWS index 010acdaf17c63..d3e73e95c9752 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,10 @@ PHP NEWS - Core: . Fixed bug GH-11937 (Constant ASTs containing objects). (ilutov) +- Iconv: + . Fixed build for NetBSD which still uses the old iconv signature. + (David Carlier) + - MySQLnd: . Fixed bug GH-10270 (Invalid error message when connection via SSL fails: "trying to connect via (null)"). (Kamil Tekiela) diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index f05e58aa1d953..83d89a0df4835 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -44,6 +44,14 @@ #undef iconv #endif +#if defined(__NetBSD__) +// unfortunately, netbsd has still the old non posix conformant signature +// libiconv tends to match the eventual system's iconv too. +#define ICONV_CONST const +#else +#define ICONV_CONST +#endif + #include "zend_smart_str.h" #include "ext/standard/base64.h" #include "ext/standard/quot_print.h" @@ -360,7 +368,7 @@ static php_iconv_err_t _php_iconv_appendl(smart_str *d, const char *s, size_t l, out_p = ZSTR_VAL((d)->s) + ZSTR_LEN((d)->s); - if (iconv(cd, (char **)&in_p, &in_left, (char **) &out_p, &out_left) == (size_t)-1) { + if (iconv(cd, (ICONV_CONST char **)&in_p, &in_left, (char **) &out_p, &out_left) == (size_t)-1) { switch (errno) { case EINVAL: return PHP_ICONV_ERR_ILLEGAL_CHAR; @@ -456,7 +464,7 @@ PHP_ICONV_API php_iconv_err_t php_iconv_string(const char *in_p, size_t in_len, out_p = ZSTR_VAL(out_buf); while (in_left > 0) { - result = iconv(cd, (char **) &in_p, &in_left, (char **) &out_p, &out_left); + result = iconv(cd, (ICONV_CONST char **) &in_p, &in_left, (char **) &out_p, &out_left); out_size = bsz - out_left; if (result == (size_t)(-1)) { if (ignore_ilseq && errno == EILSEQ) { @@ -576,7 +584,7 @@ static php_iconv_err_t _php_iconv_strlen(size_t *pretval, const char *str, size_ more = in_left > 0; - iconv(cd, more ? (char **)&in_p : NULL, more ? &in_left : NULL, (char **) &out_p, &out_left); + iconv(cd, more ? (ICONV_CONST char **)&in_p : NULL, more ? &in_left : NULL, (char **) &out_p, &out_left); if (out_left == sizeof(buf)) { break; } else { @@ -683,7 +691,7 @@ static php_iconv_err_t _php_iconv_substr(smart_str *pretval, more = in_left > 0 && len > 0; - iconv(cd1, more ? (char **)&in_p : NULL, more ? &in_left : NULL, (char **) &out_p, &out_left); + iconv(cd1, more ? (ICONV_CONST char **)&in_p : NULL, more ? &in_left : NULL, (char **) &out_p, &out_left); if (out_left == sizeof(buf)) { break; } @@ -805,7 +813,7 @@ static php_iconv_err_t _php_iconv_strpos(size_t *pretval, more = in_left > 0; - iconv_ret = iconv(cd, more ? (char **)&in_p : NULL, more ? &in_left : NULL, (char **) &out_p, &out_left); + iconv_ret = iconv(cd, more ? (ICONV_CONST char **)&in_p : NULL, more ? &in_left : NULL, (char **) &out_p, &out_left); if (out_left == sizeof(buf)) { break; } @@ -1012,7 +1020,7 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn out_left = out_size - out_reserved; - if (iconv(cd, (char **)&in_p, &in_left, (char **) &out_p, &out_left) == (size_t)-1) { + if (iconv(cd, (ICONV_CONST char **)&in_p, &in_left, (char **) &out_p, &out_left) == (size_t)-1) { switch (errno) { case EINVAL: err = PHP_ICONV_ERR_ILLEGAL_CHAR; @@ -1096,7 +1104,7 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn out_p = buf; out_left = out_size; - if (iconv(cd, (char **)&in_p, &in_left, (char **) &out_p, &out_left) == (size_t)-1) { + if (iconv(cd, (ICONV_CONST char **)&in_p, &in_left, (char **) &out_p, &out_left) == (size_t)-1) { switch (errno) { case EINVAL: err = PHP_ICONV_ERR_ILLEGAL_CHAR; @@ -2373,7 +2381,7 @@ static int php_iconv_stream_filter_append_bucket( tcnt = self->stub_len; while (tcnt > 0) { - if (iconv(self->cd, &pt, &tcnt, &pd, &ocnt) == (size_t)-1) { + if (iconv(self->cd, (ICONV_CONST char **)&pt, &tcnt, &pd, &ocnt) == (size_t)-1) { switch (errno) { case EILSEQ: php_error_docref(NULL, E_WARNING, "iconv stream filter (\"%s\"=>\"%s\"): invalid multibyte sequence", self->from_charset, self->to_charset); @@ -2439,7 +2447,7 @@ static int php_iconv_stream_filter_append_bucket( while (icnt > 0) { if ((ps == NULL ? iconv(self->cd, NULL, NULL, &pd, &ocnt): - iconv(self->cd, (char **)&ps, &icnt, &pd, &ocnt)) == (size_t)-1) { + iconv(self->cd, (ICONV_CONST char **)&ps, &icnt, &pd, &ocnt)) == (size_t)-1) { switch (errno) { case EILSEQ: php_error_docref(NULL, E_WARNING, "iconv stream filter (\"%s\"=>\"%s\"): invalid multibyte sequence", self->from_charset, self->to_charset); From 20ac42e1b065e23376e7ea548995636369809a7d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 19 Aug 2023 23:54:53 +0200 Subject: [PATCH 10/11] Fix memory leak when setting an invalid DOMDocument encoding Because the failure path did not release the string, there was a memory leak. As the only valid types for this function are IS_NULL and IS_STRING, we and IS_NULL is always rejected in practice, solve the issue by not using a function that increments the refcount in the first place. Closes GH-12002. --- NEWS | 3 +++ ext/dom/document.c | 19 ++++++++++++------- ext/dom/tests/gh12002.phpt | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 ext/dom/tests/gh12002.phpt diff --git a/NEWS b/NEWS index d3e73e95c9752..a4d3499a58315 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ PHP NEWS - Core: . Fixed bug GH-11937 (Constant ASTs containing objects). (ilutov) +- DOM: + . Fix memory leak when setting an invalid DOMDocument encoding. (nielsdos) + - Iconv: . Fixed build for NetBSD which still uses the old iconv signature. (David Carlier) diff --git a/ext/dom/document.c b/ext/dom/document.c index ea6daafeb30fb..64da4f051be2c 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -139,7 +139,6 @@ int dom_document_encoding_read(dom_object *obj, zval *retval) zend_result dom_document_encoding_write(dom_object *obj, zval *newval) { xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj); - zend_string *str; xmlCharEncodingHandlerPtr handler; if (docp == NULL) { @@ -147,11 +146,15 @@ zend_result dom_document_encoding_write(dom_object *obj, zval *newval) return FAILURE; } - str = zval_try_get_string(newval); - if (UNEXPECTED(!str)) { - return FAILURE; + /* Typed property, can only be IS_STRING or IS_NULL. */ + ZEND_ASSERT(Z_TYPE_P(newval) == IS_STRING || Z_TYPE_P(newval) == IS_NULL); + + if (Z_TYPE_P(newval) == IS_NULL) { + goto invalid_encoding; } + zend_string *str = Z_STR_P(newval); + handler = xmlFindCharEncodingHandler(ZSTR_VAL(str)); if (handler != NULL) { @@ -161,12 +164,14 @@ zend_result dom_document_encoding_write(dom_object *obj, zval *newval) } docp->encoding = xmlStrdup((const xmlChar *) ZSTR_VAL(str)); } else { - zend_value_error("Invalid document encoding"); - return FAILURE; + goto invalid_encoding; } - zend_string_release_ex(str, 0); return SUCCESS; + +invalid_encoding: + zend_value_error("Invalid document encoding"); + return FAILURE; } /* }}} */ diff --git a/ext/dom/tests/gh12002.phpt b/ext/dom/tests/gh12002.phpt new file mode 100644 index 0000000000000..7d1ae944646ae --- /dev/null +++ b/ext/dom/tests/gh12002.phpt @@ -0,0 +1,38 @@ +--TEST-- +GH-12002 (DOMDocument::encoding memory leak with invalid encoding) +--EXTENSIONS-- +dom +--FILE-- +encoding = make_nonconst('utf-8'); +var_dump($dom->encoding); +try { + $dom->encoding = make_nonconst('foobar'); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +var_dump($dom->encoding); +$dom->encoding = make_nonconst('utf-16le'); +var_dump($dom->encoding); +try { + $dom->encoding = NULL; +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +var_dump($dom->encoding); + +?> +--EXPECT-- +string(5) "utf-8" +Invalid document encoding +string(5) "utf-8" +string(8) "utf-16le" +Invalid document encoding +string(8) "utf-16le" From ba07a0b8461f7c5c46eb61c0c543a6f688d830f5 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 23 Aug 2023 10:56:12 +0200 Subject: [PATCH 11/11] Move installation of oracle instant client in GHA Closes GH-12033 --- .github/actions/apt-x64/action.yml | 12 ------------ .github/actions/install-linux-x32/action.yml | 2 +- .github/actions/install-linux/action.yml | 4 +--- .github/actions/setup-oracle/action.yml | 17 +++++++++++++++++ .github/workflows/nightly.yml | 2 +- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/.github/actions/apt-x64/action.yml b/.github/actions/apt-x64/action.yml index 621b18532e05f..4e1a03dd58cc5 100644 --- a/.github/actions/apt-x64/action.yml +++ b/.github/actions/apt-x64/action.yml @@ -59,15 +59,3 @@ runs: libjpeg-dev \ libpng-dev \ libfreetype6-dev - - mkdir /opt/oracle - wget -nv https://download.oracle.com/otn_software/linux/instantclient/instantclient-basiclite-linuxx64.zip - unzip instantclient-basiclite-linuxx64.zip && rm instantclient-basiclite-linuxx64.zip - wget -nv https://download.oracle.com/otn_software/linux/instantclient/instantclient-sdk-linuxx64.zip - unzip instantclient-sdk-linuxx64.zip && rm instantclient-sdk-linuxx64.zip - mv instantclient_*_* /opt/oracle/instantclient - # interferes with libldap2 headers - rm /opt/oracle/instantclient/sdk/include/ldap.h - # fix debug build warning: zend_signal: handler was replaced for signal (2) after startup - echo DISABLE_INTERRUPT=on > /opt/oracle/instantclient/network/admin/sqlnet.ora - sudo sh -c 'echo /opt/oracle/instantclient >/etc/ld.so.conf.d/oracle-instantclient.conf && ldconfig' diff --git a/.github/actions/install-linux-x32/action.yml b/.github/actions/install-linux-x32/action.yml index bf5f09cd779d4..4ef87ee03fd3f 100644 --- a/.github/actions/install-linux-x32/action.yml +++ b/.github/actions/install-linux-x32/action.yml @@ -6,7 +6,7 @@ runs: run: | set -x make install - mkdir /etc/php.d + mkdir -p /etc/php.d chmod 777 /etc/php.d echo mysqli.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/mysqli.ini echo pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/pdo_mysql.ini diff --git a/.github/actions/install-linux/action.yml b/.github/actions/install-linux/action.yml index 7ac2ae4c4fcb1..576357b94f1c5 100644 --- a/.github/actions/install-linux/action.yml +++ b/.github/actions/install-linux/action.yml @@ -6,9 +6,7 @@ runs: run: | set -x sudo make install - sudo mkdir /etc/php.d + sudo mkdir -p /etc/php.d sudo chmod 777 /etc/php.d echo mysqli.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/mysqli.ini echo pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/pdo_mysql.ini - echo extension=oci8.so > /etc/php.d/oci8.ini - echo extension=pdo_oci.so > /etc/php.d/pdo_oci.ini diff --git a/.github/actions/setup-oracle/action.yml b/.github/actions/setup-oracle/action.yml index 11c16fe93d525..1208e93a24893 100644 --- a/.github/actions/setup-oracle/action.yml +++ b/.github/actions/setup-oracle/action.yml @@ -11,3 +11,20 @@ runs: --name oracle \ -h oracle \ -d gvenzl/oracle-xe:slim + + mkdir /opt/oracle + wget -nv https://download.oracle.com/otn_software/linux/instantclient/instantclient-basiclite-linuxx64.zip + unzip instantclient-basiclite-linuxx64.zip && rm instantclient-basiclite-linuxx64.zip + wget -nv https://download.oracle.com/otn_software/linux/instantclient/instantclient-sdk-linuxx64.zip + unzip instantclient-sdk-linuxx64.zip && rm instantclient-sdk-linuxx64.zip + mv instantclient_*_* /opt/oracle/instantclient + # interferes with libldap2 headers + rm /opt/oracle/instantclient/sdk/include/ldap.h + # fix debug build warning: zend_signal: handler was replaced for signal (2) after startup + echo DISABLE_INTERRUPT=on > /opt/oracle/instantclient/network/admin/sqlnet.ora + sudo sh -c 'echo /opt/oracle/instantclient >/etc/ld.so.conf.d/oracle-instantclient.conf && ldconfig' + + sudo mkdir -p /etc/php.d + sudo chmod 777 /etc/php.d + echo extension=oci8.so > /etc/php.d/oci8.ini + echo extension=pdo_oci.so > /etc/php.d/pdo_oci.ini diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 3e8ce86f9dda9..1ff8b6847a4a0 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -555,7 +555,7 @@ jobs: - name: make install run: | sudo make install - sudo mkdir /etc/php.d + sudo mkdir -p /etc/php.d sudo chmod 777 /etc/php.d echo mysqli.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/mysqli.ini echo pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/pdo_mysql.ini