diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index c310565f3b57..ded06c46b2ec 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -14,6 +14,9 @@ on: libmysqlclient_with_mysqli: required: true type: boolean + macos_arm64_version: + required: true + type: string run_alpine: required: true type: boolean @@ -366,11 +369,11 @@ jobs: matrix: debug: [true, false] zts: [true, false] - os: ['13', '14'] + arch: ['X64', 'ARM64'] exclude: - - os: ${{ !inputs.run_macos_arm64 && '14' || '*never*' }} - name: "MACOS_${{ matrix.os == '13' && 'X64' || 'ARM64' }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" - runs-on: macos-${{ matrix.os }} + - arch: ${{ !inputs.run_macos_arm64 && 'ARM64' || '*never*' }} + name: "MACOS_${{ matrix.arch }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" + runs-on: macos-${{ matrix.arch == 'X64' && '15-intel' || inputs.macos_arm64_version }} steps: - name: git checkout uses: actions/checkout@v5 @@ -393,7 +396,7 @@ jobs: - name: Test uses: ./.github/actions/test-macos - name: Test Tracing JIT - if: matrix.os != '14' || !matrix.zts + if: matrix.arch == 'X64' || !matrix.zts uses: ./.github/actions/test-macos with: jitType: tracing @@ -405,7 +408,7 @@ jobs: runTestsParameters: >- -d opcache.enable_cli=1 - name: Test Function JIT - if: matrix.os != '14' || !matrix.zts + if: matrix.arch == 'X64' || !matrix.zts uses: ./.github/actions/test-macos with: jitType: function diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index b70b026eced0..2983a8e3c908 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -52,6 +52,7 @@ jobs: branch: ${{ matrix.branch.ref }} community_verify_type_inference: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} libmysqlclient_with_mysqli: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1) }} + macos_arm64_version: ${{ ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 5) || matrix.branch.version[0] >= 9) && '15' || '14' }} run_alpine: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} run_linux_ppc64: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} run_macos_arm64: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index d71c06c0a135..3c3065e15687 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -9720,7 +9720,11 @@ ZEND_VM_HANDLER(202, ZEND_CALLABLE_CONVERT, UNUSED, UNUSED, NUM|CACHE_SLOT) if (closure) { ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); } else { - zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), (zend_ulong)(uintptr_t)call->func); + /* Rotate the key for better hash distribution. */ + const int shift = sizeof(size_t) == 4 ? 6 : 7; + zend_ulong key = (zend_ulong)(uintptr_t)call->func; + key = (key >> shift) | (key << ((sizeof(key) * 8) - shift)); + zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), key); if (Z_TYPE_P(closure_zv) == IS_NULL) { zend_closure_from_frame(closure_zv, call); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 50b65c864ed2..50870ce463de 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -39093,7 +39093,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALLABLE_CONV if (closure) { ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); } else { - zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), (zend_ulong)(uintptr_t)call->func); + /* Rotate the key for better hash distribution. */ + const int shift = sizeof(size_t) == 4 ? 6 : 7; + zend_ulong key = (zend_ulong)(uintptr_t)call->func; + key = (key >> shift) | (key << ((sizeof(key) * 8) - shift)); + zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), key); if (Z_TYPE_P(closure_zv) == IS_NULL) { zend_closure_from_frame(closure_zv, call); } @@ -94331,7 +94335,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALLABLE_CONVERT_S if (closure) { ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); } else { - zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), (zend_ulong)(uintptr_t)call->func); + /* Rotate the key for better hash distribution. */ + const int shift = sizeof(size_t) == 4 ? 6 : 7; + zend_ulong key = (zend_ulong)(uintptr_t)call->func; + key = (key >> shift) | (key << ((sizeof(key) * 8) - shift)); + zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), key); if (Z_TYPE_P(closure_zv) == IS_NULL) { zend_closure_from_frame(closure_zv, call); } diff --git a/ext/ctype/tests/lc_ctype_inheritance.phpt b/ext/ctype/tests/lc_ctype_inheritance.phpt index 98a0c35cf00e..ba5ea177c38a 100644 --- a/ext/ctype/tests/lc_ctype_inheritance.phpt +++ b/ext/ctype/tests/lc_ctype_inheritance.phpt @@ -4,7 +4,9 @@ Do not inherit LC_CTYPE from environment ctype --SKIPIF-- =')) { + die('skip macOS 15 inherits LC_CTYPE into the thread locale'); +} if (setlocale(LC_ALL, 'invalid') === 'invalid') { die('skip setlocale() is broken /w musl'); } if (!setlocale(LC_CTYPE, "de_DE", "de-DE")) die("skip requires de_DE locale"); ?> diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 9dcca2e81e0b..2906b8c7150e 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -3261,6 +3261,7 @@ static bool exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * val #define REQUIRE_NON_EMPTY() do { \ if (byte_count == 0) { \ + EFREE_IF(outside); \ exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Process tag(x%04X=%s): Cannot be empty", tag, exif_get_tagname_debug(tag, tag_table)); \ return false; \ } \ diff --git a/ext/mysqlnd/mysqlnd_connection.c b/ext/mysqlnd/mysqlnd_connection.c index 31f3da08f6e1..8eb61a58acb4 100644 --- a/ext/mysqlnd/mysqlnd_connection.c +++ b/ext/mysqlnd/mysqlnd_connection.c @@ -552,7 +552,14 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_ if (hostname.s[0] != '[' && mysqlnd_fast_is_ipv6_address(hostname.s)) { transport.l = mnd_sprintf(&transport.s, 0, "tcp://[%s]:%u", hostname.s, port); } else { - transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s:%u", hostname.s, port); + /* Not ipv6, but could already contain a port number, in which case we should not add an extra port. + * See GH-8978. In a port doubling scenario, the first port would be used so we do the same to keep BC. */ + if (strchr(hostname.s, ':')) { + /* TODO: Ideally we should be able to get rid of this workaround in the future. */ + transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s", hostname.s); + } else { + transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s:%u", hostname.s, port); + } } } DBG_INF_FMT("transport=%s", transport.s? transport.s:"OOM");