[php-src] master: Merge branch 'PHP-8.4' into PHP-8.5

Ilia Alshanetsky <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Ilia Alshanetsky (iliaal)
Date: 2026-08-30T12:14:02-04:00

Commit: https://github.com/php/php-src/commit/02d5d45e2c1222b15dbd513e51cd1616b9581472
Raw diff: https://github.com/php/php-src/commit/02d5d45e2c1222b15dbd513e51cd1616b9581472.diff

Merge branch 'PHP-8.4' into PHP-8.5

* PHP-8.4:
  [SOAP] Fix WSDL cache corruption when header defines headerfaults

Changed paths:
  A  ext/soap/tests/headerfault_cache.phpt
  A  ext/soap/tests/headerfault_cache.wsdl
  M  NEWS
  M  ext/soap/php_sdl.c


Diff:

diff --git a/NEWS b/NEWS
index 693ff78fafd0..75355cb5130a 100644
--- a/NEWS
+++ b/NEWS
@@ -67,6 +67,10 @@ PHP                                                                        NEWS
   . Fixed the interactive shell not waiting for the pager process to exit.
     (Weilin Du)
 
+- SOAP:
+  . Fixed WSDL cache corruption when a soap:header defines headerfaults.
+    (Ilia Alshanetsky)
+
 - Standard:
   . Fixed a segfault when a stream filter callback unsets StreamBucket::$data
     before re-attaching the bucket. (iliaal)
diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c
index cc01b598bd9c..566b8dc1e503 100644
--- a/ext/soap/php_sdl.c
+++ b/ext/soap/php_sdl.c
@@ -1152,7 +1152,7 @@ static sdlPtr load_wsdl(zval *this_ptr, char *struri)
 	return ctx.sdl;
 }
 
-#define WSDL_CACHE_VERSION 0x10
+#define WSDL_CACHE_VERSION 0x11
 
 #define WSDL_CACHE_GET(ret,type,buf)   memcpy(&ret,*buf,sizeof(type)); *buf += sizeof(type);
 #define WSDL_CACHE_GET_INT(ret,buf)    ret = ((unsigned char)(*buf)[0])|((unsigned char)(*buf)[1]<<8)|((unsigned char)(*buf)[2]<<16)|((unsigned)(*buf)[3]<<24); *buf += 4;
@@ -2063,7 +2063,7 @@ static void sdl_serialize_soap_body(const sdlSoapBindingFunctionBodyPtr body, co
 				sdlSoapBindingFunctionHeaderPtr tmp2;
 				const zend_string *key_inner;
 
-				ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(body->headers, key_inner, tmp2) {
+				ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(tmp->headerfaults, key_inner, tmp2) {
 					sdl_serialize_key(key_inner, out);
 					WSDL_CACHE_PUT_1(tmp2->use, out);
 					if (tmp2->use == SOAP_ENCODED) {
diff --git a/ext/soap/tests/headerfault_cache.phpt b/ext/soap/tests/headerfault_cache.phpt
new file mode 100644
index 000000000000..6da747902d80
--- /dev/null
+++ b/ext/soap/tests/headerfault_cache.phpt
@@ -0,0 +1,45 @@
+--TEST--
+WSDL cache corruption when soap:header has headerfaults
+--EXTENSIONS--
+soap
+--INI--
+soap.wsdl_cache_enabled=1
+--FILE--
+<?php
+$dir = __DIR__ . '/headerfault_cache_dir';
+@mkdir($dir);
+ini_set('soap.wsdl_cache_dir', $dir);
+
+$options = ['cache_wsdl' => WSDL_CACHE_DISK];
+
+$c1 = new SoapClient(__DIR__ . '/headerfault_cache.wsdl', $options);
+var_dump($c1->__getFunctions());
+
+$c2 = new SoapClient(__DIR__ . '/headerfault_cache.wsdl', $options);
+var_dump($c2->__getFunctions());
+
+echo "ok\n";
+?>
+--CLEAN--
+<?php
+$dir = __DIR__ . '/headerfault_cache_dir';
+if (is_dir($dir)) {
+    foreach (scandir($dir) as $f) {
+        if ($f === '.' || $f === '..') {
+            continue;
+        }
+        @unlink($dir . '/' . $f);
+    }
+    @rmdir($dir);
+}
+?>
+--EXPECT--
+array(1) {
+  [0]=>
+  string(32) "string testHeader(string $param)"
+}
+array(1) {
+  [0]=>
+  string(32) "string testHeader(string $param)"
+}
+ok
diff --git a/ext/soap/tests/headerfault_cache.wsdl b/ext/soap/tests/headerfault_cache.wsdl
new file mode 100644
index 000000000000..8a844c0b899d
--- /dev/null
+++ b/ext/soap/tests/headerfault_cache.wsdl
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://example.com/hf" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://example.com/hf">
+  <wsdl:message name="message">
+    <wsdl:part name="param" type="xsd:string"/>
+  </wsdl:message>
+  <wsdl:message name="authToken">
+    <wsdl:part name="authToken" type="xsd:string"/>
+  </wsdl:message>
+  <wsdl:message name="traceId">
+    <wsdl:part name="traceId" type="xsd:string"/>
+  </wsdl:message>
+  <wsdl:message name="faultToken">
+    <wsdl:part name="faultToken" type="xsd:string"/>
+  </wsdl:message>
+  <wsdl:message name="faultTrace">
+    <wsdl:part name="faultTrace" type="xsd:string"/>
+  </wsdl:message>
+  <wsdl:portType name="hf">
+    <wsdl:operation name="testHeader">
+      <wsdl:input message="tns:message"/>
+      <wsdl:output message="tns:message"/>
+    </wsdl:operation>
+  </wsdl:portType>
+  <wsdl:binding name="hfBinding" type="tns:hf">
+    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
+    <wsdl:operation name="testHeader">
+      <soap:operation soapAction="http://example.com/hf/testHeader"/>
+      <wsdl:input>
+        <soap:body namespace="http://example.com/hf" use="literal"/>
+        <soap:header namespace="http://example.com/hf" use="literal" part="authToken" message="tns:authToken">
+          <soap:headerfault namespace="http://example.com/hf" use="literal" part="faultToken" message="tns:faultToken"/>
+        </soap:header>
+        <soap:header namespace="http://example.com/hf" use="literal" part="traceId" message="tns:traceId">
+          <soap:headerfault namespace="http://example.com/hf" use="literal" part="faultTrace" message="tns:faultTrace"/>
+        </soap:header>
+      </wsdl:input>
+      <wsdl:output>
+        <soap:body namespace="http://example.com/hf" use="literal"/>
+      </wsdl:output>
+    </wsdl:operation>
+  </wsdl:binding>
+  <wsdl:service name="hfService">
+    <wsdl:port binding="tns:hfBinding" name="hfPort">
+      <soap:address location="http://localhost/hf.php"/>
+    </wsdl:port>
+  </wsdl:service>
+</wsdl:definitions>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.