Skip to content

Commit 57a39c1

Browse files
committedSep 13, 2024
Fix bug #45282: SoapClient has namespace issues when WSDL is distributed
We're ignoring the namespaces that the messages, ports, bindings and services are defined in when registering them. Consequently, we're also ignoring the namespace component of the QName when looking up references. This patch solves this issue by introducing a new qname_hash_table type along with two methods to add and query the table. Internally, it's a nested HashTable where the outer layer is the namespace uri and the inner layer is the local name. It's worth pointing out that at least one comment in the original issue points to a WSDL that actually has a validation issue because it has two messages with the same local name in the same namespace, so in that case PHP's SOAP client is actually correct. The other links in the comments no longer exist, but I was able to reconstruct the issue based on reading the report and by cross-checking the expected behaviour with the WSDL spec.
1 parent b4d9649 commit 57a39c1

9 files changed

+282
-77
lines changed
 

‎ext/soap/php_sdl.c

+140-73
Large diffs are not rendered by default.

‎ext/soap/php_sdl.h

+8-4
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,19 @@ struct _sdl {
6161
bool is_persistent;
6262
};
6363

64+
typedef struct qname_hash_table {
65+
HashTable inner;
66+
} qname_hash_table;
67+
6468
typedef struct sdlCtx {
6569
sdlPtr sdl;
6670

6771
HashTable docs; /* array of xmlDocPtr */
6872

69-
HashTable messages; /* array of xmlNodePtr */
70-
HashTable bindings; /* array of xmlNodePtr */
71-
HashTable portTypes; /* array of xmlNodePtr */
72-
HashTable services; /* array of xmlNodePtr */
73+
qname_hash_table messages; /* array of xmlNodePtr */
74+
qname_hash_table bindings; /* array of xmlNodePtr */
75+
qname_hash_table portTypes; /* array of xmlNodePtr */
76+
qname_hash_table services; /* array of xmlNodePtr */
7377

7478
HashTable *attributes; /* array of sdlAttributePtr */
7579
HashTable *attributeGroups; /* array of sdlTypesPtr */

‎ext/soap/tests/bugs/bug45282_a.phpt

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Bug #45282 (SoapClient has namespace issues when WSDL is distributed)
3+
--EXTENSIONS--
4+
soap
5+
--INI--
6+
soap.wsdl_cache_enabled=0
7+
--FILE--
8+
<?php
9+
$client = new SoapClient(__DIR__ . "/bug45282_a.wsdl");
10+
var_dump($client->__getFunctions());
11+
?>
12+
--EXPECT--
13+
array(3) {
14+
[0]=>
15+
string(34) "date reportHealthView(int $number)"
16+
[1]=>
17+
string(34) "void reportHealthView(string $str)"
18+
[2]=>
19+
string(34) "date reportHealthView(int $number)"
20+
}

‎ext/soap/tests/bugs/bug45282_a.wsdl

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<definitions
3+
xmlns="http://schemas.xmlsoap.org/wsdl/"
4+
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
5+
xmlns:tns="http://wssmcommupper/"
6+
xmlns:tnsi="http://wssmcommupper/imported"
7+
xmlns:xs="http://www.w3.org/2001/XMLSchema"
8+
name="WSSmCommUpperImplService"
9+
targetNamespace="http://wssmcommupper/">
10+
<types/>
11+
<import namespace="http://wssmcommupper/imported" location="bug45282_import.wsdl" />
12+
<message name="reportHealthView">
13+
<part type="xs:string" name="str" />
14+
</message>
15+
<portType name="wssmcommupper">
16+
<operation name="reportHealthView">
17+
<input message="tns:reportHealthView" name="reportHealthView" />
18+
</operation>
19+
</portType>
20+
<binding name="WSSmCommUpperImplServiceSoapBinding" type="tns:wssmcommupper">
21+
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
22+
<operation name="reportHealthView">
23+
<soap:operation soapAction="" style="document" />
24+
<input name="reportHealthView">
25+
<soap:body use="literal" />
26+
</input>
27+
</operation>
28+
</binding>
29+
<service name="WSSmCommUpperImplService">
30+
<port binding="tns:WSSmCommUpperImplServiceSoapBinding" name="WSSmCommUpperImplPort">
31+
<soap:address location="http://172.20.22.9:10081/WSSmCommUpper/WSSmCommUpper" />
32+
</port>
33+
</service>
34+
<!-- cross-reference imported definitions -->
35+
<service name="WSSmCommUpperImplService2">
36+
<port binding="tnsi:WSSmCommUpperImplServiceSoapBinding" name="WSSmCommUpperImplPort">
37+
<soap:address location="http://172.20.22.9:10081/WSSmCommUpper/WSSmCommUpper" />
38+
</port>
39+
</service>
40+
</definitions>

‎ext/soap/tests/bugs/bug45282_b.phpt

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Bug #45282 (SoapClient has namespace issues when WSDL is distributed)
3+
--EXTENSIONS--
4+
soap
5+
--SKIPIF--
6+
<?php
7+
if (getenv('SKIP_ASAN')) die('xleak libxml does not use the request allocator');
8+
?>
9+
--INI--
10+
soap.wsdl_cache_enabled=0
11+
--FILE--
12+
<?php
13+
try {
14+
new SoapClient(__DIR__ . "/bug45282_b.wsdl");
15+
} catch (SoapFault $e) {
16+
echo $e->getMessage();
17+
}
18+
?>
19+
--EXPECT--
20+
SOAP-ERROR: Parsing WSDL: <message> 'reportHealthView' already defined

‎ext/soap/tests/bugs/bug45282_b.wsdl

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<definitions
3+
xmlns="http://schemas.xmlsoap.org/wsdl/"
4+
xmlns:xs="http://www.w3.org/2001/XMLSchema"
5+
name="WSSmCommUpperImplService"
6+
targetNamespace="http://wssmcommupper/x">
7+
<types/>
8+
<message name="reportHealthView">
9+
<part name="number" type="xs:int"/>
10+
</message>
11+
<import location="bug45282_import_nested1.wsdl"/>
12+
</definitions>
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
2+
targetNamespace="http://wssmcommupper/imported"
3+
xmlns:x="http://wssmcommupper/x"
4+
xmlns:parent="http://wssmcommupper/"
5+
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
6+
<import location="bug45282_import_nested1.wsdl"/>
7+
<import namespace="http://wssmcommupper/imported" location="bug45282_import_nested2.wsdl"/>
8+
<portType name="wssmcommupper">
9+
<operation name="reportHealthView">
10+
<input message="x:reportHealthView" name="reportHealthView" />
11+
<output message="parent:reportHealthViewOut" name="reportHealthView" />
12+
</operation>
13+
</portType>
14+
<!-- Intentionally missing tns declaration to test the BC fallback -->
15+
<binding name="WSSmCommUpperImplServiceSoapBinding" type="tns:wssmcommupper">
16+
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
17+
<operation name="reportHealthView">
18+
<soap:operation soapAction="" style="document" />
19+
<input name="reportHealthView">
20+
<soap:body use="literal" />
21+
</input>
22+
</operation>
23+
</binding>
24+
<service name="WSSmCommUpperImplService">
25+
<port binding="tns:WSSmCommUpperImplServiceSoapBinding" name="WSSmCommUpperImplPort">
26+
<soap:address location="http://172.20.22.9:10081/WSSmCommUpper/WSSmCommUpper" />
27+
</port>
28+
</service>
29+
</definitions>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
2+
targetNamespace="http://wssmcommupper/x"
3+
xmlns:xs="http://www.w3.org/2001/XMLSchema">
4+
<message name="reportHealthView">
5+
<part name="number" type="xs:int"/>
6+
</message>
7+
</definitions>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
2+
xmlns:xs="http://www.w3.org/2001/XMLSchema">
3+
<message name="reportHealthViewOut">
4+
<part name="date" type="xs:date"/>
5+
</message>
6+
</definitions>

0 commit comments

Comments
 (0)
Please sign in to comment.