File php8-CVE-2025-1220.patch of Package php8.39647

From 27e67cc3712ce0bc94fd4b2bfbb7155d89ec52d6 Mon Sep 17 00:00:00 2001
From: Jakub Zelenka <bukka@php.net>
Date: Thu, 10 Apr 2025 15:15:36 +0200
Subject: [PATCH] Fix GHSA-3cr5-j632-f35r: Null byte in hostnames

This fixes stream_socket_client() and fsockopen().

Specifically it adds a check to parse_ip_address_ex and it also makes
sure that the \0 is not ignored in fsockopen() hostname formatting.
---
 ext/standard/fsock.c                          | 27 +++++++++++++++++--
 .../tests/network/ghsa-3cr5-j632-f35r.phpt    | 21 +++++++++++++++
 .../tests/streams/ghsa-3cr5-j632-f35r.phpt    | 26 ++++++++++++++++++
 main/streams/xp_socket.c                      |  9 ++++---
 4 files changed, 78 insertions(+), 5 deletions(-)
 create mode 100644 ext/standard/tests/network/ghsa-3cr5-j632-f35r.phpt
 create mode 100644 ext/standard/tests/streams/ghsa-3cr5-j632-f35r.phpt

Index: php-8.0.30/ext/standard/fsock.c
===================================================================
--- php-8.0.30.orig/ext/standard/fsock.c
+++ php-8.0.30/ext/standard/fsock.c
@@ -23,6 +23,28 @@
 #include "php_network.h"
 #include "file.h"
 
+static size_t php_fsockopen_format_host_port(char **message, const char *prefix, size_t prefix_len,
+	const char *host, size_t host_len, zend_long port)
+{
+    char portbuf[32];
+    int portlen = snprintf(portbuf, sizeof(portbuf), ":" ZEND_LONG_FMT, port);
+    size_t total_len = prefix_len + host_len + portlen;
+
+    char *result = emalloc(total_len + 1); 
+
+	if (prefix_len > 0) {
+    	memcpy(result, prefix, prefix_len);
+	}
+    memcpy(result + prefix_len, host, host_len);
+    memcpy(result + prefix_len + host_len, portbuf, portlen);
+
+    result[total_len] = '\0';
+
+    *message = result;
+
+	return total_len;
+}
+
 /* {{{ php_fsockopen() */
 
 static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
@@ -62,11 +84,12 @@ static void php_fsockopen_stream(INTERNA
 	}
 
 	if (persistent) {
-		spprintf(&hashkey, 0, "pfsockopen__%s:" ZEND_LONG_FMT, host, port);
+		php_fsockopen_format_host_port(&hashkey, "pfsockopen__", strlen("pfsockopen__"), host,
+				host_len, port);
 	}
 
 	if (port > 0) {
-		hostname_len = spprintf(&hostname, 0, "%s:" ZEND_LONG_FMT, host, port);
+		hostname_len = php_fsockopen_format_host_port(&hostname, "", 0, host, host_len, port);
 	} else {
 		hostname_len = host_len;
 		hostname = host;
Index: php-8.0.30/main/streams/xp_socket.c
===================================================================
--- php-8.0.30.orig/main/streams/xp_socket.c
+++ php-8.0.30/main/streams/xp_socket.c
@@ -580,12 +580,15 @@ static inline char *parse_ip_address_ex(
 	char *colon;
 	char *host = NULL;
 
-#ifdef HAVE_IPV6
-	char *p;
+	if (memchr(str, '\0', str_len)) {
+		*err = strpprintf(0, "The hostname must not contain null bytes", str);
+		return NULL;
+	}
 
+#ifdef HAVE_IPV6
 	if (*(str) == '[' && str_len > 1) {
 		/* IPV6 notation to specify raw address with port (i.e. [fe80::1]:80) */
-		p = memchr(str + 1, ']', str_len - 2);
+		char *p = memchr(str + 1, ']', str_len - 2);
 		if (!p || *(p + 1) != ':') {
 			if (get_err) {
 				*err = strpprintf(0, "Failed to parse IPv6 address \"%s\"", str);
openSUSE Build Service is sponsored by