From d3a4b4b09c311471c1333dfc049359bc7ca6d2b9 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+ndossche@users.noreply.github.com> Date: Sun, 2 Nov 2025 13:37:13 +0100 Subject: [PATCH 1/7] Fix crashes when trying to instantiate uninstantiable classes via date static constructors Closes GH-20361. --- NEWS | 4 ++ ext/date/php_date.c | 32 ++++++--- .../instantiate_uninstantiable_classes.phpt | 68 +++++++++++++++++++ 3 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 ext/date/tests/instantiate_uninstantiable_classes.phpt diff --git a/NEWS b/NEWS index af4ff2a54435..070de2a09860 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.3.29 +- Date: + . Fix crashes when trying to instantiate uninstantiable classes via date + static constructors. (ndossche) + - Opcache: . Fixed bug GH-20329 (opcache.file_cache broken with full interned string buffer). (Arnaud) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index e54b1945e1e3..84fad72948fd 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -1476,7 +1476,8 @@ static void create_date_period_datetime(timelib_time *datetime, zend_class_entry if (datetime) { php_date_obj *date_obj; - object_init_ex(zv, ce); + zend_result result = object_init_ex(zv, ce); + ZEND_ASSERT(result == SUCCESS && "should succeed as it reuses an existing object's ce"); date_obj = Z_PHPDATE_P(zv); date_obj->time = timelib_time_clone(datetime); } else { @@ -2345,6 +2346,7 @@ static void add_common_properties(HashTable *myht, zend_object *zobj) } /* Advanced Interface */ +/* TODO: remove this API because it is unsafe to use as-is, as it does not propagate the failure/success status. */ PHPAPI zval *php_date_instantiate(zend_class_entry *pce, zval *object) /* {{{ */ { object_init_ex(object, pce); @@ -2564,7 +2566,9 @@ PHP_FUNCTION(date_create_from_format) Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone) ZEND_PARSE_PARAMETERS_END(); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value); + if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date) != SUCCESS) { + RETURN_THROWS(); + } if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, format_str, timezone_object, PHP_DATE_INIT_FORMAT)) { zval_ptr_dtor(return_value); RETURN_FALSE; @@ -2586,7 +2590,9 @@ PHP_FUNCTION(date_create_immutable_from_format) Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone) ZEND_PARSE_PARAMETERS_END(); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value); + if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable) != SUCCESS) { + RETURN_THROWS(); + } if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, format_str, timezone_object, PHP_DATE_INIT_FORMAT)) { zval_ptr_dtor(return_value); RETURN_FALSE; @@ -2642,7 +2648,9 @@ PHP_METHOD(DateTime, createFromImmutable) old_obj = Z_PHPDATE_P(datetimeimmutable_object); DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetimeimmutable_object)); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value); + if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date) != SUCCESS) { + RETURN_THROWS(); + } new_obj = Z_PHPDATE_P(return_value); new_obj->time = timelib_time_clone(old_obj->time); @@ -2663,7 +2671,9 @@ PHP_METHOD(DateTime, createFromInterface) old_obj = Z_PHPDATE_P(datetimeinterface_object); DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetimeinterface_object)); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value); + if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date) != SUCCESS) { + RETURN_THROWS(); + } new_obj = Z_PHPDATE_P(return_value); new_obj->time = timelib_time_clone(old_obj->time); @@ -2684,7 +2694,9 @@ PHP_METHOD(DateTimeImmutable, createFromMutable) old_obj = Z_PHPDATE_P(datetime_object); DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetime_object)); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value); + if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable) != SUCCESS) { + RETURN_THROWS(); + } new_obj = Z_PHPDATE_P(return_value); new_obj->time = timelib_time_clone(old_obj->time); @@ -2705,7 +2717,9 @@ PHP_METHOD(DateTimeImmutable, createFromInterface) old_obj = Z_PHPDATE_P(datetimeinterface_object); DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetimeinterface_object)); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value); + if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable) != SUCCESS) { + RETURN_THROWS(); + } new_obj = Z_PHPDATE_P(return_value); new_obj->time = timelib_time_clone(old_obj->time); @@ -4950,7 +4964,9 @@ PHP_METHOD(DatePeriod, createFromISO8601String) RETURN_THROWS(); } - object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_period); + if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_period) != SUCCESS) { + RETURN_THROWS(); + } dpobj = Z_PHPPERIOD_P(return_value); dpobj->current = NULL; diff --git a/ext/date/tests/instantiate_uninstantiable_classes.phpt b/ext/date/tests/instantiate_uninstantiable_classes.phpt new file mode 100644 index 000000000000..282696b04c9c --- /dev/null +++ b/ext/date/tests/instantiate_uninstantiable_classes.phpt @@ -0,0 +1,68 @@ +--TEST-- +Instantiating uninstantiable classes via static constructors +--FILE-- +getMessage(), "\n"; +} + +try { + MyDateTime::createFromFormat('Y-m-d', '2025-01-01'); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + MyDateTime::createFromImmutable(new DateTimeImmutable()); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + MyDateTime::createFromInterface(new DateTimeImmutable()); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + MyDateTimeImmutable::createFromFormat('Y-m-d', '2025-01-01'); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + MyDateTimeImmutable::createFromMutable(new DateTime()); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + MyDateTimeImmutable::createFromInterface(new DateTime()); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Cannot instantiate abstract class MyDatePeriod +Cannot instantiate abstract class MyDateTime +Cannot instantiate abstract class MyDateTime +Cannot instantiate abstract class MyDateTime +Cannot instantiate abstract class MyDateTimeImmutable +Cannot instantiate abstract class MyDateTimeImmutable +Cannot instantiate abstract class MyDateTimeImmutable From 7c96263ceefb809ac1c9831178825f58f8514910 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+ndossche@users.noreply.github.com> Date: Thu, 6 Nov 2025 22:42:03 +0100 Subject: [PATCH 2/7] dom: Fix compile warning due to misplaced const cast --- ext/dom/document.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/dom/document.c b/ext/dom/document.c index e48cafbabe9c..faf6e210e2d7 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -1234,7 +1234,7 @@ PHP_METHOD(DOMDocument, __construct) } if (encoding_len > 0) { - docp->encoding = (const xmlChar *) xmlStrdup((xmlChar *) encoding); + docp->encoding = xmlStrdup((const xmlChar *) encoding); } intern = Z_DOMOBJ_P(ZEND_THIS); From 3b2f03d16c85cdf25e15ffb179fe2ef04c7e42fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Mon, 3 Nov 2025 15:14:23 +0100 Subject: [PATCH 3/7] Sync all boost.context files with release 1.86.0 Closes GH-20375. --- NEWS | 3 +++ Zend/asm/jump_s390x_sysv_elf_gas.S | 24 ++++++++++++++---------- Zend/asm/make_s390x_sysv_elf_gas.S | 14 +++++++------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/NEWS b/NEWS index 070de2a09860..ad480774cc5a 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.3.29 +- Core: + . Sync all boost.context files with release 1.86.0. (mvorisek) + - Date: . Fix crashes when trying to instantiate uninstantiable classes via date static constructors. (ndossche) diff --git a/Zend/asm/jump_s390x_sysv_elf_gas.S b/Zend/asm/jump_s390x_sysv_elf_gas.S index c2a578b2663e..fa71467756d2 100644 --- a/Zend/asm/jump_s390x_sysv_elf_gas.S +++ b/Zend/asm/jump_s390x_sysv_elf_gas.S @@ -49,11 +49,12 @@ .type jump_fcontext, @function #define ARG_OFFSET 0 -#define GR_OFFSET 16 -#define FP_OFFSET 96 -#define FPC_OFFSET 160 -#define PC_OFFSET 168 -#define CONTEXT_SIZE 176 +#define GR_OFFSET 16 +#define R14_OFFSET 88 +#define FP_OFFSET 96 +#define FPC_OFFSET 160 +#define PC_OFFSET 168 +#define CONTEXT_SIZE 176 #define REG_SAVE_AREA_SIZE 160 @@ -131,11 +132,14 @@ jump_fcontext: ltg %r2,GR_OFFSET(%r15) jnz use_return_slot - /* We restore a make_fcontext context. Use the function - argument slot in the context we just saved and allocate the - register save area for the target function. */ - la %r2,ARG_OFFSET(%r1) - aghi %r15,-REG_SAVE_AREA_SIZE + /* We're restoring a context created by make_fcontext. + This is going to be the argument of the entry point + of the fiber. We're placing it on top of the ABI + defined register save area of the fiber's own stack. */ + la %r2,REG_SAVE_AREA_SIZE(%r15) + + /* REG_SAVE_AREA_SIZE + sizeof(transfer_t) */ + aghi %r15,-(REG_SAVE_AREA_SIZE+16) use_return_slot: /* Save the two fields in transfer_t. When calling a diff --git a/Zend/asm/make_s390x_sysv_elf_gas.S b/Zend/asm/make_s390x_sysv_elf_gas.S index e7e2d5f6e0c9..4dd423e2a44c 100644 --- a/Zend/asm/make_s390x_sysv_elf_gas.S +++ b/Zend/asm/make_s390x_sysv_elf_gas.S @@ -49,12 +49,12 @@ .type make_fcontext, @function #define ARG_OFFSET 0 -#define GR_OFFSET 16 -#define R14_OFFSET 88 -#define FP_OFFSET 96 -#define FPC_OFFSET 160 -#define PC_OFFSET 168 -#define CONTEXT_SIZE 176 +#define GR_OFFSET 16 +#define R14_OFFSET 88 +#define FP_OFFSET 96 +#define FPC_OFFSET 160 +#define PC_OFFSET 168 +#define CONTEXT_SIZE 176 /* @@ -72,7 +72,7 @@ r4 - The address of the context function make_fcontext: .machine "z10" /* Align the stack to an 8 byte boundary. */ - nill %r2,0xfff0 + nill %r2,0xfff8 /* Allocate stack space for the context. */ aghi %r2,-CONTEXT_SIZE From 04bdc4aee07b8dc6ef1ab31d33d7f5642adc3142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Mon, 3 Nov 2025 15:14:23 +0100 Subject: [PATCH 4/7] Sync all boost.context files with release 1.86.0 --- Zend/asm/jump_sparc64_sysv_elf_gas.S | 12 +++++++----- Zend/asm/jump_x86_64_ms_pe_gas.S | 4 ++++ Zend/asm/make_sparc64_sysv_elf_gas.S | 4 ++-- Zend/asm/make_x86_64_ms_pe_gas.S | 4 ++++ 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Zend/asm/jump_sparc64_sysv_elf_gas.S b/Zend/asm/jump_sparc64_sysv_elf_gas.S index 727687aad804..61101fb1f629 100644 --- a/Zend/asm/jump_sparc64_sysv_elf_gas.S +++ b/Zend/asm/jump_sparc64_sysv_elf_gas.S @@ -6,12 +6,14 @@ */ /* - * typedef struct { - * void *handle; - * zend_fiber_transfer *transfer; - * } boost_context_data; + * typedef void* fcontext_t; * - * boost_context_data jump_fcontext(void *to, zend_fiber_transfer *transfer); + * struct transfer_t { + * fcontext_t fctx; + * void * data; + * }; + * + * transfer_t jump_fcontext(fcontext_t const to, void *vp); */ #define CC64FSZ 176 #define BIAS 2047 diff --git a/Zend/asm/jump_x86_64_ms_pe_gas.S b/Zend/asm/jump_x86_64_ms_pe_gas.S index 5ebc46f36403..ec4ecfe946d3 100644 --- a/Zend/asm/jump_x86_64_ms_pe_gas.S +++ b/Zend/asm/jump_x86_64_ms_pe_gas.S @@ -89,6 +89,7 @@ .file "jump_x86_64_ms_pe_gas.asm" .text .p2align 4,,15 +.globl jump_fcontext .def jump_fcontext; .scl 2; .type 32; .endef .seh_proc jump_fcontext jump_fcontext: @@ -203,3 +204,6 @@ jump_fcontext: /* indirect jump to context */ jmp *%r10 .seh_endproc + +.section .drectve +.ascii " -export:\"jump_fcontext\"" diff --git a/Zend/asm/make_sparc64_sysv_elf_gas.S b/Zend/asm/make_sparc64_sysv_elf_gas.S index 52ff70b996b6..3e7ee809c918 100644 --- a/Zend/asm/make_sparc64_sysv_elf_gas.S +++ b/Zend/asm/make_sparc64_sysv_elf_gas.S @@ -6,7 +6,7 @@ */ /* - * void *make_fcontext(void *sp, size_t size, void (*fn)(boost_context_data)); + * fcontext_t *make_fcontext(void *sp, size_t size, void (*fn)(transfer_t)); */ #define CC64FSZ 176 #define BIAS 2047 @@ -56,7 +56,7 @@ make_fcontext: trampoline: ldx [%sp + BIAS + I7], %l0 - # no need to setup boost_context_data, already in %o0 and %o1 + # no need to setup transfer_t, already in %o0 and %o1 jmpl %l0, %o7 nop diff --git a/Zend/asm/make_x86_64_ms_pe_gas.S b/Zend/asm/make_x86_64_ms_pe_gas.S index 66a9bb395356..958a2a7b6d0e 100644 --- a/Zend/asm/make_x86_64_ms_pe_gas.S +++ b/Zend/asm/make_x86_64_ms_pe_gas.S @@ -89,6 +89,7 @@ .file "make_x86_64_ms_pe_gas.asm" .text .p2align 4,,15 +.globl make_fcontext .def make_fcontext; .scl 2; .type 32; .endef .seh_proc make_fcontext make_fcontext: @@ -168,3 +169,6 @@ finish: .seh_endproc .def _exit; .scl 2; .type 32; .endef /* standard C library function */ + +.section .drectve +.ascii " -export:\"make_fcontext\"" From 877e758a3b5b7886e52c40b6f6020ae3591541cd Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+ndossche@users.noreply.github.com> Date: Thu, 6 Nov 2025 23:36:43 +0100 Subject: [PATCH 5/7] array_unshift: Use specialised iteration macro (#20410) Forgot this while working on GH-20353, but this could avoid some checks depending on the compiler optimizations. --- ext/standard/array.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 9f7709092dde..0ef700f14a74 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -3763,7 +3763,7 @@ PHP_FUNCTION(array_unshift) zend_hash_next_index_insert_new(&new_hash, &args[i]); } - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) { if (key) { zend_hash_add_new(&new_hash, key, value); } else { From 0953e898db44403d81f73a38974c4bcd35eb5f88 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 6 Nov 2025 22:47:28 +0000 Subject: [PATCH 6/7] Fix pg_fetch_object() when an error occurs in subroutine (#20407) This is a follow-up of GH-20068 --- ext/pgsql/pgsql.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index cf4285bf2637..77425b25aee1 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -1977,8 +1977,9 @@ PHP_FUNCTION(pg_fetch_result) } /* }}} */ -/* {{{ void php_pgsql_fetch_hash */ -static void php_pgsql_fetch_hash(zval *return_value, const zval *result, zend_long row, bool row_is_null, zend_long result_type) +/* Returns true when the return_value was populated with an array, + * otherwise when an error occurs false is returned, in which case the return_value is NOT initialized */ +static bool php_pgsql_fetch_hash(zval *return_value, const zval *result, zend_long row, bool row_is_null, zend_long result_type) { PGresult *pgsql_result; pgsql_result_handle *pg_result; @@ -1987,23 +1988,26 @@ static void php_pgsql_fetch_hash(zval *return_value, const zval *result, zend_lo if (!row_is_null && row < 0) { zend_argument_value_error(2, "must be greater than or equal to 0"); - RETURN_THROWS(); + return false; } if (!(result_type & PGSQL_BOTH)) { zend_argument_value_error(3, "must be one of PGSQL_ASSOC, PGSQL_NUM, or PGSQL_BOTH"); - RETURN_THROWS(); + return false; } pg_result = Z_PGSQL_RESULT_P(result); - CHECK_PGSQL_RESULT(pg_result); + if (UNEXPECTED(pg_result->result == NULL)) { + zend_throw_error(NULL, "PostgreSQL result has already been closed"); + return false; + } pgsql_result = pg_result->result; if (!row_is_null) { if (row >= PQntuples(pgsql_result)) { php_error_docref(NULL, E_WARNING, "Unable to jump to row " ZEND_LONG_FMT " on PostgreSQL result index " ZEND_LONG_FMT, row, Z_LVAL_P(result)); - RETURN_FALSE; + return false; } pgsql_row = (int)row; pg_result->row = pgsql_row; @@ -2011,7 +2015,7 @@ static void php_pgsql_fetch_hash(zval *return_value, const zval *result, zend_lo /* If 2nd param is NULL, use internal row counter to access next row */ pgsql_row = pg_result->row; if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) { - RETURN_FALSE; + return false; } pg_result->row++; } @@ -2042,8 +2046,8 @@ static void php_pgsql_fetch_hash(zval *return_value, const zval *result, zend_lo } } } + return true; } -/* }}} */ /* {{{ Get a row as an enumerated array */ PHP_FUNCTION(pg_fetch_row) @@ -2060,7 +2064,10 @@ PHP_FUNCTION(pg_fetch_row) Z_PARAM_LONG(result_type) ZEND_PARSE_PARAMETERS_END(); - php_pgsql_fetch_hash(return_value, result, row, row_is_null, result_type); + if (UNEXPECTED(!php_pgsql_fetch_hash(return_value, result, row, row_is_null, result_type))) { + /* Either an exception is thrown, or we return false */ + RETURN_FALSE; + } } /* }}} */ @@ -2077,7 +2084,10 @@ PHP_FUNCTION(pg_fetch_assoc) Z_PARAM_LONG_OR_NULL(row, row_is_null) ZEND_PARSE_PARAMETERS_END(); - php_pgsql_fetch_hash(return_value, result, row, row_is_null, PGSQL_ASSOC); + if (UNEXPECTED(!php_pgsql_fetch_hash(return_value, result, row, row_is_null, PGSQL_ASSOC))) { + /* Either an exception is thrown, or we return false */ + RETURN_FALSE; + } } /* }}} */ @@ -2096,7 +2106,10 @@ PHP_FUNCTION(pg_fetch_array) Z_PARAM_LONG(result_type) ZEND_PARSE_PARAMETERS_END(); - php_pgsql_fetch_hash(return_value, result, row, row_is_null, result_type); + if (UNEXPECTED(!php_pgsql_fetch_hash(return_value, result, row, row_is_null, result_type))) { + /* Either an exception is thrown, or we return false */ + RETURN_FALSE; + } } /* }}} */ @@ -2129,10 +2142,11 @@ PHP_FUNCTION(pg_fetch_object) RETURN_THROWS(); } - /* pg_fetch_object() allowed result_type used to be. 3rd parameter - must be allowed for compatibility */ zval dataset; - php_pgsql_fetch_hash(&dataset, result, row, row_is_null, PGSQL_ASSOC); + if (UNEXPECTED(!php_pgsql_fetch_hash(&dataset, result, row, row_is_null, PGSQL_ASSOC))) { + /* Either an exception is thrown, or we return false */ + RETURN_FALSE; + } // TODO: Check CE is an instantiable class earlier? zend_result obj_initialized = object_init_ex(return_value, ce); From 297179dbcc643dd7c0e7f2eee5099ffbd1be8b05 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 6 Nov 2025 22:47:39 +0000 Subject: [PATCH 7/7] zend_object_handlers: add some const qualifiers (#20402) --- Zend/zend_API.c | 5 ++--- Zend/zend_object_handlers.c | 44 ++++++++++++++++++------------------- Zend/zend_object_handlers.h | 2 +- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 147e8b239961..89ffe419cd6e 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1687,10 +1687,9 @@ ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properti if (object->ce->default_properties_count) { zval *prop; zend_string *key; - zend_property_info *property_info; ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(properties, key, prop) { - property_info = zend_get_property_info(object->ce, key, 1); + const zend_property_info *property_info = zend_get_property_info(object->ce, key, 1); if (property_info != ZEND_WRONG_PROPERTY_INFO && property_info && (property_info->flags & ZEND_ACC_STATIC) == 0) { @@ -1719,7 +1718,7 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties) zval *prop, tmp; zend_string *key; zend_long h; - zend_property_info *property_info; + const zend_property_info *property_info; ZEND_HASH_FOREACH_KEY_VAL(properties, h, key, prop) { if (key) { diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index ec628dbfc9fe..470fb76ec14e 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -106,8 +106,7 @@ ZEND_API HashTable *rebuild_object_properties_internal(zend_object *zobj) /* {{{ /* Implements the fast path for array cast */ ZEND_API HashTable *zend_std_build_object_properties_array(zend_object *zobj) /* {{{ */ { - zend_property_info *prop_info; - zend_class_entry *ce = zobj->ce; + const zend_class_entry *ce = zobj->ce; HashTable *ht; zval* prop; int i; @@ -118,7 +117,7 @@ ZEND_API HashTable *zend_std_build_object_properties_array(zend_object *zobj) /* if (ce->default_properties_count) { zend_hash_real_init_mixed(ht); for (i = 0; i < ce->default_properties_count; i++) { - prop_info = ce->properties_info_table[i]; + const zend_property_info *prop_info = ce->properties_info_table[i]; if (!prop_info) { continue; @@ -192,7 +191,7 @@ ZEND_API HashTable *zend_std_get_gc(zend_object *zobj, zval **table, int *n) /* ZEND_API HashTable *zend_std_get_debug_info(zend_object *object, int *is_temp) /* {{{ */ { - zend_class_entry *ce = object->ce; + const zend_class_entry *ce = object->ce; zval retval; HashTable *ht; @@ -334,7 +333,7 @@ static ZEND_COLD zend_never_inline bool zend_deprecated_dynamic_property( zend_error(E_DEPRECATED, "Creation of dynamic property %s::$%s is deprecated", ZSTR_VAL(obj->ce->name), ZSTR_VAL(member)); if (UNEXPECTED(GC_DELREF(obj) == 0)) { - zend_class_entry *ce = obj->ce; + const zend_class_entry *ce = obj->ce; zend_objects_store_del(obj); if (!EG(exception)) { /* We cannot continue execution and have to throw an exception */ @@ -347,7 +346,7 @@ static ZEND_COLD zend_never_inline bool zend_deprecated_dynamic_property( } static ZEND_COLD zend_never_inline void zend_readonly_property_unset_error( - zend_class_entry *ce, zend_string *member) { + const zend_class_entry *ce, const zend_string *member) { zend_throw_error(NULL, "Cannot unset readonly property %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(member)); } @@ -711,7 +710,7 @@ static bool zend_should_call_hook(const zend_property_info *prop_info, const zen return true; } -static ZEND_COLD void zend_throw_no_prop_backing_value_access(zend_string *class_name, zend_string *prop_name, bool is_read) +static ZEND_COLD void zend_throw_no_prop_backing_value_access(const zend_string *class_name, const zend_string *prop_name, bool is_read) { zend_throw_error(NULL, "Must not %s virtual property %s::$%s", is_read ? "read from" : "write to", @@ -719,7 +718,7 @@ static ZEND_COLD void zend_throw_no_prop_backing_value_access(zend_string *class } static bool zend_call_get_hook( - const zend_property_info *prop_info, zend_string *prop_name, + const zend_property_info *prop_info, const zend_string *prop_name, zend_function *get, zend_object *zobj, zval *rv) { if (!zend_should_call_hook(prop_info, zobj)) { @@ -842,7 +841,7 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int goto exit; } - zend_class_entry *ce = zobj->ce; + const zend_class_entry *ce = zobj->ce; if (!zend_call_get_hook(prop_info, name, get, zobj, rv)) { if (EG(exception)) { @@ -850,7 +849,7 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int } /* Reads from backing store can only occur in hooks, and hence will always remain simple. */ - zend_execute_data *execute_data = EG(current_execute_data); + const zend_execute_data *execute_data = EG(current_execute_data); if (cache_slot && EX(opline) && EX(opline)->opcode == ZEND_FETCH_OBJ_R && EX(opline)->op1_type == IS_UNUSED) { ZEND_SET_PROPERTY_HOOK_SIMPLE_READ(cache_slot); } @@ -1274,7 +1273,7 @@ found:; } /* }}} */ -static ZEND_COLD zend_never_inline void zend_bad_array_access(zend_class_entry *ce) /* {{{ */ +static ZEND_COLD zend_never_inline void zend_bad_array_access(const zend_class_entry *ce) /* {{{ */ { zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(ce->name)); } @@ -1282,7 +1281,7 @@ static ZEND_COLD zend_never_inline void zend_bad_array_access(zend_class_entry * ZEND_API zval *zend_std_read_dimension(zend_object *object, zval *offset, int type, zval *rv) /* {{{ */ { - zend_class_entry *ce = object->ce; + const zend_class_entry *ce = object->ce; zval tmp_offset; /* arrayaccess_funcs_ptr is set if (and only if) the class implements zend_ce_arrayaccess */ @@ -1333,7 +1332,7 @@ ZEND_API zval *zend_std_read_dimension(zend_object *object, zval *offset, int ty ZEND_API void zend_std_write_dimension(zend_object *object, zval *offset, zval *value) /* {{{ */ { - zend_class_entry *ce = object->ce; + const zend_class_entry *ce = object->ce; zval tmp_offset; zend_class_arrayaccess_funcs *funcs = ce->arrayaccess_funcs_ptr; @@ -1356,7 +1355,7 @@ ZEND_API void zend_std_write_dimension(zend_object *object, zval *offset, zval * // todo: make zend_std_has_dimension return bool as well ZEND_API int zend_std_has_dimension(zend_object *object, zval *offset, int check_empty) /* {{{ */ { - zend_class_entry *ce = object->ce; + const zend_class_entry *ce = object->ce; zval retval, tmp_offset; bool result; @@ -1610,7 +1609,7 @@ ZEND_API void zend_std_unset_property(zend_object *zobj, zend_string *name, void ZEND_API void zend_std_unset_dimension(zend_object *object, zval *offset) /* {{{ */ { - zend_class_entry *ce = object->ce; + const zend_class_entry *ce = object->ce; zval tmp_offset; zend_class_arrayaccess_funcs *funcs = ce->arrayaccess_funcs_ptr; @@ -1626,7 +1625,7 @@ ZEND_API void zend_std_unset_dimension(zend_object *object, zval *offset) /* {{{ } /* }}} */ -static zend_never_inline zend_function *zend_get_parent_private_method(zend_class_entry *scope, zend_class_entry *ce, zend_string *function_name) /* {{{ */ +static zend_never_inline zend_function *zend_get_parent_private_method(const zend_class_entry *scope, const zend_class_entry *ce, zend_string *function_name) /* {{{ */ { zval *func; zend_function *fbc; @@ -1747,7 +1746,7 @@ static ZEND_FUNCTION(zend_parent_hook_get_trampoline) } zval rv; - zval *retval = obj->handlers->read_property(obj, prop_name, BP_VAR_R, NULL, &rv); + const zval *retval = obj->handlers->read_property(obj, prop_name, BP_VAR_R, NULL, &rv); if (retval == &rv) { RETVAL_COPY_VALUE(retval); } else { @@ -1846,7 +1845,6 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string * zval *func; zend_function *fbc; zend_string *lc_method_name; - zend_class_entry *scope; ALLOCA_FLAG(use_heap); if (EXPECTED(key != NULL)) { @@ -1874,7 +1872,7 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string * /* Check access level */ if (fbc->op_array.fn_flags & (ZEND_ACC_CHANGED|ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) { - scope = zend_get_executed_scope(); + const zend_class_entry *scope = zend_get_executed_scope(); if (fbc->common.scope != scope) { if (fbc->op_array.fn_flags & ZEND_ACC_CHANGED) { @@ -1930,7 +1928,7 @@ static zend_always_inline zend_function *get_static_method_fallback( } } -ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name, const zval *key) /* {{{ */ +ZEND_API zend_function *zend_std_get_static_method(const zend_class_entry *ce, zend_string *function_name, const zval *key) /* {{{ */ { zend_string *lc_function_name; if (EXPECTED(key != NULL)) { @@ -1944,7 +1942,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st if (EXPECTED(func)) { fbc = Z_FUNC_P(func); if (!(fbc->common.fn_flags & ZEND_ACC_PUBLIC)) { - zend_class_entry *scope = zend_get_executed_scope(); + const zend_class_entry *scope = zend_get_executed_scope(); ZEND_ASSERT(!(fbc->common.fn_flags & ZEND_ACC_PUBLIC)); if (!zend_check_method_accessible(fbc, scope)) { zend_function *fallback_fbc = get_static_method_fallback(ce, function_name); @@ -2442,7 +2440,7 @@ ZEND_API zend_result zend_std_cast_object_tostring(zend_object *readobj, zval *w { switch (type) { case IS_STRING: { - zend_class_entry *ce = readobj->ce; + const zend_class_entry *ce = readobj->ce; if (ce->__tostring) { zval retval; GC_ADDREF(readobj); @@ -2475,7 +2473,7 @@ ZEND_API zend_result zend_std_cast_object_tostring(zend_object *readobj, zval *w ZEND_API zend_result zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only) /* {{{ */ { zend_class_entry *ce = obj->ce; - zval *func = zend_hash_find_known_hash(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE)); + const zval *func = zend_hash_find_known_hash(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE)); if (func == NULL) { return FAILURE; diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 238d9539a7d5..59277c09d802 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -248,7 +248,7 @@ extern const ZEND_API zend_object_handlers std_object_handlers; #define ZEND_PROPERTY_EXISTS 0x2 /* Property exists */ ZEND_API void zend_class_init_statics(zend_class_entry *ce); -ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name_strval, const zval *key); +ZEND_API zend_function *zend_std_get_static_method(const zend_class_entry *ce, zend_string *function_name_strval, const zval *key); ZEND_API zval *zend_std_get_static_property_with_info(zend_class_entry *ce, zend_string *property_name, int type, struct _zend_property_info **prop_info); ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *property_name, int type); ZEND_API ZEND_COLD bool zend_std_unset_static_property(const zend_class_entry *ce, const zend_string *property_name);