From abc1910b4f3e7b6c1f1fb15a6af52aec4c13d311 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 14 Nov 2025 08:12:32 +0000 Subject: [PATCH 1/6] ext/standard/array.c: refactor php_valid_var_name() --- ext/standard/array.c | 85 +++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 53 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 54b26a3dadfd5..d8be2fc1f3024 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1675,9 +1675,8 @@ PHP_FUNCTION(array_search) } /* }}} */ -static zend_always_inline int php_valid_var_name(const char *var_name, size_t var_name_len) /* {{{ */ +static zend_always_inline bool php_valid_var_name(const zend_string *var_name) /* {{{ */ { -#if 1 /* first 256 bits for first character, and second 256 bits for the next */ static const uint32_t charset[8] = { /* 31 0 63 32 95 64 127 96 */ @@ -1687,48 +1686,28 @@ static zend_always_inline int php_valid_var_name(const char *var_name, size_t va /* 31 0 63 32 95 64 127 96 */ 0x00000000, 0x03ff0000, 0x87fffffe, 0x07fffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}; -#endif - size_t i; - uint32_t ch; - if (UNEXPECTED(!var_name_len)) { - return 0; + if (UNEXPECTED(!ZSTR_LEN(var_name))) { + return false; } /* These are allowed as first char: [a-zA-Z_\x7f-\xff] */ - ch = (uint32_t)((unsigned char *)var_name)[0]; -#if 1 + uint32_t ch = (uint32_t)((unsigned char *)ZSTR_VAL(var_name))[0]; if (UNEXPECTED(!ZEND_BIT_TEST(charset, ch))) { -#else - if (var_name[0] != '_' && - (ch < 65 /* A */ || /* Z */ ch > 90) && - (ch < 97 /* a */ || /* z */ ch > 122) && - (ch < 127 /* 0x7f */ || /* 0xff */ ch > 255) - ) { -#endif - return 0; + return false; } /* And these as the rest: [a-zA-Z0-9_\x7f-\xff] */ - if (var_name_len > 1) { - i = 1; + if (ZSTR_LEN(var_name) > 1) { + size_t i = 1; do { - ch = (uint32_t)((unsigned char *)var_name)[i]; -#if 1 + ch = (uint32_t)((unsigned char *)ZSTR_VAL(var_name))[i]; if (UNEXPECTED(!ZEND_BIT_TEST(charset2, ch))) { -#else - if (var_name[i] != '_' && - (ch < 48 /* 0 */ || /* 9 */ ch > 57) && - (ch < 65 /* A */ || /* Z */ ch > 90) && - (ch < 97 /* a */ || /* z */ ch > 122) && - (ch < 127 /* 0x7f */ || /* 0xff */ ch > 255) - ) { -#endif - return 0; + return false; } - } while (++i < var_name_len); + } while (++i < ZSTR_LEN(var_name)); } - return 1; + return true; } /* }}} */ @@ -1768,7 +1747,7 @@ static zend_long php_extract_ref_if_exists(zend_array *arr, zend_array *symbol_t continue; } } - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals_literal(var_name, "GLOBALS")) { @@ -1814,7 +1793,7 @@ static zend_long php_extract_if_exists(zend_array *arr, zend_array *symbol_table continue; } } - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals_literal(var_name, "GLOBALS")) { @@ -1850,7 +1829,7 @@ static zend_long php_extract_ref_overwrite(zend_array *arr, zend_array *symbol_t if (!var_name) { continue; } - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { @@ -1902,7 +1881,7 @@ static zend_long php_extract_overwrite(zend_array *arr, zend_array *symbol_table if (!var_name) { continue; } - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { @@ -1963,7 +1942,7 @@ static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *s } } php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); - if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { + if (php_valid_var_name(Z_STR(final_name))) { if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { zend_throw_error(NULL, "Cannot re-assign $this"); return -1; @@ -2017,7 +1996,7 @@ static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbo } } php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); - if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { + if (php_valid_var_name(Z_STR(final_name))) { if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { zend_throw_error(NULL, "Cannot re-assign $this"); return -1; @@ -2080,7 +2059,7 @@ static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol } prefix: php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); - if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { + if (php_valid_var_name(Z_STR(final_name))) { if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { zend_throw_error(NULL, "Cannot re-assign $this"); return -1; @@ -2104,7 +2083,7 @@ static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol } zval_ptr_dtor_str(&final_name); } else { - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { @@ -2152,7 +2131,7 @@ static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_tab } prefix: php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); - if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { + if (php_valid_var_name(Z_STR(final_name))) { if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { zend_throw_error(NULL, "Cannot re-assign $this"); return -1; @@ -2176,7 +2155,7 @@ static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_tab } zval_ptr_dtor_str(&final_name); } else { - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { @@ -2211,7 +2190,7 @@ static zend_long php_extract_ref_prefix_all(zend_array *arr, zend_array *symbol_ php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), true); zend_string_release_ex(str, 0); } - if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { + if (php_valid_var_name(Z_STR(final_name))) { if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { zend_throw_error(NULL, "Cannot re-assign $this"); return -1; @@ -2258,7 +2237,7 @@ static zend_long php_extract_prefix_all(zend_array *arr, zend_array *symbol_tabl php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), true); zend_string_release_ex(str, 0); } - if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { + if (php_valid_var_name(Z_STR(final_name))) { if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { zend_throw_error(NULL, "Cannot re-assign $this"); return -1; @@ -2296,10 +2275,10 @@ static zend_long php_extract_ref_prefix_invalid(zend_array *arr, zend_array *sym ZEND_HASH_FOREACH_KEY_VAL(arr, num_key, var_name, entry) { if (var_name) { - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name)) + if (!php_valid_var_name(var_name) || zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); - if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { + if (!php_valid_var_name(Z_STR(final_name))) { zval_ptr_dtor_str(&final_name); continue; } @@ -2310,7 +2289,7 @@ static zend_long php_extract_ref_prefix_invalid(zend_array *arr, zend_array *sym zend_string *str = zend_long_to_str(num_key); php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), true); zend_string_release_ex(str, 0); - if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { + if (!php_valid_var_name(Z_STR(final_name))) { zval_ptr_dtor_str(&final_name); continue; } @@ -2351,10 +2330,10 @@ static zend_long php_extract_prefix_invalid(zend_array *arr, zend_array *symbol_ ZEND_HASH_FOREACH_KEY_VAL(arr, num_key, var_name, entry) { if (var_name) { - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name)) + if (!php_valid_var_name(var_name) || zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); - if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { + if (!php_valid_var_name(Z_STR(final_name))) { zval_ptr_dtor_str(&final_name); continue; } @@ -2365,7 +2344,7 @@ static zend_long php_extract_prefix_invalid(zend_array *arr, zend_array *symbol_ zend_string *str = zend_long_to_str(num_key); php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), true); zend_string_release_ex(str, 0); - if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { + if (!php_valid_var_name(Z_STR(final_name))) { zval_ptr_dtor_str(&final_name); continue; } @@ -2410,7 +2389,7 @@ static zend_long php_extract_ref_skip(zend_array *arr, zend_array *symbol_table) if (!var_name) { continue; } - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { @@ -2458,7 +2437,7 @@ static zend_long php_extract_skip(zend_array *arr, zend_array *symbol_table) /* if (!var_name) { continue; } - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { @@ -2519,7 +2498,7 @@ PHP_FUNCTION(extract) } if (prefix) { - if (ZSTR_LEN(prefix) && !php_valid_var_name(ZSTR_VAL(prefix), ZSTR_LEN(prefix))) { + if (ZSTR_LEN(prefix) && !php_valid_var_name(prefix)) { zend_argument_value_error(3, "must be a valid identifier"); RETURN_THROWS(); } From 6cd80f715f30ee1131eb1660faf45ea0f8e23501 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 14 Nov 2025 08:26:44 +0000 Subject: [PATCH 2/6] ext/standard/array.c: assert on conditions which are always false --- ext/standard/array.c | 267 ++++++++++++++++++++----------------------- 1 file changed, 127 insertions(+), 140 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index d8be2fc1f3024..321a688d1d13e 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1943,26 +1943,24 @@ static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *s } php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); if (php_valid_var_name(Z_STR(final_name))) { - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; + /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ + ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); } else { - if (Z_ISREF_P(entry)) { - Z_ADDREF_P(entry); - } else { - ZVAL_MAKE_REF_EX(entry, 2); - } - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - zval_ptr_dtor(orig_var); - ZVAL_REF(orig_var, Z_REF_P(entry)); - } else { - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + ZVAL_MAKE_REF_EX(entry, 2); + } + if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + zval_ptr_dtor(orig_var); + ZVAL_REF(orig_var, Z_REF_P(entry)); + } else { + zend_hash_add_new(symbol_table, Z_STR(final_name), entry); } + count++; } zval_ptr_dtor_str(&final_name); } @@ -1997,26 +1995,24 @@ static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbo } php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); if (php_valid_var_name(Z_STR(final_name))) { - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; - } else { - ZVAL_DEREF(entry); - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); - if (UNEXPECTED(EG(exception))) { - zend_string_release_ex(Z_STR(final_name), 0); - return -1; - } - } else { - Z_TRY_ADDREF_P(entry); - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ + ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + + ZVAL_DEREF(entry); + if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); + if (UNEXPECTED(EG(exception))) { + zend_string_release_ex(Z_STR(final_name), 0); + return -1; + } + } else { + Z_TRY_ADDREF_P(entry); + zend_hash_add_new(symbol_table, Z_STR(final_name), entry); } + count++; } zval_ptr_dtor_str(&final_name); } @@ -2060,26 +2056,24 @@ static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol prefix: php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); if (php_valid_var_name(Z_STR(final_name))) { - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; + /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ + ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); } else { - if (Z_ISREF_P(entry)) { - Z_ADDREF_P(entry); - } else { - ZVAL_MAKE_REF_EX(entry, 2); - } - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - zval_ptr_dtor(orig_var); - ZVAL_REF(orig_var, Z_REF_P(entry)); - } else { - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + ZVAL_MAKE_REF_EX(entry, 2); + } + if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + zval_ptr_dtor(orig_var); + ZVAL_REF(orig_var, Z_REF_P(entry)); + } else { + zend_hash_add_new(symbol_table, Z_STR(final_name), entry); } + count++; } zval_ptr_dtor_str(&final_name); } else { @@ -2132,26 +2126,24 @@ static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_tab prefix: php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); if (php_valid_var_name(Z_STR(final_name))) { - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; - } else { - ZVAL_DEREF(entry); - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); - if (UNEXPECTED(EG(exception))) { - zend_string_release_ex(Z_STR(final_name), 0); - return -1; - } - } else { - Z_TRY_ADDREF_P(entry); - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ + ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + + ZVAL_DEREF(entry); + if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); + if (UNEXPECTED(EG(exception))) { + zend_string_release_ex(Z_STR(final_name), 0); + return -1; + } + } else { + Z_TRY_ADDREF_P(entry); + zend_hash_add_new(symbol_table, Z_STR(final_name), entry); } + count++; } zval_ptr_dtor_str(&final_name); } else { @@ -2191,26 +2183,24 @@ static zend_long php_extract_ref_prefix_all(zend_array *arr, zend_array *symbol_ zend_string_release_ex(str, 0); } if (php_valid_var_name(Z_STR(final_name))) { - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; + /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ + ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); } else { - if (Z_ISREF_P(entry)) { - Z_ADDREF_P(entry); - } else { - ZVAL_MAKE_REF_EX(entry, 2); - } - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - zval_ptr_dtor(orig_var); - ZVAL_REF(orig_var, Z_REF_P(entry)); - } else { - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + ZVAL_MAKE_REF_EX(entry, 2); + } + if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + zval_ptr_dtor(orig_var); + ZVAL_REF(orig_var, Z_REF_P(entry)); + } else { + zend_hash_add_new(symbol_table, Z_STR(final_name), entry); } + count++; } zval_ptr_dtor_str(&final_name); } ZEND_HASH_FOREACH_END(); @@ -2238,26 +2228,24 @@ static zend_long php_extract_prefix_all(zend_array *arr, zend_array *symbol_tabl zend_string_release_ex(str, 0); } if (php_valid_var_name(Z_STR(final_name))) { - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; - } else { - ZVAL_DEREF(entry); - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); - if (UNEXPECTED(EG(exception))) { - zend_string_release_ex(Z_STR(final_name), 0); - return -1; - } - } else { - Z_TRY_ADDREF_P(entry); - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ + ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + + ZVAL_DEREF(entry); + if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); + if (UNEXPECTED(EG(exception))) { + zend_string_release_ex(Z_STR(final_name), 0); + return -1; + } + } else { + Z_TRY_ADDREF_P(entry); + zend_hash_add_new(symbol_table, Z_STR(final_name), entry); } + count++; } zval_ptr_dtor_str(&final_name); } ZEND_HASH_FOREACH_END(); @@ -2294,26 +2282,25 @@ static zend_long php_extract_ref_prefix_invalid(zend_array *arr, zend_array *sym continue; } } - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; + + /* We previously checked if the var name is "this" to prefix it */ + ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); } else { - if (Z_ISREF_P(entry)) { - Z_ADDREF_P(entry); - } else { - ZVAL_MAKE_REF_EX(entry, 2); - } - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - zval_ptr_dtor(orig_var); - ZVAL_REF(orig_var, Z_REF_P(entry)); - } else { - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + ZVAL_MAKE_REF_EX(entry, 2); + } + if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + zval_ptr_dtor(orig_var); + ZVAL_REF(orig_var, Z_REF_P(entry)); + } else { + zend_hash_add_new(symbol_table, Z_STR(final_name), entry); } + count++; + zval_ptr_dtor_str(&final_name); } ZEND_HASH_FOREACH_END(); @@ -2349,26 +2336,26 @@ static zend_long php_extract_prefix_invalid(zend_array *arr, zend_array *symbol_ continue; } } - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; - } else { - ZVAL_DEREF(entry); - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); - if (UNEXPECTED(EG(exception))) { - zend_string_release_ex(Z_STR(final_name), 0); - return -1; - } - } else { - Z_TRY_ADDREF_P(entry); - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + + /* We previously checked if the var name is "this" to prefix it */ + ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + + ZVAL_DEREF(entry); + if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); + if (UNEXPECTED(EG(exception))) { + zend_string_release_ex(Z_STR(final_name), 0); + return -1; + } + } else { + Z_TRY_ADDREF_P(entry); + zend_hash_add_new(symbol_table, Z_STR(final_name), entry); } + count++; + zval_ptr_dtor_str(&final_name); } ZEND_HASH_FOREACH_END(); From 8587bb2f93bf5378854542969a78cacf31610f66 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 14 Nov 2025 08:21:02 +0000 Subject: [PATCH 3/6] ext/standard/array.c: refactor php_prefix_varname() --- ext/standard/array.c | 180 ++++++++++++++++----------------- ext/standard/basic_functions.h | 1 - 2 files changed, 87 insertions(+), 94 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 321a688d1d13e..3ccb5d25a9db6 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1711,20 +1711,10 @@ static zend_always_inline bool php_valid_var_name(const zend_string *var_name) / } /* }}} */ -PHPAPI int php_prefix_varname(zval *result, zend_string *prefix, const char *var_name, size_t var_name_len, bool add_underscore) /* {{{ */ +static zend_string* php_prefix_varname(const zend_string *prefix, const zend_string *var_name) { - ZVAL_NEW_STR(result, zend_string_alloc(ZSTR_LEN(prefix) + (add_underscore ? 1 : 0) + var_name_len, 0)); - memcpy(Z_STRVAL_P(result), ZSTR_VAL(prefix), ZSTR_LEN(prefix)); - - if (add_underscore) { - Z_STRVAL_P(result)[ZSTR_LEN(prefix)] = '_'; - } - - memcpy(Z_STRVAL_P(result) + ZSTR_LEN(prefix) + (add_underscore ? 1 : 0), var_name, var_name_len + 1); - - return SUCCESS; + return zend_string_concat3(ZSTR_VAL(prefix), ZSTR_LEN(prefix), ZEND_STRL("_"), ZSTR_VAL(var_name), ZSTR_LEN(var_name)); } -/* }}} */ static zend_long php_extract_ref_if_exists(zend_array *arr, zend_array *symbol_table) /* {{{ */ { @@ -1917,7 +1907,7 @@ static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *s { zend_long count = 0; zend_string *var_name; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; if (HT_IS_PACKED(arr)) { return 0; @@ -1941,28 +1931,28 @@ static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *s continue; } } - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); - if (php_valid_var_name(Z_STR(final_name))) { + zend_string *final_name = php_prefix_varname(prefix, var_name); + if (php_valid_var_name(final_name)) { /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ - ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); if (Z_ISREF_P(entry)) { Z_ADDREF_P(entry); } else { ZVAL_MAKE_REF_EX(entry, 2); } - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); } zval_ptr_dtor(orig_var); ZVAL_REF(orig_var, Z_REF_P(entry)); } else { - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + zend_hash_add_new(symbol_table, final_name, entry); } count++; } - zval_ptr_dtor_str(&final_name); + zend_string_release_ex(final_name, false); } } ZEND_HASH_FOREACH_END(); @@ -1974,7 +1964,7 @@ static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbo { zend_long count = 0; zend_string *var_name; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; if (HT_IS_PACKED(arr)) { return 0; @@ -1993,28 +1983,28 @@ static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbo continue; } } - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); - if (php_valid_var_name(Z_STR(final_name))) { + zend_string *final_name = php_prefix_varname(prefix, var_name); + if (php_valid_var_name(final_name)) { /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ - ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); ZVAL_DEREF(entry); - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); } ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); if (UNEXPECTED(EG(exception))) { - zend_string_release_ex(Z_STR(final_name), 0); + zend_string_release_ex(final_name, 0); return -1; } } else { Z_TRY_ADDREF_P(entry); - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + zend_hash_add_new(symbol_table, final_name, entry); } count++; } - zval_ptr_dtor_str(&final_name); + zend_string_release_ex(final_name, false); } } ZEND_HASH_FOREACH_END(); @@ -2026,7 +2016,7 @@ static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol { zend_long count = 0; zend_string *var_name; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; if (HT_IS_PACKED(arr)) { return 0; @@ -2053,29 +2043,29 @@ static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol continue; } } -prefix: - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); - if (php_valid_var_name(Z_STR(final_name))) { +prefix:; + zend_string *final_name = php_prefix_varname(prefix, var_name); + if (php_valid_var_name(final_name)) { /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ - ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); if (Z_ISREF_P(entry)) { Z_ADDREF_P(entry); } else { ZVAL_MAKE_REF_EX(entry, 2); } - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); } zval_ptr_dtor(orig_var); ZVAL_REF(orig_var, Z_REF_P(entry)); } else { - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + zend_hash_add_new(symbol_table, final_name, entry); } count++; } - zval_ptr_dtor_str(&final_name); + zend_string_release_ex(final_name, false); } else { if (!php_valid_var_name(var_name)) { continue; @@ -2101,7 +2091,7 @@ static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_tab { zend_long count = 0; zend_string *var_name; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; if (HT_IS_PACKED(arr)) { return 0; @@ -2123,29 +2113,29 @@ static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_tab continue; } } -prefix: - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); - if (php_valid_var_name(Z_STR(final_name))) { +prefix:; + zend_string *final_name = php_prefix_varname(prefix, var_name); + if (php_valid_var_name(final_name)) { /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ - ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); ZVAL_DEREF(entry); - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); } ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); if (UNEXPECTED(EG(exception))) { - zend_string_release_ex(Z_STR(final_name), 0); + zend_string_release_ex(final_name, false); return -1; } } else { Z_TRY_ADDREF_P(entry); - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + zend_hash_add_new(symbol_table, final_name, entry); } count++; } - zval_ptr_dtor_str(&final_name); + zend_string_release_ex(final_name, false); } else { if (!php_valid_var_name(var_name)) { continue; @@ -2169,40 +2159,41 @@ static zend_long php_extract_ref_prefix_all(zend_array *arr, zend_array *symbol_ zend_long count = 0; zend_string *var_name; zend_ulong num_key; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; ZEND_HASH_FOREACH_KEY_VAL(arr, num_key, var_name, entry) { + zend_string *final_name; if (var_name) { if (ZSTR_LEN(var_name) == 0) { continue; } - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); + final_name = php_prefix_varname(prefix, var_name); } else { zend_string *str = zend_long_to_str(num_key); - php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), true); - zend_string_release_ex(str, 0); + final_name = php_prefix_varname(prefix, str); + zend_string_release_ex(str, false); } - if (php_valid_var_name(Z_STR(final_name))) { + if (php_valid_var_name(final_name)) { /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ - ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); if (Z_ISREF_P(entry)) { Z_ADDREF_P(entry); } else { ZVAL_MAKE_REF_EX(entry, 2); } - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); } zval_ptr_dtor(orig_var); ZVAL_REF(orig_var, Z_REF_P(entry)); } else { - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + zend_hash_add_new(symbol_table, final_name, entry); } count++; } - zval_ptr_dtor_str(&final_name); + zend_string_release_ex(final_name, false); } ZEND_HASH_FOREACH_END(); return count; @@ -2214,40 +2205,41 @@ static zend_long php_extract_prefix_all(zend_array *arr, zend_array *symbol_tabl zend_long count = 0; zend_string *var_name; zend_ulong num_key; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; ZEND_HASH_FOREACH_KEY_VAL(arr, num_key, var_name, entry) { + zend_string *final_name; if (var_name) { if (ZSTR_LEN(var_name) == 0) { continue; } - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); + final_name = php_prefix_varname(prefix, var_name); } else { zend_string *str = zend_long_to_str(num_key); - php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), true); - zend_string_release_ex(str, 0); + final_name = php_prefix_varname(prefix, str); + zend_string_release_ex(str, false); } - if (php_valid_var_name(Z_STR(final_name))) { + if (php_valid_var_name(final_name)) { /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ - ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); ZVAL_DEREF(entry); - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); } ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); if (UNEXPECTED(EG(exception))) { - zend_string_release_ex(Z_STR(final_name), 0); + zend_string_release_ex(final_name, false); return -1; } } else { Z_TRY_ADDREF_P(entry); - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + zend_hash_add_new(symbol_table, final_name, entry); } count++; } - zval_ptr_dtor_str(&final_name); + zend_string_release_ex(final_name, false); } ZEND_HASH_FOREACH_END(); return count; @@ -2259,49 +2251,51 @@ static zend_long php_extract_ref_prefix_invalid(zend_array *arr, zend_array *sym zend_long count = 0; zend_string *var_name; zend_ulong num_key; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; ZEND_HASH_FOREACH_KEY_VAL(arr, num_key, var_name, entry) { + zend_string *final_name; if (var_name) { - if (!php_valid_var_name(var_name) - || zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); - if (!php_valid_var_name(Z_STR(final_name))) { - zval_ptr_dtor_str(&final_name); + if (!php_valid_var_name(var_name) || zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { + final_name = php_prefix_varname(prefix, var_name); + + if (!php_valid_var_name(final_name)) { + zend_string_release_ex(final_name, false); continue; } } else { - ZVAL_STR_COPY(&final_name, var_name); + final_name = zend_string_copy(var_name); } } else { zend_string *str = zend_long_to_str(num_key); - php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), true); - zend_string_release_ex(str, 0); - if (!php_valid_var_name(Z_STR(final_name))) { - zval_ptr_dtor_str(&final_name); + final_name = php_prefix_varname(prefix, str); + zend_string_release_ex(str, false); + if (!php_valid_var_name(final_name)) { + zend_string_release_ex(final_name, false); continue; } } /* We previously checked if the var name is "this" to prefix it */ - ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); + if (Z_ISREF_P(entry)) { Z_ADDREF_P(entry); } else { ZVAL_MAKE_REF_EX(entry, 2); } - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); } zval_ptr_dtor(orig_var); ZVAL_REF(orig_var, Z_REF_P(entry)); } else { - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + zend_hash_add_new(symbol_table, final_name, entry); } count++; - zval_ptr_dtor_str(&final_name); + zend_string_release_ex(final_name, false); } ZEND_HASH_FOREACH_END(); return count; @@ -2313,50 +2307,50 @@ static zend_long php_extract_prefix_invalid(zend_array *arr, zend_array *symbol_ zend_long count = 0; zend_string *var_name; zend_ulong num_key; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; ZEND_HASH_FOREACH_KEY_VAL(arr, num_key, var_name, entry) { + zend_string *final_name; if (var_name) { - if (!php_valid_var_name(var_name) - || zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), true); - if (!php_valid_var_name(Z_STR(final_name))) { - zval_ptr_dtor_str(&final_name); + if (!php_valid_var_name(var_name) || zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { + final_name = php_prefix_varname(prefix, var_name); + if (!php_valid_var_name(final_name)) { + zend_string_release_ex(final_name, false); continue; } } else { - ZVAL_STR_COPY(&final_name, var_name); + final_name = zend_string_copy(var_name); } } else { zend_string *str = zend_long_to_str(num_key); - php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), true); + final_name = php_prefix_varname(prefix, str); zend_string_release_ex(str, 0); - if (!php_valid_var_name(Z_STR(final_name))) { - zval_ptr_dtor_str(&final_name); + if (!php_valid_var_name(final_name)) { + zend_string_release_ex(final_name, false); continue; } } /* We previously checked if the var name is "this" to prefix it */ - ZEND_ASSERT(!zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))); + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); ZVAL_DEREF(entry); - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { if (Z_TYPE_P(orig_var) == IS_INDIRECT) { orig_var = Z_INDIRECT_P(orig_var); } ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); if (UNEXPECTED(EG(exception))) { - zend_string_release_ex(Z_STR(final_name), 0); + zend_string_release_ex(final_name, false); return -1; } } else { Z_TRY_ADDREF_P(entry); - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + zend_hash_add_new(symbol_table, final_name, entry); } count++; - zval_ptr_dtor_str(&final_name); + zend_string_release_ex(final_name, false); } ZEND_HASH_FOREACH_END(); return count; diff --git a/ext/standard/basic_functions.h b/ext/standard/basic_functions.h index bad6fcf4e645e..8c8c6ba58dfd6 100644 --- a/ext/standard/basic_functions.h +++ b/ext/standard/basic_functions.h @@ -49,7 +49,6 @@ PHP_RSHUTDOWN_FUNCTION(browscap); /* Left for BC (not binary safe!) */ PHPAPI int _php_error_log(int opt_err, const char *message, const char *opt, const char *headers); PHPAPI int _php_error_log_ex(int opt_err, const char *message, size_t message_len, const char *opt, const char *headers); -PHPAPI int php_prefix_varname(zval *result, zend_string *prefix, const char *var_name, size_t var_name_len, bool add_underscore); typedef struct _php_basic_globals { HashTable *user_shutdown_function_names; From 095fd26c95baa4025ba811762c1920709dcf93eb Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 14 Nov 2025 08:48:07 +0000 Subject: [PATCH 4/6] ext/standard/array.c: add const qualifiers for extract() related functions --- ext/standard/array.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 3ccb5d25a9db6..f1b25387db060 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1716,7 +1716,7 @@ static zend_string* php_prefix_varname(const zend_string *prefix, const zend_str return zend_string_concat3(ZSTR_VAL(prefix), ZSTR_LEN(prefix), ZEND_STRL("_"), ZSTR_VAL(var_name), ZSTR_LEN(var_name)); } -static zend_long php_extract_ref_if_exists(zend_array *arr, zend_array *symbol_table) /* {{{ */ +static zend_long php_extract_ref_if_exists(const zend_array *arr, const zend_array *symbol_table) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -1762,7 +1762,7 @@ static zend_long php_extract_ref_if_exists(zend_array *arr, zend_array *symbol_t } /* }}} */ -static zend_long php_extract_if_exists(zend_array *arr, zend_array *symbol_table) /* {{{ */ +static zend_long php_extract_if_exists(const zend_array *arr, const zend_array *symbol_table) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -1806,7 +1806,7 @@ static zend_long php_extract_if_exists(zend_array *arr, zend_array *symbol_table } /* }}} */ -static zend_long php_extract_ref_overwrite(zend_array *arr, zend_array *symbol_table) /* {{{ */ +static zend_long php_extract_ref_overwrite(const zend_array *arr, zend_array *symbol_table) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -1858,7 +1858,7 @@ static zend_long php_extract_ref_overwrite(zend_array *arr, zend_array *symbol_t } /* }}} */ -static zend_long php_extract_overwrite(zend_array *arr, zend_array *symbol_table) /* {{{ */ +static zend_long php_extract_overwrite(const zend_array *arr, zend_array *symbol_table) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -1903,7 +1903,7 @@ static zend_long php_extract_overwrite(zend_array *arr, zend_array *symbol_table } /* }}} */ -static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_ref_prefix_if_exists(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -1960,7 +1960,7 @@ static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *s } /* }}} */ -static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_prefix_if_exists(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2012,7 +2012,7 @@ static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbo } /* }}} */ -static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_ref_prefix_same(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2087,7 +2087,7 @@ prefix:; } /* }}} */ -static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_prefix_same(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2154,7 +2154,7 @@ prefix:; } /* }}} */ -static zend_long php_extract_ref_prefix_all(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_ref_prefix_all(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2200,7 +2200,7 @@ static zend_long php_extract_ref_prefix_all(zend_array *arr, zend_array *symbol_ } /* }}} */ -static zend_long php_extract_prefix_all(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_prefix_all(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2246,7 +2246,7 @@ static zend_long php_extract_prefix_all(zend_array *arr, zend_array *symbol_tabl } /* }}} */ -static zend_long php_extract_ref_prefix_invalid(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_ref_prefix_invalid(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2302,7 +2302,7 @@ static zend_long php_extract_ref_prefix_invalid(zend_array *arr, zend_array *sym } /* }}} */ -static zend_long php_extract_prefix_invalid(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_prefix_invalid(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2357,7 +2357,7 @@ static zend_long php_extract_prefix_invalid(zend_array *arr, zend_array *symbol_ } /* }}} */ -static zend_long php_extract_ref_skip(zend_array *arr, zend_array *symbol_table) /* {{{ */ +static zend_long php_extract_ref_skip(const zend_array *arr, zend_array *symbol_table) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2405,7 +2405,7 @@ static zend_long php_extract_ref_skip(zend_array *arr, zend_array *symbol_table) } /* }}} */ -static zend_long php_extract_skip(zend_array *arr, zend_array *symbol_table) /* {{{ */ +static zend_long php_extract_skip(const zend_array *arr, zend_array *symbol_table) /* {{{ */ { zend_long count = 0; zend_string *var_name; From d026e2bca1d544ca2a3698087e5098199ada0bac Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sun, 16 Nov 2025 22:14:15 +0000 Subject: [PATCH 5/6] ext/standard/array.c: add tests when extracting negative keys --- .../tests/array/extract_negative_keys.phpt | 31 +++++++++++++++++++ .../tests/array/extract_negative_keys2.phpt | 11 +++++++ 2 files changed, 42 insertions(+) create mode 100644 ext/standard/tests/array/extract_negative_keys.phpt create mode 100644 ext/standard/tests/array/extract_negative_keys2.phpt diff --git a/ext/standard/tests/array/extract_negative_keys.phpt b/ext/standard/tests/array/extract_negative_keys.phpt new file mode 100644 index 0000000000000..55fce2a656570 --- /dev/null +++ b/ext/standard/tests/array/extract_negative_keys.phpt @@ -0,0 +1,31 @@ +--TEST-- +extract() with negative keys +--FILE-- + 'hello', 'world', 2 => 'positive', 'check' => 'extracted']; + +function foo(array $a) { + extract($a, EXTR_PREFIX_ALL, 'prefix'); + var_dump(get_defined_vars()); +} + +foo($a); +?> +--EXPECT-- +array(3) { + ["a"]=> + array(4) { + [-5]=> + string(5) "hello" + [-4]=> + string(5) "world" + [2]=> + string(8) "positive" + ["check"]=> + string(9) "extracted" + } + ["prefix_2"]=> + string(8) "positive" + ["prefix_check"]=> + string(9) "extracted" +} diff --git a/ext/standard/tests/array/extract_negative_keys2.phpt b/ext/standard/tests/array/extract_negative_keys2.phpt new file mode 100644 index 0000000000000..dd2a1fa7a18a4 --- /dev/null +++ b/ext/standard/tests/array/extract_negative_keys2.phpt @@ -0,0 +1,11 @@ +--TEST-- +extract() with negative keys +--FILE-- + "foo"]; +var_dump(extract($arr, EXTR_PREFIX_ALL | EXTR_REFS, "prefix")); + +?> +--EXPECT-- +int(0) From d40ae97f52b0c026e37072dbd896d67e949b91d3 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Wed, 19 Nov 2025 20:42:31 +0000 Subject: [PATCH 6/6] Zend language scanner: minor refactorings (#20480) * Use uint32_t type * Remove some useless size_t casts * Explain why we include zend_globals.h --- Zend/zend_language_scanner.h | 3 ++- Zend/zend_language_scanner.l | 15 ++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Zend/zend_language_scanner.h b/Zend/zend_language_scanner.h index 612c845479272..c494564ba2349 100644 --- a/Zend/zend_language_scanner.h +++ b/Zend/zend_language_scanner.h @@ -20,6 +20,7 @@ #ifndef ZEND_SCANNER_H #define ZEND_SCANNER_H +/* The zend_php_scanner_event enum is declared in zend_globals and we don't want everything to include zend_language_scanner.h */ #include "zend_globals.h" typedef struct _zend_lex_state { @@ -71,7 +72,7 @@ typedef struct _zend_heredoc_label { /* Track locations of unclosed {, [, (, etc. for better syntax error reporting */ typedef struct _zend_nest_location { char text; - int lineno; + uint32_t lineno; } zend_nest_location; BEGIN_EXTERN_C() diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 3ecb2f8d0ee45..1e26ddbd99199 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -30,6 +30,7 @@ #include "zend_language_scanner_defs.h" #include +#include #include "zend.h" #ifdef ZEND_WIN32 # include @@ -600,7 +601,7 @@ static zend_op_array *zend_compile(int type) CG(ast_arena) = zend_arena_create(1024 * 32); if (!zendparse()) { - int last_lineno = CG(zend_lineno); + uint32_t last_lineno = CG(zend_lineno); zend_file_context original_file_context; zend_oparray_context original_oparray_context; zend_op_array *original_active_op_array = CG(active_op_array); @@ -1140,7 +1141,7 @@ skip_escape_conversion: unsigned char *str; // TODO: avoid realocation ??? s = Z_STRVAL_P(zendlval); - SCNG(output_filter)(&str, &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval)); + SCNG(output_filter)(&str, &sz, (unsigned char *)s, Z_STRLEN_P(zendlval)); zval_ptr_dtor(zendlval); ZVAL_STRINGL(zendlval, (char *) str, sz); efree(str); @@ -1172,7 +1173,7 @@ static bool strip_multiline_string_indentation( const char *str = Z_STRVAL_P(zendlval), *end = str + Z_STRLEN_P(zendlval); char *copy = Z_STRVAL_P(zendlval); - int newline_count = 0; + uint32_t newline_count = 0; size_t newline_len; const char *nl; @@ -1253,7 +1254,7 @@ static void copy_heredoc_label_stack(void *void_heredoc_label) } /* Check that { }, [ ], ( ) are nested correctly */ -static void report_bad_nesting(char opening, int opening_lineno, char closing) +static void report_bad_nesting(char opening, uint32_t opening_lineno, char closing) { char buf[256]; size_t used = 0; @@ -1361,7 +1362,7 @@ int ZEND_FASTCALL lex_scan(zval *zendlval, zend_parser_stack_elem *elem) { int token; int offset; -int start_line = CG(zend_lineno); +uint32_t start_line = CG(zend_lineno); ZVAL_UNDEF(zendlval); restart: @@ -2499,7 +2500,7 @@ inline_char_handler: if (YYCURSOR < YYLIMIT) { YYCURSOR++; } else { - zend_throw_exception_ex(zend_ce_parse_error, 0, "Unterminated comment starting line %d", CG(zend_lineno)); + zend_throw_exception_ex(zend_ce_parse_error, 0, "Unterminated comment starting line %" PRIu32, CG(zend_lineno)); if (PARSER_MODE()) { RETURN_TOKEN(T_ERROR); } @@ -2616,7 +2617,7 @@ skip_escape_conversion: zend_string *new_str; s = Z_STRVAL_P(zendlval); // TODO: avoid reallocation ??? - SCNG(output_filter)((unsigned char **)&str, &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval)); + SCNG(output_filter)((unsigned char **)&str, &sz, (unsigned char *)s, Z_STRLEN_P(zendlval)); new_str = zend_string_init(str, sz, 0); if (str != s) { efree(str);