diff --git a/NEWS b/NEWS index 6cca730cd9e77..1171faacfcb9e 100644 --- a/NEWS +++ b/NEWS @@ -2,22 +2,15 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.5.0beta1 -- Core: - . Fixed bug GH-19305 (Operands may be being released during comparison). - (Arnaud) -- Intl: - . Fixed bug GH-19307 (PGO builds of shared ext-intl are broken). (cmb) - -- Opcache: - . Fixed bug GH-19301 (opcache build failure). (Remi) - -31 Jul 2025, PHP 8.5.0alpha3 +31 Jul 2025, PHP 8.5.0alpha4 - Core: . Add clone-with support to the clone() function. (timwolla, edorian) . Fix support for non-userland stream notifiers. (timwolla) . Added PHP_BUILD_PROVIDER constant. (timwolla) + . Fixed bug GH-19305 (Operands may be being released during comparison). + (Arnaud) - Curl: . Add support for CURLINFO_CONN_ID in curl_getinfo() (thecaliskan) @@ -32,6 +25,7 @@ PHP NEWS - Intl: . Fix return value on failure for resourcebundle count handler. (Girgias) + . Fixed bug GH-19307 (PGO builds of shared ext-intl are broken). (cmb) - OPcache: . Disallow changing opcache.memory_consumption when SHM is already set up. @@ -41,6 +35,7 @@ PHP NEWS . Make OPcache non-optional (Arnaud, timwolla) . Fixed bug GH-17422 (OPcache bypasses the user-defined error handler for deprecations). (Arnaud, timwolla) + . Fixed bug GH-19301 (opcache build failure). (Remi) - OpenSSL: . Add $digest_algo parameter to openssl_public_encrypt() and diff --git a/Zend/tests/array_unpack/gh19303.phpt b/Zend/tests/array_unpack/gh19303.phpt new file mode 100644 index 0000000000000..af594c3740c2d --- /dev/null +++ b/Zend/tests/array_unpack/gh19303.phpt @@ -0,0 +1,11 @@ +--TEST-- +GH-19303 (Unpacking empty packed array into uninitialized array causes assertion failure) +--FILE-- + +--EXPECT-- +array(0) { +} diff --git a/Zend/tests/attributes/allow_dynamic_properties_on_enum.phpt b/Zend/tests/attributes/allow_dynamic_properties_on_enum.phpt index b9ab745be9ae7..f1ce8b055b0e0 100644 --- a/Zend/tests/attributes/allow_dynamic_properties_on_enum.phpt +++ b/Zend/tests/attributes/allow_dynamic_properties_on_enum.phpt @@ -8,4 +8,4 @@ enum Test {} ?> --EXPECTF-- -Fatal error: Cannot apply #[AllowDynamicProperties] to enum Test in %s on line %d +Fatal error: Cannot apply #[\AllowDynamicProperties] to enum Test in %s on line %d diff --git a/Zend/tests/attributes/allow_dynamic_properties_on_interface.phpt b/Zend/tests/attributes/allow_dynamic_properties_on_interface.phpt index 0428256a18e40..16440a385db14 100644 --- a/Zend/tests/attributes/allow_dynamic_properties_on_interface.phpt +++ b/Zend/tests/attributes/allow_dynamic_properties_on_interface.phpt @@ -8,4 +8,4 @@ interface Test {} ?> --EXPECTF-- -Fatal error: Cannot apply #[AllowDynamicProperties] to interface Test in %s on line %d +Fatal error: Cannot apply #[\AllowDynamicProperties] to interface Test in %s on line %d diff --git a/Zend/tests/attributes/allow_dynamic_properties_on_trait.phpt b/Zend/tests/attributes/allow_dynamic_properties_on_trait.phpt index 9636dc03141e5..bd18b3e71c8f1 100644 --- a/Zend/tests/attributes/allow_dynamic_properties_on_trait.phpt +++ b/Zend/tests/attributes/allow_dynamic_properties_on_trait.phpt @@ -8,4 +8,4 @@ trait Test {} ?> --EXPECTF-- -Fatal error: Cannot apply #[AllowDynamicProperties] to trait Test in %s on line %d +Fatal error: Cannot apply #[\AllowDynamicProperties] to trait Test in %s on line %d diff --git a/Zend/tests/readonly_classes/gh10377_1.phpt b/Zend/tests/readonly_classes/gh10377_1.phpt index ac421cb8a5171..fba1605ff0849 100644 --- a/Zend/tests/readonly_classes/gh10377_1.phpt +++ b/Zend/tests/readonly_classes/gh10377_1.phpt @@ -12,4 +12,4 @@ $readonly_anon = new #[AllowDynamicProperties] readonly class { ?> --EXPECTF-- -Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class class@anonymous in %s on line %d +Fatal error: Cannot apply #[\AllowDynamicProperties] to readonly class class@anonymous in %s on line %d diff --git a/Zend/tests/readonly_classes/readonly_class_dynamic_property_attribute.phpt b/Zend/tests/readonly_classes/readonly_class_dynamic_property_attribute.phpt index ace50c572aced..fab37dccfbf61 100644 --- a/Zend/tests/readonly_classes/readonly_class_dynamic_property_attribute.phpt +++ b/Zend/tests/readonly_classes/readonly_class_dynamic_property_attribute.phpt @@ -10,4 +10,4 @@ readonly class Foo ?> --EXPECTF-- -Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class Foo in %s on line %d +Fatal error: Cannot apply #[\AllowDynamicProperties] to readonly class Foo in %s on line %d diff --git a/Zend/zend_attributes.c b/Zend/zend_attributes.c index c3633801be83e..01b16d7d205eb 100644 --- a/Zend/zend_attributes.c +++ b/Zend/zend_attributes.c @@ -73,22 +73,22 @@ static void validate_allow_dynamic_properties( zend_attribute *attr, uint32_t target, zend_class_entry *scope) { if (scope->ce_flags & ZEND_ACC_TRAIT) { - zend_error_noreturn(E_ERROR, "Cannot apply #[AllowDynamicProperties] to trait %s", + zend_error_noreturn(E_ERROR, "Cannot apply #[\\AllowDynamicProperties] to trait %s", ZSTR_VAL(scope->name) ); } if (scope->ce_flags & ZEND_ACC_INTERFACE) { - zend_error_noreturn(E_ERROR, "Cannot apply #[AllowDynamicProperties] to interface %s", + zend_error_noreturn(E_ERROR, "Cannot apply #[\\AllowDynamicProperties] to interface %s", ZSTR_VAL(scope->name) ); } if (scope->ce_flags & ZEND_ACC_READONLY_CLASS) { - zend_error_noreturn(E_ERROR, "Cannot apply #[AllowDynamicProperties] to readonly class %s", + zend_error_noreturn(E_ERROR, "Cannot apply #[\\AllowDynamicProperties] to readonly class %s", ZSTR_VAL(scope->name) ); } if (scope->ce_flags & ZEND_ACC_ENUM) { - zend_error_noreturn(E_ERROR, "Cannot apply #[AllowDynamicProperties] to enum %s", + zend_error_noreturn(E_ERROR, "Cannot apply #[\\AllowDynamicProperties] to enum %s", ZSTR_VAL(scope->name) ); } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index a38793ac205b5..d305b0a9516ba 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -6325,17 +6325,22 @@ ZEND_VM_C_LABEL(add_unpack_again): zval *val; if (HT_IS_PACKED(ht) && (zend_hash_num_elements(result_ht) == 0 || HT_IS_PACKED(result_ht))) { - zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1); - ZEND_HASH_FILL_PACKED(result_ht) { - ZEND_HASH_PACKED_FOREACH_VAL(ht, val) { - if (UNEXPECTED(Z_ISREF_P(val)) && - UNEXPECTED(Z_REFCOUNT_P(val) == 1)) { - val = Z_REFVAL_P(val); - } - Z_TRY_ADDREF_P(val); - ZEND_HASH_FILL_ADD(val); - } ZEND_HASH_FOREACH_END(); - } ZEND_HASH_FILL_END(); + /* zend_hash_extend() skips initialization when the number of elements is 0, + * but the code below expects that result_ht is initialized as packed. + * We can just skip the work in that case. */ + if (result_ht->nNumUsed + zend_hash_num_elements(ht) > 0) { + zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1); + ZEND_HASH_FILL_PACKED(result_ht) { + ZEND_HASH_PACKED_FOREACH_VAL(ht, val) { + if (UNEXPECTED(Z_ISREF_P(val)) && + UNEXPECTED(Z_REFCOUNT_P(val) == 1)) { + val = Z_REFVAL_P(val); + } + Z_TRY_ADDREF_P(val); + ZEND_HASH_FILL_ADD(val); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FILL_END(); + } } else { zend_string *key; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 35f4e558dc93f..677166304f506 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2819,17 +2819,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_UNPACK_SPEC_HANDLER( zval *val; if (HT_IS_PACKED(ht) && (zend_hash_num_elements(result_ht) == 0 || HT_IS_PACKED(result_ht))) { - zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1); - ZEND_HASH_FILL_PACKED(result_ht) { - ZEND_HASH_PACKED_FOREACH_VAL(ht, val) { - if (UNEXPECTED(Z_ISREF_P(val)) && - UNEXPECTED(Z_REFCOUNT_P(val) == 1)) { - val = Z_REFVAL_P(val); - } - Z_TRY_ADDREF_P(val); - ZEND_HASH_FILL_ADD(val); - } ZEND_HASH_FOREACH_END(); - } ZEND_HASH_FILL_END(); + /* zend_hash_extend() skips initialization when the number of elements is 0, + * but the code below expects that result_ht is initialized as packed. + * We can just skip the work in that case. */ + if (result_ht->nNumUsed + zend_hash_num_elements(ht) > 0) { + zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1); + ZEND_HASH_FILL_PACKED(result_ht) { + ZEND_HASH_PACKED_FOREACH_VAL(ht, val) { + if (UNEXPECTED(Z_ISREF_P(val)) && + UNEXPECTED(Z_REFCOUNT_P(val) == 1)) { + val = Z_REFVAL_P(val); + } + Z_TRY_ADDREF_P(val); + ZEND_HASH_FILL_ADD(val); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FILL_END(); + } } else { zend_string *key; diff --git a/docs/release-process.md b/docs/release-process.md index 41a24481389ed..08b95df53513f 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -878,25 +878,37 @@ If you choose to create a patch-level release, follow these steps: mailinglist. -## Feature freeze +## Soft feature freeze -A major/minor version [feature freeze][] occurs with the first beta release. -Specifically, it occurs when the first beta release is packaged, which means the -feature freeze occurs two days before the first beta release. +A major/minor version soft feature freeze occurs with the first beta release. +This is a soft feature freeze because features can still be merged with RM +approval. -The feature freeze for `php-src` means that we will not accept any new features -after the date of the feature freeze. For any RFCs to be included in the new -version, they should be discussed and have the voting polls closed no later than -the feature freeze date. However, this does not mean the new feature must have a -complete implementation by this date. - -Following the feature freeze, the focus of work for the new version will be on -fixing bugs, writing tests, and completing/polishing all accepted features. +For any RFCs to be included in the new release, they should be discussed and +have their voting polls closed no later than when the first beta is released. +However, this does not mean the new feature must have a complete implementation +by this date. Such implementation can be merged only with RM approval and must +be done before the hard feature freeze. As a courtesy to the community, the release managers should remind others about -the upcoming feature freeze by posting reminders to internals@lists.php.net at -4-weeks, 3-weeks, 2-weeks, and 1-week prior to the feature freeze. This is a -recommendation and the intervals may vary based on work load. +the upcoming soft feature freeze by posting reminders to +internals@lists.php.net at 5 weeks, 4 weeks, 3 weeks, 2 weeks, and 1 week prior +to this feature freeze. This is a recommendation and the intervals may vary +based on workload. The reminder should also contain a note with dates for +the last allowed RFC to start voting. + +## Hard feature freeze + +A major/minor version hard [feature freeze][] occurs with the first RC release. +Specifically, it occurs when the first RC release is packaged, which means the +hard feature freeze occurs two days before the first RC release. + +The hard feature freeze for php-src means that we will not accept any new +features after the date of the hard feature freeze. + +Following the hard feature freeze, the focus of work for the new version will +be on fixing bugs, writing tests, and preparing documentation for all accepted +features. ## Forking a new version branch diff --git a/ext/standard/tests/file/bug81145.phpt b/ext/standard/tests/file/bug81145.phpt index f3258ff6019e9..27026176193f3 100644 --- a/ext/standard/tests/file/bug81145.phpt +++ b/ext/standard/tests/file/bug81145.phpt @@ -9,8 +9,8 @@ if (PHP_OS_FAMILY !== "Windows") { $src = __DIR__ . "/bug81145_src.bin"; define('SIZE_4G', 0x100000000); exec("fallocate -l " . (SIZE_4G-0x100) . " " . escapeshellarg($src), $output, $status); - if ($status !== 0) die("skip fallocate() not supported"); @unlink(__DIR__ . "/bug81145_src.bin"); + if ($status !== 0) die("skip fallocate() not supported"); } ?> --CONFLICTS--