Skip to content

Commit a9987fa

Browse files
committed
ext/soap: ignore empty SOAPAction header during server dispatch.
Fix #22285 Since 8.5 SoapServer::handle() uses the HTTP SOAPAction header to select the operation, falling back to the request body otherwise. An empty header made every request match the first WSDL operation. Skip empty SOAPAction headers so dispatch falls back to body inspection. close GH-22304
1 parent 8a43a0a commit a9987fa

4 files changed

Lines changed: 148 additions & 1 deletion

File tree

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ PHP NEWS
4444
- SOAP:
4545
. Fixed bug GH-22218 (SoapServer::handle() crash on $_SERVER not being
4646
an array). (David Carlier / Rex-Reynolds)
47+
. Fixed bug GH-22285 (Soap server requires the raw input to be passed
48+
to $server->handle). (David Carlier / ndossche)
4749

4850
- Sqlite:
4951
. Fix error checks for column retrieval. (ndossche)

ext/soap/soap.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1394,7 +1394,7 @@ PHP_METHOD(SoapServer, handle)
13941394
}
13951395
}
13961396

1397-
if ((soap_action_z = zend_hash_str_find(Z_ARRVAL_P(server_vars), ZEND_STRL("HTTP_SOAPACTION"))) != NULL && Z_TYPE_P(soap_action_z) == IS_STRING) {
1397+
if ((soap_action_z = zend_hash_str_find(Z_ARRVAL_P(server_vars), ZEND_STRL("HTTP_SOAPACTION"))) != NULL && Z_TYPE_P(soap_action_z) == IS_STRING && Z_STRLEN_P(soap_action_z) > 0) {
13981398
soap_action = Z_STRVAL_P(soap_action_z);
13991399
}
14001400
}
@@ -3178,6 +3178,10 @@ static sdlFunctionPtr find_function_using_soap_action(const sdl *sdl, const char
31783178
soap_action_length -= 2;
31793179
}
31803180

3181+
if (UNEXPECTED(soap_action_length == 0)) {
3182+
return NULL;
3183+
}
3184+
31813185
/* TODO: This may depend on a particular target namespace, in which case this won't find a match when multiple different
31823186
* target namespaces are used until #45282 is resolved. */
31833187
sdlFunctionPtr function;

ext/soap/tests/bugs/gh22285.phpt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
GH-22285 (SoapServer dispatches to the first function when the SOAPAction header is empty)
3+
--CREDITS--
4+
Jarkko Hyvärinen
5+
--EXTENSIONS--
6+
soap
7+
--INI--
8+
soap.wsdl_cache_enabled=0
9+
--SKIPIF--
10+
<?php
11+
if (php_sapi_name()=='cli') echo 'skip';
12+
?>
13+
--POST--
14+
<SOAP-ENV:Envelope
15+
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
16+
xmlns:ns1="urn:TestService">
17+
<SOAP-ENV:Body>
18+
<ns1:goodbyeIn>
19+
<name>World</name>
20+
</ns1:goodbyeIn>
21+
</SOAP-ENV:Body>
22+
</SOAP-ENV:Envelope>
23+
--FILE--
24+
<?php
25+
class TestWS {
26+
public function hello($params) {
27+
return ['message' => 'Hello ' . $params->name];
28+
}
29+
public function goodbye($params) {
30+
return ['message' => 'Goodbye ' . $params->name];
31+
}
32+
}
33+
34+
$server = new SoapServer(__DIR__ . '/gh22285.wsdl', [
35+
'cache_wsdl' => WSDL_CACHE_NONE,
36+
'encoding' => 'UTF-8',
37+
'soap_version' => SOAP_1_1,
38+
]);
39+
$server->setClass('TestWS');
40+
$_SERVER['HTTP_SOAPACTION'] = '""';
41+
$server->handle();
42+
?>
43+
--EXPECTF--
44+
<?xml version="1.0" encoding="UTF-8"?>
45+
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:TestService"><SOAP-ENV:Body><ns1:goodbyeOut><message>Goodbye World</message></ns1:goodbyeOut></SOAP-ENV:Body></SOAP-ENV:Envelope>

