From 0f2ddec7abdf05d35c7184f52546e9aba89feb9d Mon Sep 17 00:00:00 2001 From: Volker Dusch Date: Tue, 24 Mar 2026 17:30:51 +0100 Subject: [PATCH 01/24] PHP-8.5 is now for PHP 8.5.6-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 221587fc48a4..07d13468bb53 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.5.5 +?? ??? ????, PHP 8.5.6 + + +26 Mar 2026, PHP 8.5.5 - Core: . Fixed bug GH-20672 (Incorrect property_info sizing for locally shadowed diff --git a/Zend/zend.h b/Zend/zend.h index 2d214bab196d..d1c0266c7147 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.5.5-dev" +#define ZEND_VERSION "4.5.6-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index e4a477dae30f..07e64e74887c 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.5.5-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.5.6-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 aae2ff323259..cea66d0c7fb6 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 5 -#define PHP_RELEASE_VERSION 5 +#define PHP_RELEASE_VERSION 6 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.5.5-dev" -#define PHP_VERSION_ID 80505 +#define PHP_VERSION "8.5.6-dev" +#define PHP_VERSION_ID 80506 From f8e4f641db89d5831c77eebb4b4fd7c42bf33bd4 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Tue, 24 Mar 2026 12:34:47 -0400 Subject: [PATCH 02/24] [skip ci] Regenerate ext/fileinfo/libmagic.patch (GH-21509) Run ext/fileinfo/generate_patch.sh to update PHP's patch against file-5.46. In 399cb4ca8 the PHP copy of libmagic was updated but the patch re-roll was overlooked. --- ext/fileinfo/libmagic.patch | 72 ++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/ext/fileinfo/libmagic.patch b/ext/fileinfo/libmagic.patch index 4eb7ccd336f8..d2db3c044d3f 100644 --- a/ext/fileinfo/libmagic.patch +++ b/ext/fileinfo/libmagic.patch @@ -1,6 +1,6 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c ---- libmagic.orig/apprentice.c 2024-11-27 16:37:00.000000000 +0100 -+++ libmagic/apprentice.c 2025-02-09 02:25:02.364884555 +0100 +--- libmagic.orig/apprentice.c 2024-11-27 10:37:00.000000000 -0500 ++++ libmagic/apprentice.c 2026-03-20 12:10:19.777614667 -0400 @@ -32,7 +32,7 @@ #include "file.h" @@ -325,14 +325,14 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c // Don't warn for DER if (mpa.type == FILE_DER) return 0; -@@ -1151,6 +1075,7 @@ +@@ -1150,6 +1074,7 @@ + ma->mp->desc); file_mdump(ma->mp); file_mdump(mb->mp); +#endif return 0; } return x > 0 ? -1 : 1; - } @@ -1303,7 +1228,7 @@ size_t incr = mset[i].max + ALLOC_INCR; @@ -954,8 +954,8 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c if (ma[j].cont_level == 0) break; diff -u libmagic.orig/ascmagic.c libmagic/ascmagic.c ---- libmagic.orig/ascmagic.c 2024-06-19 18:18:53.000000000 +0200 -+++ libmagic/ascmagic.c 2025-02-09 01:20:19.757840211 +0100 +--- libmagic.orig/ascmagic.c 2024-06-19 12:18:53.000000000 -0400 ++++ libmagic/ascmagic.c 2026-03-19 16:25:42.998672674 -0400 @@ -96,7 +96,7 @@ rv = file_ascmagic_with_encoding(ms, &bb, ubuf, ulen, code, type, text); @@ -996,8 +996,8 @@ diff -u libmagic.orig/ascmagic.c libmagic/ascmagic.c return rv; } diff -u libmagic.orig/buffer.c libmagic/buffer.c ---- libmagic.orig/buffer.c 2024-06-19 18:18:53.000000000 +0200 -+++ libmagic/buffer.c 2025-02-09 01:20:19.757910844 +0100 +--- libmagic.orig/buffer.c 2024-06-19 12:18:53.000000000 -0400 ++++ libmagic/buffer.c 2026-03-19 16:25:42.998672674 -0400 @@ -31,19 +31,21 @@ #endif /* lint */ @@ -1055,8 +1055,8 @@ diff -u libmagic.orig/buffer.c libmagic/buffer.c goto out; } diff -u libmagic.orig/cdf.c libmagic/cdf.c ---- libmagic.orig/cdf.c 2024-11-25 22:24:59.000000000 +0100 -+++ libmagic/cdf.c 2025-02-09 01:25:00.187641434 +0100 +--- libmagic.orig/cdf.c 2024-11-25 16:24:59.000000000 -0500 ++++ libmagic/cdf.c 2026-03-19 16:25:42.998672674 -0400 @@ -43,7 +43,9 @@ #include #endif @@ -1286,8 +1286,8 @@ diff -u libmagic.orig/cdf.c libmagic/cdf.c #endif diff -u libmagic.orig/cdf.h libmagic/cdf.h ---- libmagic.orig/cdf.h 2024-11-25 22:18:55.000000000 +0100 -+++ libmagic/cdf.h 2025-02-09 01:23:35.871635744 +0100 +--- libmagic.orig/cdf.h 2024-11-25 16:18:55.000000000 -0500 ++++ libmagic/cdf.h 2026-03-19 16:25:42.990672671 -0400 @@ -37,8 +37,6 @@ #ifdef WIN32 @@ -1439,8 +1439,8 @@ diff -u libmagic.orig/cdf.h libmagic/cdf.h diff -u libmagic.orig/compress.c libmagic/compress.c ---- libmagic.orig/compress.c 2024-11-10 17:52:27.000000000 +0100 -+++ libmagic/compress.c 2025-02-09 01:59:42.978538071 +0100 +--- libmagic.orig/compress.c 2024-11-10 11:52:27.000000000 -0500 ++++ libmagic/compress.c 2026-03-20 12:10:19.777614667 -0400 @@ -64,13 +64,14 @@ #if defined(HAVE_SYS_TIME_H) #include @@ -1666,8 +1666,8 @@ diff -u libmagic.orig/compress.c libmagic/compress.c #endif +#endif diff -u libmagic.orig/der.c libmagic/der.c ---- libmagic.orig/der.c 2024-11-25 23:31:53.000000000 +0100 -+++ libmagic/der.c 2025-02-09 01:20:19.770853011 +0100 +--- libmagic.orig/der.c 2024-11-25 17:31:53.000000000 -0500 ++++ libmagic/der.c 2026-03-19 16:25:43.002672676 -0400 @@ -54,7 +54,9 @@ #include "magic.h" #include "der.h" @@ -1679,8 +1679,8 @@ diff -u libmagic.orig/der.c libmagic/der.c #include #endif diff -u libmagic.orig/der.h libmagic/der.h ---- libmagic.orig/der.h 2024-11-25 22:26:18.000000000 +0100 -+++ libmagic/der.h 2023-04-09 22:21:58.195018580 +0200 +--- libmagic.orig/der.h 2024-11-25 16:26:18.000000000 -0500 ++++ libmagic/der.h 2026-03-19 16:25:43.006672678 -0400 @@ -24,5 +24,5 @@ * POSSIBILITY OF SUCH DAMAGE. */ @@ -1690,8 +1690,8 @@ diff -u libmagic.orig/der.h libmagic/der.h +extern int der_offs(struct magic_set *, struct magic *, size_t); +extern int der_cmp(struct magic_set *, struct magic *); diff -u libmagic.orig/encoding.c libmagic/encoding.c ---- libmagic.orig/encoding.c 2024-10-29 21:56:48.000000000 +0100 -+++ libmagic/encoding.c 2025-02-09 01:20:19.770879123 +0100 +--- libmagic.orig/encoding.c 2024-10-29 16:56:48.000000000 -0400 ++++ libmagic/encoding.c 2026-03-19 16:25:43.010672679 -0400 @@ -97,7 +97,7 @@ nbytes = ms->encoding_max; @@ -1726,8 +1726,8 @@ diff -u libmagic.orig/encoding.c libmagic/encoding.c return rv; } diff -u libmagic.orig/file.h libmagic/file.h ---- libmagic.orig/file.h 2024-11-27 16:37:00.000000000 +0100 -+++ libmagic/file.h 2025-02-09 01:47:36.242811911 +0100 +--- libmagic.orig/file.h 2024-11-27 10:37:00.000000000 -0500 ++++ libmagic/file.h 2026-03-24 10:45:21.427536159 -0400 @@ -27,15 +27,13 @@ */ /* @@ -1936,8 +1936,8 @@ diff -u libmagic.orig/file.h libmagic/file.h #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H) && !defined(QUICK) #define QUICK diff -u libmagic.orig/fsmagic.c libmagic/fsmagic.c ---- libmagic.orig/fsmagic.c 2024-06-19 18:18:53.000000000 +0200 -+++ libmagic/fsmagic.c 2025-02-09 01:20:19.770987982 +0100 +--- libmagic.orig/fsmagic.c 2024-06-19 12:18:53.000000000 -0400 ++++ libmagic/fsmagic.c 2026-03-19 16:25:43.006672678 -0400 @@ -66,26 +66,10 @@ # define minor(dev) ((dev) & 0xff) #endif @@ -2229,8 +2229,8 @@ diff -u libmagic.orig/fsmagic.c libmagic/fsmagic.c #ifndef __COHERENT__ case S_IFSOCK: diff -u libmagic.orig/funcs.c libmagic/funcs.c ---- libmagic.orig/funcs.c 2024-06-19 18:18:53.000000000 +0200 -+++ libmagic/funcs.c 2025-02-09 01:29:25.403659334 +0100 +--- libmagic.orig/funcs.c 2024-06-19 12:18:53.000000000 -0400 ++++ libmagic/funcs.c 2026-03-19 16:25:42.990672671 -0400 @@ -66,7 +66,7 @@ file_private void file_clearbuf(struct magic_set *ms) @@ -2592,8 +2592,8 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c file_protected int file_clear_closexec(int fd) { diff -u libmagic.orig/magic.c libmagic/magic.c ---- libmagic.orig/magic.c 2024-06-19 18:18:53.000000000 +0200 -+++ libmagic/magic.c 2025-02-09 01:20:19.771155033 +0100 +--- libmagic.orig/magic.c 2024-06-19 12:18:53.000000000 -0400 ++++ libmagic/magic.c 2026-03-20 12:10:19.777614667 -0400 @@ -25,11 +25,6 @@ * SUCH DAMAGE. */ @@ -3066,8 +3066,8 @@ diff -u libmagic.orig/magic.c libmagic/magic.c } return file_getbuffer(ms); diff -u libmagic.orig/magic.h libmagic/magic.h ---- libmagic.orig/magic.h 2025-02-09 12:43:22.903059789 +0100 -+++ libmagic/magic.h 2025-02-09 01:39:57.110146603 +0100 +--- libmagic.orig/magic.h 2026-03-24 10:45:56.975553410 -0400 ++++ libmagic/magic.h 2026-03-20 12:10:19.777614667 -0400 @@ -47,8 +47,6 @@ * extensions */ #define MAGIC_COMPRESS_TRANSP 0x2000000 /* Check inside compressed files @@ -3109,8 +3109,8 @@ diff -u libmagic.orig/magic.h libmagic/magic.h const char *magic_buffer(magic_t, const void *, size_t); diff -u libmagic.orig/print.c libmagic/print.c ---- libmagic.orig/print.c 2024-10-06 19:04:42.000000000 +0200 -+++ libmagic/print.c 2025-02-09 01:36:41.713156291 +0100 +--- libmagic.orig/print.c 2024-10-06 13:04:42.000000000 -0400 ++++ libmagic/print.c 2026-03-19 16:25:42.982672668 -0400 @@ -74,7 +74,7 @@ if (m->mask_op & FILE_OPINVERSE) (void) fputc('~', stderr); @@ -3187,8 +3187,8 @@ diff -u libmagic.orig/print.c libmagic/print.c if (pp == NULL) goto out; diff -u libmagic.orig/readcdf.c libmagic/readcdf.c ---- libmagic.orig/readcdf.c 2024-11-25 22:07:46.000000000 +0100 -+++ libmagic/readcdf.c 2025-02-09 01:20:19.771337672 +0100 +--- libmagic.orig/readcdf.c 2024-11-25 16:07:46.000000000 -0500 ++++ libmagic/readcdf.c 2026-03-19 16:25:43.002672676 -0400 @@ -31,7 +31,9 @@ #include @@ -3307,8 +3307,8 @@ diff -u libmagic.orig/readcdf.c libmagic/readcdf.c /* If we handled it already, return */ if (i != -1) diff -u libmagic.orig/softmagic.c libmagic/softmagic.c ---- libmagic.orig/softmagic.c 2024-11-27 16:37:00.000000000 +0100 -+++ libmagic/softmagic.c 2025-02-09 01:21:46.845689318 +0100 +--- libmagic.orig/softmagic.c 2024-11-27 10:37:00.000000000 -0500 ++++ libmagic/softmagic.c 2026-03-19 16:25:42.986672670 -0400 @@ -32,7 +32,7 @@ #include "file.h" From 9caa0a7d501710d009db4778091831df6aa1b1ff Mon Sep 17 00:00:00 2001 From: Jorg Sowa Date: Sun, 22 Mar 2026 18:52:31 +0100 Subject: [PATCH 03/24] Fix bc_str2num accepting strings with embedded null bytes Closes GH-21492 --- NEWS | 3 + ext/bcmath/libbcmath/src/str2num.c | 6 +- .../tests/sec_embedded_null_truncation.phpt | 59 +++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 ext/bcmath/tests/sec_embedded_null_truncation.phpt diff --git a/NEWS b/NEWS index 55b0d28000bc..e2df869dfbc7 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,9 @@ PHP NEWS ReflectionProperty::skipLazyInitialization after failed LazyProxy initialization). (Arnaud) +- BCMath: + . Added NUL-byte validation to BCMath functions. (jorgsowa) + - Date: . Update timelib to 2022.16. (Derick) diff --git a/ext/bcmath/libbcmath/src/str2num.c b/ext/bcmath/libbcmath/src/str2num.c index 11d71ae492ad..b6f3d736f8da 100644 --- a/ext/bcmath/libbcmath/src/str2num.c +++ b/ext/bcmath/libbcmath/src/str2num.c @@ -131,7 +131,7 @@ bool bc_str2num(bc_num *num, const char *str, const char *end, size_t scale, siz const char *decimal_point = (*ptr == '.') ? ptr : NULL; /* If a non-digit and non-decimal-point indicator is in the string, i.e. an invalid character */ - if (UNEXPECTED(!decimal_point && *ptr != '\0')) { + if (UNEXPECTED(!decimal_point && ptr != end)) { goto fail; } @@ -140,7 +140,7 @@ bool bc_str2num(bc_num *num, const char *str, const char *end, size_t scale, siz /* search */ fractional_ptr = fractional_end = decimal_point + 1; /* For strings that end with a decimal point, such as "012." */ - if (UNEXPECTED(*fractional_ptr == '\0')) { + if (UNEXPECTED(fractional_ptr == end)) { if (full_scale) { *full_scale = 0; } @@ -149,7 +149,7 @@ bool bc_str2num(bc_num *num, const char *str, const char *end, size_t scale, siz /* validate */ fractional_end = bc_count_digits(fractional_ptr, end); - if (UNEXPECTED(*fractional_end != '\0')) { + if (UNEXPECTED(fractional_end != end)) { /* invalid num */ goto fail; } diff --git a/ext/bcmath/tests/sec_embedded_null_truncation.phpt b/ext/bcmath/tests/sec_embedded_null_truncation.phpt new file mode 100644 index 000000000000..157810ecbb3a --- /dev/null +++ b/ext/bcmath/tests/sec_embedded_null_truncation.phpt @@ -0,0 +1,59 @@ +--TEST-- +bcmath strings with embedded null bytes must be rejected as not well-formed +--EXTENSIONS-- +bcmath +--FILE-- + bcadd($s, "0"), + fn($s) => bcsub($s, "0"), + fn($s) => bcmul($s, "1"), + fn($s) => bcdiv($s, "1"), + fn($s) => bcmod($s, "7"), + fn($s) => bcpow($s, "1"), + fn($s) => bccomp($s, "0"), + fn($s) => bcsqrt($s), +]; + +foreach ($cases as $s) { + foreach ($calls as $fn) { + try { + $fn($s); + echo "FAIL: accepted\n"; + } catch (\ValueError $e) { + echo $e->getMessage() . "\n"; + } + } +} +?> +--EXPECT-- +bcadd(): Argument #1 ($num1) is not well-formed +bcsub(): Argument #1 ($num1) is not well-formed +bcmul(): Argument #1 ($num1) is not well-formed +bcdiv(): Argument #1 ($num1) is not well-formed +bcmod(): Argument #1 ($num1) is not well-formed +bcpow(): Argument #1 ($num) is not well-formed +bccomp(): Argument #1 ($num1) is not well-formed +bcsqrt(): Argument #1 ($num) is not well-formed +bcadd(): Argument #1 ($num1) is not well-formed +bcsub(): Argument #1 ($num1) is not well-formed +bcmul(): Argument #1 ($num1) is not well-formed +bcdiv(): Argument #1 ($num1) is not well-formed +bcmod(): Argument #1 ($num1) is not well-formed +bcpow(): Argument #1 ($num) is not well-formed +bccomp(): Argument #1 ($num1) is not well-formed +bcsqrt(): Argument #1 ($num) is not well-formed +bcadd(): Argument #1 ($num1) is not well-formed +bcsub(): Argument #1 ($num1) is not well-formed +bcmul(): Argument #1 ($num1) is not well-formed +bcdiv(): Argument #1 ($num1) is not well-formed +bcmod(): Argument #1 ($num1) is not well-formed +bcpow(): Argument #1 ($num) is not well-formed +bccomp(): Argument #1 ($num1) is not well-formed +bcsqrt(): Argument #1 ($num) is not well-formed From ce1761e3fe0c73b14184f55848a9b2c94a010a5e Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 24 Mar 2026 17:09:20 +0000 Subject: [PATCH 04/24] ext/dom: add a const qualifier in dom_objects_set_class_ex()(#21511) --- ext/dom/php_dom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 57fa5e71f6bc..fe2810689193 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -1496,7 +1496,7 @@ void dom_objects_free_storage(zend_object *object) static void dom_objects_set_class_ex(zend_class_entry *class_type, dom_object *intern) { - zend_class_entry *base_class = class_type; + const zend_class_entry *base_class = class_type; while ((base_class->type != ZEND_INTERNAL_CLASS || base_class->info.internal.module->module_number != dom_module_entry.module_number) && base_class->parent != NULL) { base_class = base_class->parent; } From 118fa2ce5eb12a0a1d2d4f39d20ae780922204d6 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 24 Mar 2026 17:09:37 +0000 Subject: [PATCH 05/24] ext/mysqli: add a const qualifier in mysqli_objects_new() (#21510) --- ext/mysqli/mysqli.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index caefd9432d14..a077972f5167 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -360,12 +360,11 @@ HashTable *mysqli_object_get_debug_info(zend_object *object, int *is_temp) PHP_MYSQLI_EXPORT(zend_object *) mysqli_objects_new(zend_class_entry *class_type) { mysqli_object *intern; - zend_class_entry *mysqli_base_class; zend_object_handlers *handlers; intern = zend_object_alloc(sizeof(mysqli_object), class_type); - mysqli_base_class = class_type; + const zend_class_entry *mysqli_base_class = class_type; while (mysqli_base_class->type != ZEND_INTERNAL_CLASS && mysqli_base_class->parent != NULL) { mysqli_base_class = mysqli_base_class->parent; From 674473daa9f1d11274a62c89b5f6f35a792244f1 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 24 Mar 2026 17:09:59 +0000 Subject: [PATCH 06/24] ext/xsl: add const qualifiers when iteration over a CE's parents (#21513) And rename the variables to proper English. --- ext/xsl/xsltprocessor.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c index 1d073822b462..823c56f1cfb5 100644 --- a/ext/xsl/xsltprocessor.c +++ b/ext/xsl/xsltprocessor.c @@ -430,20 +430,18 @@ PHP_METHOD(XSLTProcessor, transformToDoc) if (newdocp) { if (ret_class) { - zend_string *curclass_name; - zend_class_entry *curce; php_libxml_node_object *interndoc; - curce = Z_OBJCE_P(docp); - curclass_name = curce->name; - while (curce->parent != NULL) { - curce = curce->parent; + const zend_class_entry *current_ce = Z_OBJCE_P(docp); + const zend_string *current_class_name = current_ce->name; + while (current_ce->parent != NULL) { + current_ce = current_ce->parent; } - if (!instanceof_function(ret_class, curce)) { + if (!instanceof_function(ret_class, current_ce)) { xmlFreeDoc(newdocp); zend_argument_type_error(2, "must be a class name compatible with %s, %s given", - ZSTR_VAL(curclass_name), ZSTR_VAL(ret_class->name) + ZSTR_VAL(current_class_name), ZSTR_VAL(ret_class->name) ); RETURN_THROWS(); } From a8cc04dc31546d0fc0723adf44bb82f6f462ea4e Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Wed, 25 Mar 2026 01:40:47 +0800 Subject: [PATCH 07/24] Optimize JSON pretty print indentation performance (GH-21474) Grow the string buffer in advance, avoiding repeated reallocations for each indentation level. --- UPGRADING | 2 ++ ext/json/json_encoder.c | 1 + 2 files changed, 3 insertions(+) diff --git a/UPGRADING b/UPGRADING index 113258ebbd3e..b7b160820bb2 100644 --- a/UPGRADING +++ b/UPGRADING @@ -252,6 +252,8 @@ PHP 8.6 UPGRADE NOTES - JSON: . Improve performance of encoding arrays and objects. + . Improved performance of indentation generation in json_encode() + when using PHP_JSON_PRETTY_PRINT. - Standard: . Improved performance of array_fill_keys(). diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c index 186485c05c6f..d84917e95c7b 100644 --- a/ext/json/json_encoder.c +++ b/ext/json/json_encoder.c @@ -54,6 +54,7 @@ static inline void php_json_pretty_print_char(smart_str *buf, int options, char static inline void php_json_pretty_print_indent(smart_str *buf, int options, const php_json_encoder *encoder) /* {{{ */ { if (options & PHP_JSON_PRETTY_PRINT) { + smart_str_alloc(buf, encoder->depth * 4, 0); for (int i = 0; i < encoder->depth; ++i) { smart_str_appendl(buf, " ", 4); } From 8af4e8096895b1412a39f86eedb8c48057fdc1dc Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 9 Mar 2026 16:43:50 +0000 Subject: [PATCH 08/24] ext/opcache: formalize return type of accel_restart_is_active() to bool --- ext/opcache/ZendAccelerator.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 0c6e405d0410..00ea60cb53ec 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -312,7 +312,7 @@ static inline void accel_restart_leave(void) #endif } -static inline int accel_restart_is_active(void) +static inline bool accel_restart_is_active(void) { if (ZCSG(restart_in_progress)) { #ifndef ZEND_WIN32 @@ -325,19 +325,19 @@ static inline int accel_restart_is_active(void) if (fcntl(lock_file, F_GETLK, &restart_check) == -1) { zend_accel_error(ACCEL_LOG_DEBUG, "RestartC: %s (%d)", strerror(errno), errno); - return FAILURE; + return true; } if (restart_check.l_type == F_UNLCK) { ZCSG(restart_in_progress) = false; - return 0; + return false; } else { - return 1; + return true; } #else return LOCKVAL(restart_in) != 0; #endif } - return 0; + return false; } /* Creates a read lock for SHM access */ From 046b44e12855d9979a501464fa732233f067687e Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 9 Mar 2026 16:47:09 +0000 Subject: [PATCH 09/24] ext/opcache: formalize return type of zend_get_stream_timestamp() to zend_result --- ext/opcache/ZendAccelerator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 00ea60cb53ec..bfd96fec0ccd 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -964,7 +964,7 @@ static inline bool accel_is_inactive(void) return false; } -static int zend_get_stream_timestamp(const char *filename, zend_stat_t *statbuf) +static zend_result zend_get_stream_timestamp(const char *filename, zend_stat_t *statbuf) { php_stream_wrapper *wrapper; php_stream_statbuf stream_statbuf; From c136801ddf4e35bd017aca3c6a4664a93464f7ca Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 9 Mar 2026 16:48:03 +0000 Subject: [PATCH 10/24] ext/opcache: formalize return type of do_validate_timestamps() to zend_result --- ext/opcache/ZendAccelerator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index bfd96fec0ccd..2155e410ed99 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -1137,11 +1137,11 @@ accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_ return statbuf.st_mtime; } -static inline int do_validate_timestamps(zend_persistent_script *persistent_script, zend_file_handle *file_handle) +static inline zend_result do_validate_timestamps(zend_persistent_script *persistent_script, zend_file_handle *file_handle) { zend_file_handle ps_handle; zend_string *full_path_ptr = NULL; - int ret; + zend_result ret; /** check that the persistent script is indeed the same file we cached * (if part of the path is a symlink than it possible that the user will change it) From b431c36e47ff1a8df985ab0f5e21b1d6b270fcd4 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 9 Mar 2026 16:55:08 +0000 Subject: [PATCH 11/24] ext/opcache: formalize return type of check_persistent_script_access() to bool --- ext/opcache/ZendAccelerator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 2155e410ed99..0e2918cce77f 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -1993,7 +1993,7 @@ static zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int return op_array; } -static int check_persistent_script_access(zend_persistent_script *persistent_script) +static bool check_persistent_script_access(zend_persistent_script *persistent_script) { char *phar_path, *ptr; if ((ZSTR_LEN(persistent_script->script.filename) Date: Mon, 9 Mar 2026 16:46:11 +0000 Subject: [PATCH 12/24] ext/opcache: reduce scope of variable --- ext/opcache/ZendAccelerator.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 0e2918cce77f..6ca8171c0a83 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -591,13 +591,12 @@ static zend_string* ZEND_FASTCALL accel_new_interned_string_for_php(zend_string static zend_always_inline zend_string *accel_find_interned_string_ex(zend_ulong h, const char *str, size_t size) { zend_string_table_pos_t pos; - zend_string *s; /* check for existing interned string */ pos = *STRTAB_HASH_TO_SLOT(&ZCSG(interned_strings), h); if (EXPECTED(pos != STRTAB_INVALID_POS)) { do { - s = STRTAB_POS_TO_STR(&ZCSG(interned_strings), pos); + zend_string *s = STRTAB_POS_TO_STR(&ZCSG(interned_strings), pos); if (EXPECTED(ZSTR_H(s) == h) && zend_string_equals_cstr(s, str, size)) { return s; } @@ -720,14 +719,13 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int Z_FUNC(q->val)->common.function_name = new_interned_string(Z_FUNC(q->val)->common.function_name); } if (Z_FUNC(q->val)->common.scope == ce) { - uint32_t i; uint32_t num_args = Z_FUNC(q->val)->common.num_args + 1; zend_arg_info *arg_info = Z_FUNC(q->val)->common.arg_info - 1; if (Z_FUNC(q->val)->common.fn_flags & ZEND_ACC_VARIADIC) { num_args++; } - for (i = 0 ; i < num_args; i++) { + for (uint32_t i = 0 ; i < num_args; i++) { if (i > 0) { arg_info[i].name = new_interned_string(arg_info[i].name); if (arg_info[i].default_value) { @@ -860,7 +858,6 @@ static void accel_use_shm_interned_strings(void) #ifndef ZEND_WIN32 static inline void kill_all_lockers(struct flock *mem_usage_check) { - int tries; /* so that other process won't try to force while we are busy cleaning up */ ZCSG(force_restart_time) = 0; while (mem_usage_check->l_pid > 0) { @@ -868,7 +865,7 @@ static inline void kill_all_lockers(struct flock *mem_usage_check) int signal = SIGTERM; errno = 0; bool success = false; - tries = 10; + int tries = 10; while (tries--) { zend_accel_error(ACCEL_LOG_WARNING, "Attempting to kill locker %d", mem_usage_check->l_pid); @@ -1225,8 +1222,6 @@ zend_string *accel_make_persistent_key(zend_string *str) { const char *path = ZSTR_VAL(str); size_t path_length = ZSTR_LEN(str); - char *key; - int key_length; ZEND_ASSERT(GC_REFCOUNT(ZCG(key)) == 1); ZSTR_LEN(ZCG(key)) = 0; @@ -1245,7 +1240,6 @@ zend_string *accel_make_persistent_key(zend_string *str) const char *include_path = NULL, *cwd = NULL; int include_path_len = 0, cwd_len = 0; zend_string *parent_script = NULL; - size_t parent_script_len = 0; if (EXPECTED(ZCG(cwd_key_len))) { cwd = ZCG(cwd_key); @@ -1348,10 +1342,10 @@ zend_string *accel_make_persistent_key(zend_string *str) * since in itself, it may include colons (which we use to separate * different components of the key) */ - key = ZSTR_VAL(ZCG(key)); + char *key = ZSTR_VAL(ZCG(key)); memcpy(key, path, path_length); key[path_length] = ':'; - key_length = path_length + 1; + int key_length = path_length + 1; memcpy(key + key_length, cwd, cwd_len); key_length += cwd_len; @@ -1369,7 +1363,7 @@ zend_string *accel_make_persistent_key(zend_string *str) if (EXPECTED(EG(current_execute_data)) && EXPECTED((parent_script = zend_get_executed_filename_ex()) != NULL)) { - parent_script_len = ZSTR_LEN(parent_script); + size_t parent_script_len = ZSTR_LEN(parent_script); while (parent_script_len > 0) { --parent_script_len; if (IS_SLASH(ZSTR_VAL(parent_script)[parent_script_len])) { @@ -2341,7 +2335,6 @@ static zend_always_inline zend_inheritance_cache_entry* zend_accel_inheritance_c static zend_class_entry* zend_accel_inheritance_cache_get(zend_class_entry *ce, zend_class_entry *parent, zend_class_entry **traits_and_interfaces) { - uint32_t i; bool needs_autoload; zend_inheritance_cache_entry *entry = ce->inheritance_cache; @@ -2360,7 +2353,7 @@ static zend_class_entry* zend_accel_inheritance_cache_get(zend_class_entry *ce, return ce; } - for (i = 0; i < entry->dependencies_count; i++) { + for (uint32_t i = 0; i < entry->dependencies_count; i++) { zend_class_entry *ce = zend_lookup_class_ex(entry->dependencies[i].name, NULL, 0); if (ce == NULL) { @@ -3923,10 +3916,9 @@ static bool preload_try_resolve_constants(zend_class_entry *ce) ce->ce_flags &= ~ZEND_ACC_HAS_AST_CONSTANTS; } if (ce->default_properties_count) { - uint32_t i; bool resolved = true; - for (i = 0; i < ce->default_properties_count; i++) { + for (uint32_t i = 0; i < ce->default_properties_count; i++) { zend_property_info *prop = ce->properties_info_table[i]; if (!prop) { continue; @@ -4349,7 +4341,6 @@ static void preload_remove_empty_includes(void) static void preload_register_trait_methods(zend_class_entry *ce) { zend_op_array *op_array; - zend_property_info *info; ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { if (!(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) { @@ -4359,7 +4350,7 @@ static void preload_register_trait_methods(zend_class_entry *ce) { } ZEND_HASH_FOREACH_END(); if (ce->num_hooked_props > 0) { - ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, info) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, zend_property_info *info) { if (info->hooks) { for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) { if (info->hooks[i]) { From d50b91f4fee7bdf65379a2bd31c5f044d7fc716d Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 9 Mar 2026 16:41:41 +0000 Subject: [PATCH 13/24] ext/opcache: add const qualifiers --- ext/opcache/ZendAccelerator.c | 76 +++++++++++++++++------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 6ca8171c0a83..43625d6727f2 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -1053,7 +1053,7 @@ accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_ !EG(current_execute_data) && file_handle->primary_script) { - zend_stat_t *tmpbuf = sapi_module.get_stat(); + const zend_stat_t *tmpbuf = sapi_module.get_stat(); if (tmpbuf) { if (size) { @@ -1134,7 +1134,7 @@ accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_ return statbuf.st_mtime; } -static inline zend_result do_validate_timestamps(zend_persistent_script *persistent_script, zend_file_handle *file_handle) +static inline zend_result do_validate_timestamps(const zend_persistent_script *persistent_script, zend_file_handle *file_handle) { zend_file_handle ps_handle; zend_string *full_path_ptr = NULL; @@ -1239,7 +1239,7 @@ zend_string *accel_make_persistent_key(zend_string *str) } else { const char *include_path = NULL, *cwd = NULL; int include_path_len = 0, cwd_len = 0; - zend_string *parent_script = NULL; + const zend_string *parent_script = NULL; if (EXPECTED(ZCG(cwd_key_len))) { cwd = ZCG(cwd_key); @@ -1274,7 +1274,7 @@ zend_string *accel_make_persistent_key(zend_string *str) } if (str) { char buf[32]; - char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, STRTAB_STR_TO_POS(&ZCSG(interned_strings), str)); + const char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, STRTAB_STR_TO_POS(&ZCSG(interned_strings), str)); cwd_len = ZCG(cwd_key_len) = buf + sizeof(buf) - 1 - res; cwd = ZCG(cwd_key); @@ -1318,7 +1318,7 @@ zend_string *accel_make_persistent_key(zend_string *str) } if (str) { char buf[32]; - char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, STRTAB_STR_TO_POS(&ZCSG(interned_strings), str)); + const char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, STRTAB_STR_TO_POS(&ZCSG(interned_strings), str)); include_path_len = ZCG(include_path_key_len) = buf + sizeof(buf) - 1 - res; include_path = ZCG(include_path_key); @@ -1517,7 +1517,7 @@ static void zend_accel_add_key(zend_string *key, zend_accel_hash_entry *bucket) } } -static zend_always_inline bool is_phar_file(zend_string *filename) +static zend_always_inline bool is_phar_file(const zend_string *filename) { return filename && ZSTR_LEN(filename) >= sizeof(".phar") && !memcmp(ZSTR_VAL(filename) + ZSTR_LEN(filename) - (sizeof(".phar")-1), ".phar", sizeof(".phar")-1) && @@ -1987,7 +1987,7 @@ static zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int return op_array; } -static bool check_persistent_script_access(zend_persistent_script *persistent_script) +static bool check_persistent_script_access(const zend_persistent_script *persistent_script) { char *phar_path, *ptr; if ((ZSTR_LEN(persistent_script->script.filename)dependencies) { for (i = 0; i < entry->dependencies_count; i++) { - zend_class_entry *ce = zend_lookup_class_ex(entry->dependencies[i].name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); + const zend_class_entry *dependency_ce = zend_lookup_class_ex(entry->dependencies[i].name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); - if (ce != entry->dependencies[i].ce) { - if (!ce) { + if (dependency_ce != entry->dependencies[i].ce) { + if (!dependency_ce) { needs_autoload = true; } else { found = false; @@ -2354,9 +2354,9 @@ static zend_class_entry* zend_accel_inheritance_cache_get(zend_class_entry *ce, } for (uint32_t i = 0; i < entry->dependencies_count; i++) { - zend_class_entry *ce = zend_lookup_class_ex(entry->dependencies[i].name, NULL, 0); + const zend_class_entry *dependency_ce = zend_lookup_class_ex(entry->dependencies[i].name, NULL, 0); - if (ce == NULL) { + if (dependency_ce == NULL) { return NULL; } } @@ -2585,7 +2585,7 @@ static zend_string* persistent_zend_resolve_path(zend_string *filename) /* lookup by "not-real" path */ key = accel_make_persistent_key(filename); if (key) { - zend_accel_hash_entry *bucket = zend_accel_hash_find_entry(&ZCSG(hash), key); + const zend_accel_hash_entry *bucket = zend_accel_hash_find_entry(&ZCSG(hash), key); if (bucket != NULL) { zend_persistent_script *persistent_script = (zend_persistent_script *)bucket->data; if (!persistent_script->corrupted) { @@ -3640,7 +3640,7 @@ static void preload_shutdown(void) if (EG(function_table)) { ZEND_HASH_MAP_REVERSE_FOREACH_VAL(EG(function_table), zv) { - zend_function *func = Z_PTR_P(zv); + const zend_function *func = Z_PTR_P(zv); if (func->type == ZEND_INTERNAL_FUNCTION) { break; } @@ -3649,7 +3649,7 @@ static void preload_shutdown(void) if (EG(class_table)) { ZEND_HASH_MAP_REVERSE_FOREACH_VAL(EG(class_table), zv) { - zend_class_entry *ce = Z_PTR_P(zv); + const zend_class_entry *ce = Z_PTR_P(zv); if (ce->type == ZEND_INTERNAL_CLASS && Z_TYPE_P(zv) != IS_ALIAS_PTR) { break; } @@ -3676,7 +3676,7 @@ static void preload_restart(void) } } -static size_t preload_try_strip_filename(zend_string *filename) { +static size_t preload_try_strip_filename(const zend_string *filename) { /*FIXME: better way to handle eval()'d code? see COMPILED_STRING_DESCRIPTION_FORMAT */ if (ZSTR_LEN(filename) > sizeof(" eval()'d code") && *(ZSTR_VAL(filename) + ZSTR_LEN(filename) - sizeof(" eval()'d code")) == ':') { @@ -3797,17 +3797,17 @@ static void preload_sort_classes(void *base, size_t count, size_t siz, compare_f Bucket *b2; Bucket *end = b1 + count; Bucket tmp; - zend_class_entry *ce, *p; + const zend_class_entry *ce, *p; while (b1 < end) { try_again: - ce = (zend_class_entry*)Z_PTR(b1->val); + ce = Z_PTR(b1->val); if (ce->parent && (ce->ce_flags & ZEND_ACC_LINKED)) { p = ce->parent; if (p->type == ZEND_USER_CLASS) { b2 = b1 + 1; while (b2 < end) { - if (p == Z_PTR(b2->val)) { + if (p == Z_PTR(b2->val)) { tmp = *b1; *b1 = *b2; *b2 = tmp; @@ -3824,7 +3824,7 @@ static void preload_sort_classes(void *base, size_t count, size_t siz, compare_f if (p->type == ZEND_USER_CLASS) { b2 = b1 + 1; while (b2 < end) { - if (p == Z_PTR(b2->val)) { + if (p == Z_PTR(b2->val)) { tmp = *b1; *b1 = *b2; *b2 = tmp; @@ -3850,7 +3850,7 @@ static zend_result preload_resolve_deps(preload_error *error, const zend_class_e if (ce->parent_name) { zend_string *key = zend_string_tolower(ce->parent_name); - zend_class_entry *parent = zend_hash_find_ptr(EG(class_table), key); + const zend_class_entry *parent = zend_hash_find_ptr(EG(class_table), key); zend_string_release(key); if (!parent) { error->kind = "Unknown parent "; @@ -3861,7 +3861,7 @@ static zend_result preload_resolve_deps(preload_error *error, const zend_class_e if (ce->num_interfaces) { for (uint32_t i = 0; i < ce->num_interfaces; i++) { - zend_class_entry *interface = + const zend_class_entry *interface = zend_hash_find_ptr(EG(class_table), ce->interface_names[i].lc_name); if (!interface) { error->kind = "Unknown interface "; @@ -3873,7 +3873,7 @@ static zend_result preload_resolve_deps(preload_error *error, const zend_class_e if (ce->num_traits) { for (uint32_t i = 0; i < ce->num_traits; i++) { - zend_class_entry *trait = + const zend_class_entry *trait = zend_hash_find_ptr(EG(class_table), ce->trait_names[i].lc_name); if (!trait) { error->kind = "Unknown trait "; @@ -3978,7 +3978,7 @@ static void preload_error_cb(int type, zend_string *error_filename, const uint32 static void preload_remove_declares(zend_op_array *op_array) { zend_op *opline = op_array->opcodes; - zend_op *end = opline + op_array->last; + const zend_op *end = opline + op_array->last; uint32_t skip_dynamic_func_count = 0; zend_string *key; zend_op_array *func; @@ -4269,7 +4269,7 @@ static void preload_remove_empty_includes(void) if (script->empty) { bool empty = true; zend_op *opline = script->script.main_op_array.opcodes; - zend_op *end = opline + script->script.main_op_array.last; + const zend_op *end = opline + script->script.main_op_array.last; while (opline < end) { if (opline->opcode == ZEND_INCLUDE_OR_EVAL && @@ -4310,7 +4310,7 @@ static void preload_remove_empty_includes(void) /* remove empty includes */ ZEND_HASH_MAP_FOREACH_PTR(preload_scripts, script) { zend_op *opline = script->script.main_op_array.opcodes; - zend_op *end = opline + script->script.main_op_array.last; + const zend_op *end = opline + script->script.main_op_array.last; while (opline < end) { if (opline->opcode == ZEND_INCLUDE_OR_EVAL && @@ -4321,7 +4321,7 @@ static void preload_remove_empty_includes(void) zend_string *resolved_path = preload_resolve_path(Z_STR_P(RT_CONSTANT(opline, opline->op1))); if (resolved_path) { - zend_persistent_script *incl = zend_hash_find_ptr(preload_scripts, resolved_path); + const zend_persistent_script *incl = zend_hash_find_ptr(preload_scripts, resolved_path); if (incl && incl->empty && opline->result_type == IS_UNUSED) { MAKE_NOP(opline); } else { @@ -4339,7 +4339,7 @@ static void preload_remove_empty_includes(void) } ZEND_HASH_FOREACH_END(); } -static void preload_register_trait_methods(zend_class_entry *ce) { +static void preload_register_trait_methods(const zend_class_entry *ce) { zend_op_array *op_array; ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { @@ -4372,7 +4372,7 @@ static void preload_fix_trait_op_array(zend_op_array *op_array) return; } - zend_op_array *orig_op_array = zend_shared_alloc_get_xlat_entry(op_array->refcount); + const zend_op_array *orig_op_array = zend_shared_alloc_get_xlat_entry(op_array->refcount); ZEND_ASSERT(orig_op_array && "Must be in xlat table"); zend_string *function_name = op_array->function_name; @@ -4390,7 +4390,7 @@ static void preload_fix_trait_op_array(zend_op_array *op_array) op_array->static_variables = ht; } -static void preload_fix_trait_methods(zend_class_entry *ce) +static void preload_fix_trait_methods(const zend_class_entry *ce) { zend_op_array *op_array; @@ -4415,7 +4415,7 @@ static void preload_fix_trait_methods(zend_class_entry *ce) static void preload_optimize(zend_persistent_script *script) { - zend_class_entry *ce; + const zend_class_entry *ce; zend_persistent_script *tmp_script; zend_shared_alloc_init_xlat_table(); @@ -4512,10 +4512,10 @@ static zend_persistent_script* preload_script_in_shared_memory(zend_persistent_s static void preload_load(size_t orig_map_ptr_static_last) { /* Load into process tables */ - zend_script *script = &ZCSG(preload_script)->script; + const zend_script *script = &ZCSG(preload_script)->script; if (zend_hash_num_elements(&script->function_table)) { Bucket *p = script->function_table.arData; - Bucket *end = p + script->function_table.nNumUsed; + const Bucket *end = p + script->function_table.nNumUsed; zend_hash_extend(CG(function_table), CG(function_table)->nNumUsed + script->function_table.nNumUsed, 0); @@ -4526,7 +4526,7 @@ static void preload_load(size_t orig_map_ptr_static_last) if (zend_hash_num_elements(&script->class_table)) { Bucket *p = script->class_table.arData; - Bucket *end = p + script->class_table.nNumUsed; + const Bucket *end = p + script->class_table.nNumUsed; zend_hash_extend(CG(class_table), CG(class_table)->nNumUsed + script->class_table.nNumUsed, 0); @@ -4574,7 +4574,7 @@ static void preload_load(size_t orig_map_ptr_static_last) } #if HAVE_JIT -static void zend_accel_clear_call_graph_ptrs(zend_op_array *op_array) +static void zend_accel_clear_call_graph_ptrs(const zend_op_array *op_array) { ZEND_ASSERT(ZEND_USER_CODE(op_array->type)); zend_func_info *info = ZEND_FUNC_INFO(op_array); @@ -4584,9 +4584,9 @@ static void zend_accel_clear_call_graph_ptrs(zend_op_array *op_array) } } -static void accel_reset_arena_info(zend_persistent_script *script) +static void accel_reset_arena_info(const zend_persistent_script *script) { - zend_op_array *op_array; + const zend_op_array *op_array; zend_class_entry *ce; zend_accel_clear_call_graph_ptrs(&script->script.main_op_array); From bcdadd57fe8fda77a9aad4ef0896e7cec3354233 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 23 Mar 2026 10:32:51 +0000 Subject: [PATCH 14/24] ext/opcache: use type size_t instead of type int --- ext/opcache/ZendAccelerator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 43625d6727f2..3d6923d12158 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -1238,7 +1238,7 @@ zend_string *accel_make_persistent_key(zend_string *str) /* pass */ } else { const char *include_path = NULL, *cwd = NULL; - int include_path_len = 0, cwd_len = 0; + size_t include_path_len = 0, cwd_len = 0; const zend_string *parent_script = NULL; if (EXPECTED(ZCG(cwd_key_len))) { @@ -1345,7 +1345,7 @@ zend_string *accel_make_persistent_key(zend_string *str) char *key = ZSTR_VAL(ZCG(key)); memcpy(key, path, path_length); key[path_length] = ':'; - int key_length = path_length + 1; + size_t key_length = path_length + 1; memcpy(key + key_length, cwd, cwd_len); key_length += cwd_len; From 022fc4c9375efbe2f7884e9c4b883a30dcadcb10 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 7 Nov 2025 01:53:26 +0000 Subject: [PATCH 15/24] zend_builtin_functions.c: Use RETURN_THROW() for clarity --- Zend/zend_builtin_functions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 8cd2f764a35f..acd9eae93705 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -249,7 +249,7 @@ ZEND_FUNCTION(func_num_args) } if (zend_forbid_dynamic_call() == FAILURE) { - RETURN_LONG(-1); + RETURN_THROWS(); } RETURN_LONG(ZEND_CALL_NUM_ARGS(ex)); From 5b5b17a498ed569418214de47bee12903c6f2341 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 7 Nov 2025 02:12:06 +0000 Subject: [PATCH 16/24] zend_builtin_functions.c: use type uint32_t instead of int --- Zend/zend_builtin_functions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index acd9eae93705..d522d3d8107e 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -503,7 +503,7 @@ ZEND_FUNCTION(error_reporting) } /* }}} */ -static bool validate_constant_array_argument(HashTable *ht, int argument_number) /* {{{ */ +static bool validate_constant_array_argument(HashTable *ht, uint32_t argument_number) /* {{{ */ { bool ret = true; zval *val; From 82866cc11b12fe90fb09af32d3bf411ad4bb61e5 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 7 Nov 2025 02:02:50 +0000 Subject: [PATCH 17/24] zend_builtin_functions.c: use known string when possible --- Zend/zend_builtin_functions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index d522d3d8107e..b8c9f7612c46 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1547,7 +1547,7 @@ ZEND_FUNCTION(get_resource_type) if (resource_type) { RETURN_STRING(resource_type); } else { - RETURN_STRING("Unknown"); + RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_UNKNOWN_CAPITALIZED)); } } /* }}} */ From 4852e7ff962f2944b4060e3032e1c1d70ec5b977 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 7 Nov 2025 01:54:10 +0000 Subject: [PATCH 18/24] zend_builtin_functions.c: add const qualifiers --- Zend/zend_builtin_functions.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index b8c9f7612c46..561fee95ae42 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -626,7 +626,7 @@ ZEND_FUNCTION(get_class) } if (!obj) { - zend_class_entry *scope = zend_get_executed_scope(); + const zend_class_entry *scope = zend_get_executed_scope(); if (scope) { zend_error(E_DEPRECATED, "Calling get_class() without arguments is deprecated"); @@ -1026,7 +1026,6 @@ ZEND_FUNCTION(method_exists) static void _property_exists(zval *return_value, const zval *object, zend_string *property) { zend_class_entry *ce; - zend_property_info *property_info; if (Z_TYPE_P(object) == IS_STRING) { ce = zend_lookup_class(Z_STR_P(object)); @@ -1040,7 +1039,7 @@ static void _property_exists(zval *return_value, const zval *object, zend_string RETURN_THROWS(); } - property_info = zend_hash_find_ptr(&ce->properties_info, property); + const zend_property_info *property_info = zend_hash_find_ptr(&ce->properties_info, property); if (property_info != NULL && (!(property_info->flags & ZEND_ACC_PRIVATE) || property_info->ce == ce)) { @@ -1421,7 +1420,6 @@ static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int fla { zend_string *key; zval *zv; - zend_class_entry *ce; ZEND_PARSE_PARAMETERS_NONE(); @@ -1429,7 +1427,7 @@ static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int fla zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) { - ce = Z_PTR_P(zv); + const zend_class_entry *ce = Z_PTR_P(zv); if ((ce->ce_flags & (ZEND_ACC_LINKED|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT)) == flags && key && ZSTR_VAL(key)[0] != 0) { From db8b4b5b9a99a89bc7207333285ac22c556a601a Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 7 Nov 2025 02:08:38 +0000 Subject: [PATCH 19/24] zend_builtin_functions.c: remove some variable shadowing --- Zend/zend_builtin_functions.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 561fee95ae42..91a552372c39 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1885,7 +1885,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int zend_execute_data *call, *last_call = NULL; zend_object *object; bool fake_frame = false; - int lineno, frameno = 0; + int frameno = 0; zend_function *func; zend_string *filename; zend_string *include_filename = NULL; @@ -1906,12 +1906,12 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int EG(filename_override) = NULL; EG(lineno_override) = -1; - zend_string *filename = zend_get_executed_filename_ex(); - zend_long lineno = zend_get_executed_lineno(); - if (filename && (!zend_string_equals(filename, filename_override) || lineno != lineno_override)) { + zend_string *executed_filename = zend_get_executed_filename_ex(); + uint32_t lineno = zend_get_executed_lineno(); + if (executed_filename && (!zend_string_equals(executed_filename, filename_override) || lineno != lineno_override)) { stack_frame = zend_new_array(8); zend_hash_real_init_mixed(stack_frame); - ZVAL_STR_COPY(&tmp, filename); + ZVAL_STR_COPY(&tmp, executed_filename); _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FILE), &tmp, 1); ZVAL_LONG(&tmp, lineno); _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_LINE), &tmp, 1); @@ -1974,19 +1974,21 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int zval *arg = zend_get_zval_ptr(op_data, op_data->op1_type, &op_data->op1, call); if (Z_TYPE_P(arg) == IS_UNDEF) goto not_frameless_call; } - zend_function *func = ZEND_FLF_FUNC(opline); + zend_function *frameless_func = ZEND_FLF_FUNC(opline); /* Assume frameless functions are not recursive with themselves. * This condition may be true when observers are enabled: * Observers will put a call frame on top of the frameless opcode. */ - if (last_call && last_call->func == func) { + if (last_call && last_call->func == frameless_func) { goto not_frameless_call; } stack_frame = zend_new_array(8); zend_hash_real_init_mixed(stack_frame); - ZVAL_STR_COPY(&tmp, func->common.function_name); + ZVAL_STR_COPY(&tmp, frameless_func->common.function_name); _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp, 1); /* Steal file and line from the previous frame. */ if (call->func && ZEND_USER_CODE(call->func->common.type)) { + uint32_t lineno; + filename = call->func->op_array.filename; if (call->opline->opcode == ZEND_HANDLE_EXCEPTION) { if (EG(opline_before_exception)) { @@ -2038,6 +2040,8 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int zend_hash_real_init_mixed(stack_frame); if (prev && prev->func && ZEND_USER_CODE(prev->func->common.type)) { + uint32_t lineno; + filename = prev->func->op_array.filename; if (prev->opline->opcode == ZEND_HANDLE_EXCEPTION) { if (EG(opline_before_exception)) { From afd04afe0fcc2ccf85e1c7ca9b6c82939b038772 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 7 Nov 2025 02:16:04 +0000 Subject: [PATCH 20/24] zend_builtin_functions.c: refactor is_a_impl() to use early returns --- Zend/zend_builtin_functions.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 91a552372c39..8487b8032302 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -691,7 +691,6 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, bool only_subclass) /* {{{ * zend_string *class_name; const zend_class_entry *instance_ce; bool allow_string = only_subclass; - bool retval; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_ZVAL(obj) @@ -718,21 +717,19 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, bool only_subclass) /* {{{ * } if (!only_subclass && EXPECTED(zend_string_equals(instance_ce->name, class_name))) { - retval = 1; - } else { - const zend_class_entry *ce = zend_lookup_class_ex(class_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); - if (!ce) { - retval = 0; - } else { - if (only_subclass && instance_ce == ce) { - retval = 0; - } else { - retval = instanceof_function(instance_ce, ce); - } - } + RETURN_TRUE; + } + + const zend_class_entry *ce = zend_lookup_class_ex(class_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (!ce) { + RETURN_FALSE; + } + + if (only_subclass && instance_ce == ce) { + RETURN_FALSE; } - RETURN_BOOL(retval); + RETURN_BOOL(instanceof_function(instance_ce, ce)); } /* }}} */ From ee7d02d76dc8adfd5e2c32ecca0bdf0642860d25 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 7 Nov 2025 02:09:29 +0000 Subject: [PATCH 21/24] zend_builtin_functions.c: use RET{URN|VAL}_BOOL() when possible --- Zend/zend_builtin_functions.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 8487b8032302..0a0f50362598 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -590,11 +590,7 @@ ZEND_FUNCTION(define) /* non persistent */ ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); c.name = zend_string_copy(name); - if (zend_register_constant(&c) != NULL) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + RETURN_BOOL(zend_register_constant(&c) != NULL); } /* }}} */ @@ -608,11 +604,7 @@ ZEND_FUNCTION(defined) Z_PARAM_STR(name) ZEND_PARSE_PARAMETERS_END(); - if (zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT)) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + RETURN_BOOL(zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT)); } /* }}} */ @@ -1043,11 +1035,10 @@ static void _property_exists(zval *return_value, const zval *object, zend_string RETURN_TRUE; } - if (Z_TYPE_P(object) == IS_OBJECT && - Z_OBJ_HANDLER_P(object, has_property)(Z_OBJ_P(object), property, ZEND_PROPERTY_EXISTS, NULL)) { - RETURN_TRUE; - } - RETURN_FALSE; + RETURN_BOOL( + Z_TYPE_P(object) == IS_OBJECT && + Z_OBJ_HANDLER_P(object, has_property)(Z_OBJ_P(object), property, ZEND_PROPERTY_EXISTS, NULL) + ); } /* {{{ Checks if the object or class has a property */ @@ -1107,11 +1098,7 @@ static zend_always_inline void _class_exists_impl(zval *return_value, zend_strin ce = zend_lookup_class(name); } - if (ce) { - RETURN_BOOL(((ce->ce_flags & flags) == flags) && !(ce->ce_flags & skip_flags)); - } else { - RETURN_FALSE; - } + RETURN_BOOL(ce && ((ce->ce_flags & flags) == flags) && !(ce->ce_flags & skip_flags)); } /* {{{ */ From deb59973ea84acecc1fcc34e5fd57348f8e903d0 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 24 Mar 2026 14:54:43 +0000 Subject: [PATCH 22/24] zend_objects_API.h: add some const qualifiers --- Zend/zend_objects_API.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Zend/zend_objects_API.h b/Zend/zend_objects_API.h index 86c3a49f8c8c..7fe1b8bbdf1d 100644 --- a/Zend/zend_objects_API.h +++ b/Zend/zend_objects_API.h @@ -80,7 +80,7 @@ static zend_always_inline void zend_object_release(zend_object *obj) } } -static zend_always_inline size_t zend_object_properties_size(zend_class_entry *ce) +static zend_always_inline size_t zend_object_properties_size(const zend_class_entry *ce) { return sizeof(zval) * (ce->default_properties_count - @@ -90,7 +90,7 @@ static zend_always_inline size_t zend_object_properties_size(zend_class_entry *c /* Allocates object type and zeros it, but not the standard zend_object and properties. * Standard object MUST be initialized using zend_object_std_init(). * Properties MUST be initialized using object_properties_init(). */ -static zend_always_inline void *zend_object_alloc(size_t obj_size, zend_class_entry *ce) { +static zend_always_inline void *zend_object_alloc(size_t obj_size, const zend_class_entry *ce) { void *obj = emalloc(obj_size + zend_object_properties_size(ce)); memset(obj, 0, obj_size - sizeof(zend_object)); return obj; From 66e4ba1222120a7fefcce6108e953a273811f6bb Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 24 Mar 2026 16:37:27 +0000 Subject: [PATCH 23/24] zend_objects_API.c: reduce scope of variable --- Zend/zend_objects_API.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index c19873cf3be3..cc1d4fc336f1 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -44,8 +44,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_call_destructors(zend_objects_sto { EG(flags) |= EG_FLAGS_OBJECT_STORE_NO_REUSE; if (objects->top > 1) { - uint32_t i; - for (i = 1; i < objects->top; i++) { + for (uint32_t i = 1; i < objects->top; i++) { zend_object *obj = objects->object_buckets[i]; if (IS_OBJ_VALID(obj)) { if (!(OBJ_FLAGS(obj) & IS_OBJ_DESTRUCTOR_CALLED)) { From e4dcd2e27204836a9a6d4338fea42634acb56be6 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 24 Mar 2026 16:37:52 +0000 Subject: [PATCH 24/24] zend_objects_API.c: use uint32_t type instead of int type --- Zend/zend_objects_API.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index cc1d4fc336f1..2e6ddd2f4d8b 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -127,20 +127,19 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_free_object_storage(zend_objects_ /* Store objects API */ static ZEND_COLD zend_never_inline void ZEND_FASTCALL zend_objects_store_put_cold(zend_object *object) { - int handle; uint32_t new_size = 2 * EG(objects_store).size; EG(objects_store).object_buckets = (zend_object **) erealloc(EG(objects_store).object_buckets, new_size * sizeof(zend_object*)); /* Assign size after realloc, in case it fails */ EG(objects_store).size = new_size; - handle = EG(objects_store).top++; + uint32_t handle = EG(objects_store).top++; object->handle = handle; EG(objects_store).object_buckets[handle] = object; } ZEND_API void ZEND_FASTCALL zend_objects_store_put(zend_object *object) { - int handle; + uint32_t handle; /* When in shutdown sequence - do not reuse previously freed handles, to make sure * the dtors for newly created objects are called in zend_objects_store_call_destructors() loop