Commit 0a423006ff5 for php.net

commit 0a423006ff5aa7cc6a3bdde80f9f7fe3d08ba80c
Author: Gina Peter Banyard <girgias@php.net>
Date:   Thu Jul 23 15:14:10 2026 +0100

    standard/http_fopen_wrapper: use zend_string API in php_stream_http_response_headers_parse()

diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
index 70829eb8465..4a0f95062bc 100644
--- a/ext/standard/http_fopen_wrapper.c
+++ b/ext/standard/http_fopen_wrapper.c
@@ -187,21 +187,17 @@ static bool php_stream_http_response_header_trim(char *http_header_line,
  * last header line.  */
 static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *wrapper,
 		php_stream *stream, php_stream_context *context, int options,
-		zend_string *last_header_line_str, char *header_line, size_t *header_line_length,
+		zend_string *last_header_line, char *header_line, size_t *header_line_length,
 		int response_code, zval *response_header,
 		php_stream_http_response_header_info *header_info)
 {
-	char *last_header_line = ZSTR_VAL(last_header_line_str);
-	size_t last_header_line_length = ZSTR_LEN(last_header_line_str);
-	char *last_header_line_end = ZSTR_VAL(last_header_line_str) + ZSTR_LEN(last_header_line_str) - 1;
-
 	/* Process non empty header line. */
 	if (header_line && (*header_line != '\n' && *header_line != '\r')) {
 		/* Removing trailing white spaces. */
 		if (php_stream_http_response_header_trim(header_line, header_line_length) &&
 				*header_line_length == 0) {
 			/* Only spaces so treat as an empty folding header. */
-			return last_header_line_str;
+			return last_header_line;
 		}

 		/* Process folding headers if starting with a space or a tab. */
@@ -218,27 +214,27 @@ static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *w
 			ZEND_ASSERT(http_folded_header_line_length > 0);
 			/* Concatenate last header line, space and current header line. */
 			zend_string *extended_header_str = zend_string_concat3(
-					last_header_line, last_header_line_length,
+					ZSTR_VAL(last_header_line), ZSTR_LEN(last_header_line),
 					" ", 1,
 					http_folded_header_line, http_folded_header_line_length);
-			zend_string_efree(last_header_line_str);
-			last_header_line_str = extended_header_str;
+			zend_string_efree(last_header_line);
+			last_header_line = extended_header_str;
 			/* Return new header line. */
-			return last_header_line_str;
+			return last_header_line;
 		}
 	}

 	/* Find header separator position. */
-	char *last_header_value = memchr(last_header_line, ':', last_header_line_length);
+	char *last_header_value = memchr(ZSTR_VAL(last_header_line), ':', ZSTR_LEN(last_header_line));
 	if (last_header_value) {
 		/* Verify there is no space in header name */
-		const char *last_header_name = last_header_line + 1;
+		const char *last_header_name = ZSTR_VAL(last_header_line) + 1;
 		while (last_header_name < last_header_value) {
 			if (*last_header_name == ' ' || *last_header_name == '\t') {
 				header_info->error = true;
 				php_stream_wrapper_log_warn(wrapper, context, options, InvalidResponse,
 					"HTTP invalid response format (space in header name)!");
-				zend_string_efree(last_header_line_str);
+				zend_string_efree(last_header_line);
 				return NULL;
 			}
 			++last_header_name;
@@ -247,6 +243,7 @@ static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *w
 		last_header_value++; /* Skip ':'. */

 		/* Strip leading whitespace. */
+		const char *last_header_line_end = ZSTR_VAL(last_header_line) + ZSTR_LEN(last_header_line) - 1;
 		while (last_header_value < last_header_line_end
 				&& (*last_header_value == ' ' || *last_header_value == '\t')) {
 			last_header_value++;
@@ -256,14 +253,14 @@ static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *w
 		header_info->error = true;
 		php_stream_wrapper_log_warn(wrapper, context, options, InvalidResponse,
 				"HTTP invalid response format (no colon in header line)!");
-		zend_string_efree(last_header_line_str);
+		zend_string_efree(last_header_line);
 		return NULL;
 	}

 	bool store_header = true;
 	zval *tmpzval = NULL;

-	if (!strncasecmp(last_header_line, "Location:", sizeof("Location:")-1)) {
+	if (zend_string_starts_with_literal_ci(last_header_line, "Location:")) {
 		/* Check if the location should be followed. */
 		if (context && (tmpzval = php_stream_context_get_option(context, "http", "follow_location")) != NULL) {
 			header_info->follow_location = zend_is_true(tmpzval);
@@ -281,7 +278,7 @@ static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *w
 			php_stream_wrapper_log_warn(wrapper, context, options, InvalidResponse,
 					"HTTP Location header size is over the limit of %d bytes",
 					HTTP_HEADER_MAX_LOCATION_SIZE);
-			zend_string_efree(last_header_line_str);
+			zend_string_efree(last_header_line);
 			return NULL;
 		}
 		if (header_info->location_len == 0) {
@@ -291,9 +288,9 @@ static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *w
 		}
 		header_info->location_len = last_header_value_len;
 		memcpy(header_info->location, last_header_value, last_header_value_len + 1);
-	} else if (!strncasecmp(last_header_line, "Content-Type:", sizeof("Content-Type:")-1)) {
+	} else if (zend_string_starts_with_literal_ci(last_header_line, "Content-Type:")) {
 		php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, last_header_value, 0);
-	} else if (!strncasecmp(last_header_line, "Content-Length:", sizeof("Content-Length:")-1)) {
+	} else if (zend_string_starts_with_literal_ci(last_header_line, "Content-Length:")) {
 		/* https://www.rfc-editor.org/rfc/rfc9110.html#name-content-length */
 		const char *ptr = last_header_value;
 		/* must contain only digits, no + or - symbols */
@@ -304,11 +301,11 @@ static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *w
 			if (endptr && !*endptr) {
 				/* truncate for 32-bit such that no negative file sizes occur */
 				header_info->file_size = MIN(parsed, ZEND_LONG_MAX);
-				php_stream_notify_file_size(context, header_info->file_size, last_header_line, 0);
+				php_stream_notify_file_size(context, header_info->file_size, ZSTR_VAL(last_header_line), 0);
 			}
 		}
 	} else if (
-		!strncasecmp(last_header_line, "Transfer-Encoding:", sizeof("Transfer-Encoding:")-1)
+		zend_string_starts_with_literal_ci(last_header_line, "Transfer-Encoding:")
 		&& !strncasecmp(last_header_value, "Chunked", sizeof("Chunked")-1)
 	) {
 		/* Create filter to decode response body. */
@@ -335,10 +332,10 @@ static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *w

 	if (store_header) {
 		zval http_header;
-		ZVAL_NEW_STR(&http_header, last_header_line_str);
+		ZVAL_NEW_STR(&http_header, last_header_line);
 		zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_header);
 	} else {
-		zend_string_efree(last_header_line_str);
+		zend_string_efree(last_header_line);
 	}

 	return NULL;