ext/soap/tests/bugs/gh22285.wsdl

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<wsdl:definitions
3+
name="TestService"
4+
targetNamespace="urn:TestService"
5+
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
6+
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
7+
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
8+
xmlns:tns="urn:TestService"
9+
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
10+
11+
<wsdl:types>
12+
<xsd:schema targetNamespace="urn:TestService">
13+
<xsd:element name="helloIn">
14+
<xsd:complexType>
15+
<xsd:sequence>
16+
<xsd:element name="name" type="xsd:string" />
17+
</xsd:sequence>
18+
</xsd:complexType>
19+
</xsd:element>
20+
<xsd:element name="helloOut">
21+
<xsd:complexType>
22+
<xsd:sequence>
23+
<xsd:element name="message" type="xsd:string" />
24+
</xsd:sequence>
25+
</xsd:complexType>
26+
</xsd:element>
27+
<xsd:element name="goodbyeIn">
28+
<xsd:complexType>
29+
<xsd:sequence>
30+
<xsd:element name="name" type="xsd:string" />
31+
</xsd:sequence>
32+
</xsd:complexType>
33+
</xsd:element>
34+
<xsd:element name="goodbyeOut">
35+
<xsd:complexType>
36+
<xsd:sequence>
37+
<xsd:element name="message" type="xsd:string" />
38+
</xsd:sequence>
39+
</xsd:complexType>
40+
</xsd:element>
41+
</xsd:schema>
42+
</wsdl:types>
43+
44+
<wsdl:message name="helloRequest">
45+
<wsdl:part element="tns:helloIn" name="helloIn" />
46+
</wsdl:message>
47+
<wsdl:message name="helloResponse">
48+
<wsdl:part element="tns:helloOut" name="helloOut" />
49+
</wsdl:message>
50+
<wsdl:message name="goodbyeRequest">
51+
<wsdl:part element="tns:goodbyeIn" name="goodbyeIn" />
52+
</wsdl:message>
53+
<wsdl:message name="goodbyeResponse">
54+
<wsdl:part element="tns:goodbyeOut" name="goodbyeOut" />
55+
</wsdl:message>
56+
57+
<wsdl:portType name="TestServicePortType">
58+
<wsdl:operation name="hello">
59+
<wsdl:input message="tns:helloRequest" name="helloRequest" />
60+
<wsdl:output message="tns:helloResponse" name="helloResponse" />
61+
</wsdl:operation>
62+
<wsdl:operation name="goodbye">
63+
<wsdl:input message="tns:goodbyeRequest" name="goodbyeRequest" />
64+
<wsdl:output message="tns:goodbyeResponse" name="goodbyeResponse" />
65+
</wsdl:operation>
66+
</wsdl:portType>
67+
68+
<wsdl:binding name="TestServiceBinding" type="tns:TestServicePortType">
69+
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
70+
<wsdl:operation name="hello">
71+
<wsdlsoap:operation soapAction="" />
72+
<wsdl:input name="helloRequest">
73+
<wsdlsoap:body use="literal" />
74+
</wsdl:input>
75+
<wsdl:output name="helloResponse">
76+
<wsdlsoap:body use="literal" />
77+
</wsdl:output>
78+
</wsdl:operation>
79+
<wsdl:operation name="goodbye">
80+
<wsdlsoap:operation soapAction="" />
81+
<wsdl:input name="goodbyeRequest">
82+
<wsdlsoap:body use="literal" />
83+
</wsdl:input>
84+
<wsdl:output name="goodbyeResponse">
85+
<wsdlsoap:body use="literal" />
86+
</wsdl:output>
87+
</wsdl:operation>
88+
</wsdl:binding>
89+
90+
<wsdl:service name="TestService">
91+
<wsdl:port name="TestServicePort" binding="tns:TestServiceBinding">
92+
<wsdlsoap:address location="http://localhost/server.php" />
93+
</wsdl:port>
94+
</wsdl:service>
95+
96+
</wsdl:definitions>

0 commit comments

Comments
 (0)