From 05b478c42161e54ca1df1ae15b792bf4a096064c Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Tue, 11 Aug 2026 20:02:58 +0800 Subject: [PATCH 1/6] tree-wide: Refactor with `zend_string_ends_with*` --- ext/json/json_encoder.c | 4 ++-- ext/odbc/php_odbc.c | 2 +- ext/opcache/ZendAccelerator.c | 4 ++-- ext/pgsql/pgsql.c | 2 +- ext/phar/phar_object.c | 2 +- ext/session/session.c | 2 +- ext/soap/php_http.c | 8 ++------ 7 files changed, 10 insertions(+), 14 deletions(-) diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c index b8ae31040c8b..d1bfc6b77bf7 100644 --- a/ext/json/json_encoder.c +++ b/ext/json/json_encoder.c @@ -182,7 +182,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, smart_str_appendc(buf, ','); } - bool empty = ZSTR_VAL(buf->s)[ZSTR_LEN(buf->s) - 1] != ','; + bool empty = !zend_string_ends_with_literal(buf->s, ","); if (!empty) { /* Drop the trailing comma. */ ZSTR_LEN(buf->s)--; @@ -312,7 +312,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, smart_str_appendc(buf, ','); } ZEND_HASH_FOREACH_END(); - empty = ZSTR_VAL(buf->s)[ZSTR_LEN(buf->s) - 1] != ','; + empty = !zend_string_ends_with_literal(buf->s, ","); if (!empty) { /* Drop the trailing comma. */ ZSTR_LEN(buf->s)--; diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 4d3081a3b076..468055732e14 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -1015,7 +1015,7 @@ PHP_FUNCTION(odbc_execute) if (ZSTR_LEN(tmpstr) > 2 && ZSTR_VAL(tmpstr)[0] == '\'' && - ZSTR_VAL(tmpstr)[ZSTR_LEN(tmpstr) - 1] == '\'') { + zend_string_ends_with_literal(tmpstr, "'")) { if (UNEXPECTED(zend_str_has_nul_byte(tmpstr))) { odbc_release_params(result, params); diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index cf62765d9e1d..6652efef3b45 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -1519,8 +1519,8 @@ static void zend_accel_add_key(zend_string *key, zend_accel_hash_entry *bucket) 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) && + return filename && ZSTR_LEN(filename) > sizeof(".phar") - 1 && + zend_string_ends_with_literal(filename, ".phar") && !strstr(ZSTR_VAL(filename), "://"); } diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 3a1b4a04cafb..1f7fa53fb173 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -3427,7 +3427,7 @@ static zend_result pgsql_copy_from_query(PGconn *pgsql, PGresult *pgsql_result, } int result; - if (ZSTR_LEN(tmp) > 0 && ZSTR_VAL(tmp)[ZSTR_LEN(tmp) - 1] != '\n') { + if (ZSTR_LEN(tmp) > 0 && !zend_string_ends_with_literal(tmp, "\n")) { char *zquery = zend_cstr_append_char( ZSTR_VAL(tmp), ZSTR_LEN(tmp), '\n'); result = PQputCopyData(pgsql, zquery, ZSTR_LEN(tmp) + 1); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 8a330a954b89..2fc17e7b9cea 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -4251,7 +4251,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 3, 5) static int extract_helper(const phar_archiv if (FAILURE == phar_extract_file(overwrite, entry, path_to, error)) return -1; extracted++; } ZEND_HASH_FOREACH_END(); - } else if (ZSTR_LEN(search) > 0 && '/' == ZSTR_VAL(search)[ZSTR_LEN(search) - 1]) { + } else if (zend_string_ends_with_literal(search, "/")) { /* ends in "/" -- extract all entries having that prefix */ ZEND_HASH_MAP_FOREACH_PTR(&archive->manifest, entry) { if (!zend_string_starts_with(entry->filename, search)) continue; diff --git a/ext/session/session.c b/ext/session/session.c index 5711f0daf216..c2bae0d808f1 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -876,7 +876,7 @@ static PHP_INI_MH(OnUpdateRfc1867Freq) return FAILURE; } - if (ZSTR_LEN(new_value) > 0 && ZSTR_VAL(new_value)[ZSTR_LEN(new_value) - 1] == '%') { + if (zend_string_ends_with_literal(new_value, "%")) { if (new_freq > 100) { php_error_docref(NULL, E_WARNING, "session.upload_progress.freq must be less than or equal to 100%%"); return FAILURE; diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index b49acd947b39..393cdf79eec0 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -341,13 +341,9 @@ static php_stream* http_connect(zval* this_ptr, php_uri *uri, bool use_ssl, php_ static bool in_domain(const zend_string *host, const zend_string *domain) { if (ZSTR_VAL(domain)[0] == '.') { - if (ZSTR_LEN(host) > ZSTR_LEN(domain)) { - return zend_string_equals_cstr(domain, ZSTR_VAL(host) + ZSTR_LEN(host) - ZSTR_LEN(domain), ZSTR_LEN(domain)); - } else { - return false; - } + return ZSTR_LEN(host) > ZSTR_LEN(domain) && zend_string_ends_with(host, domain); } else { - return zend_string_equals(host,domain); + return zend_string_equals(host, domain); } } From 4ec7b5438e98b7bd546619e5bd34deaf1b92496f Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Wed, 12 Aug 2026 10:44:29 +0800 Subject: [PATCH 2/6] feedback --- 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 6652efef3b45..96bf83a35527 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -1519,7 +1519,7 @@ static void zend_accel_add_key(zend_string *key, zend_accel_hash_entry *bucket) static zend_always_inline bool is_phar_file(const zend_string *filename) { - return filename && ZSTR_LEN(filename) > sizeof(".phar") - 1 && + return filename && zend_string_ends_with_literal(filename, ".phar") && !strstr(ZSTR_VAL(filename), "://"); } From 03d12c6a84fa9f1e0012e8c69878fb67b5a71fbf Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Wed, 12 Aug 2026 10:51:51 +0800 Subject: [PATCH 3/6] feedback_v2 --- ext/json/json_encoder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c index d1bfc6b77bf7..b8ae31040c8b 100644 --- a/ext/json/json_encoder.c +++ b/ext/json/json_encoder.c @@ -182,7 +182,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, smart_str_appendc(buf, ','); } - bool empty = !zend_string_ends_with_literal(buf->s, ","); + bool empty = ZSTR_VAL(buf->s)[ZSTR_LEN(buf->s) - 1] != ','; if (!empty) { /* Drop the trailing comma. */ ZSTR_LEN(buf->s)--; @@ -312,7 +312,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, smart_str_appendc(buf, ','); } ZEND_HASH_FOREACH_END(); - empty = !zend_string_ends_with_literal(buf->s, ","); + empty = ZSTR_VAL(buf->s)[ZSTR_LEN(buf->s) - 1] != ','; if (!empty) { /* Drop the trailing comma. */ ZSTR_LEN(buf->s)--; From 7e7cb42b1e189b174d2da6802a0c98a970d66c0b Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Wed, 12 Aug 2026 22:00:13 +0800 Subject: [PATCH 4/6] feedback_v3 --- ext/pgsql/pgsql.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 1f7fa53fb173..8467d1b7db24 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -3426,8 +3426,13 @@ static zend_result pgsql_copy_from_query(PGconn *pgsql, PGresult *pgsql_result, return FAILURE; } + if (ZSTR_LEN(tmp) == 0) { + zend_tmp_string_release(tmp_tmp); + return SUCCESS; + } + int result; - if (ZSTR_LEN(tmp) > 0 && !zend_string_ends_with_literal(tmp, "\n")) { + if (!zend_string_ends_with_literal(tmp, "\n")) { char *zquery = zend_cstr_append_char( ZSTR_VAL(tmp), ZSTR_LEN(tmp), '\n'); result = PQputCopyData(pgsql, zquery, ZSTR_LEN(tmp) + 1); From 91b8228b4d9fc1c974c9677225d1b8c1eda7bf77 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Wed, 12 Aug 2026 22:58:37 +0800 Subject: [PATCH 5/6] feedback_v4 --- ext/pgsql/pgsql.c | 9 +++------ ext/soap/php_http.c | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 8467d1b7db24..0a0ad3e66bd0 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -3426,13 +3426,10 @@ static zend_result pgsql_copy_from_query(PGconn *pgsql, PGresult *pgsql_result, return FAILURE; } - if (ZSTR_LEN(tmp) == 0) { - zend_tmp_string_release(tmp_tmp); - return SUCCESS; - } - int result; - if (!zend_string_ends_with_literal(tmp, "\n")) { + if (ZSTR_LEN(tmp) == 0) { + result = PQputCopyData(pgsql, ZSTR_VAL(tmp), 0); + } else if (!zend_string_ends_with_literal(tmp, "\n")) { char *zquery = zend_cstr_append_char( ZSTR_VAL(tmp), ZSTR_LEN(tmp), '\n'); result = PQputCopyData(pgsql, zquery, ZSTR_LEN(tmp) + 1); diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index 393cdf79eec0..5df9506102af 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -341,7 +341,7 @@ static php_stream* http_connect(zval* this_ptr, php_uri *uri, bool use_ssl, php_ static bool in_domain(const zend_string *host, const zend_string *domain) { if (ZSTR_VAL(domain)[0] == '.') { - return ZSTR_LEN(host) > ZSTR_LEN(domain) && zend_string_ends_with(host, domain); + return zend_string_ends_with(host, domain); } else { return zend_string_equals(host, domain); } From 19869fee9e807ff598d68772a78ace92cc97ad70 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Thu, 13 Aug 2026 01:21:50 +0800 Subject: [PATCH 6/6] feedback --- ext/pgsql/pgsql.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 0a0ad3e66bd0..9f0ca2c1a5e6 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -3427,15 +3427,13 @@ static zend_result pgsql_copy_from_query(PGconn *pgsql, PGresult *pgsql_result, } int result; - if (ZSTR_LEN(tmp) == 0) { - result = PQputCopyData(pgsql, ZSTR_VAL(tmp), 0); - } else if (!zend_string_ends_with_literal(tmp, "\n")) { + if (ZSTR_LEN(tmp) == 0 || zend_string_ends_with_literal(tmp, "\n")) { + result = PQputCopyData(pgsql, ZSTR_VAL(tmp), ZSTR_LEN(tmp)); + } else { char *zquery = zend_cstr_append_char( ZSTR_VAL(tmp), ZSTR_LEN(tmp), '\n'); result = PQputCopyData(pgsql, zquery, ZSTR_LEN(tmp) + 1); efree(zquery); - } else { - result = PQputCopyData(pgsql, ZSTR_VAL(tmp), ZSTR_LEN(tmp)); } zend_tmp_string_release(tmp_tmp);