]> granicus.if.org Git - php/commitdiff
Fixed bug #55323 (SoapClient segmentation fault when XSD_TYPEKIND_EXTENSION contains...
authorDmitry Stogov <dmitry@php.net>
Wed, 10 Aug 2011 13:44:48 +0000 (13:44 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 10 Aug 2011 13:44:48 +0000 (13:44 +0000)
ext/soap/php_encoding.c
ext/soap/tests/bugs/bug55323.phpt [new file with mode: 0644]
ext/soap/tests/bugs/bug55323.wsdl [new file with mode: 0644]

index e87c84b263628582455d10521dca12138363e386..5469d6d8261027425b02b7503d3e48236ec36f13 100644 (file)
@@ -114,6 +114,26 @@ static void set_ns_and_type(xmlNodePtr node, encodeTypePtr type);
                } \
        }
 
+#define CHECK_XML_NULL(xml) \
+       { \
+               xmlAttrPtr null; \
+               if (!xml) { \
+                       zval *ret; \
+                       ALLOC_INIT_ZVAL(ret); \
+                       ZVAL_NULL(ret); \
+                       return ret; \
+               } \
+               if (xml->properties) { \
+                       null = get_attribute(xml->properties, "nil"); \
+                       if (null) { \
+                               zval *ret; \
+                               ALLOC_INIT_ZVAL(ret); \
+                               ZVAL_NULL(ret); \
+                               return ret; \
+                       } \
+               } \
+       }
+
 #define FIND_ZVAL_NULL(zval, xml, style) \
 { \
        if (!zval || Z_TYPE_P(zval) == IS_NULL) { \
@@ -338,6 +358,19 @@ static zend_bool soap_check_zval_ref(zval *data, xmlNodePtr node TSRMLS_DC) {
        return 0;
 }
 
+static zval* soap_find_xml_ref(xmlNodePtr node TSRMLS_DC)
+{
+       zval **data_ptr;
+
+       if (SOAP_GLOBAL(ref_map) && 
+           zend_hash_index_find(SOAP_GLOBAL(ref_map), (ulong)node, (void**)&data_ptr) == SUCCESS) {
+               Z_SET_ISREF_PP(data_ptr);
+               Z_ADDREF_PP(data_ptr);
+               return *data_ptr;
+       }
+       return NULL;
+}
+
 static zend_bool soap_check_xml_ref(zval **data, xmlNodePtr node TSRMLS_DC)
 {
        zval **data_ptr;
@@ -1497,6 +1530,11 @@ static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_e
                            sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
                            sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
 
+                               CHECK_XML_NULL(data);
+                               if ((ret = soap_find_xml_ref(data TSRMLS_CC)) != NULL) {
+                                       return ret;
+                               }
+
                            if (ce != ZEND_STANDARD_CLASS_DEF_PTR &&
                                sdlType->encode->to_zval == sdl_guess_convert_zval &&
                                sdlType->encode->details.sdl_type != NULL &&
@@ -1510,7 +1548,6 @@ static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_e
                            } else {
                                        ret = master_to_zval_int(sdlType->encode, data TSRMLS_CC);
                                }
-                               FIND_XML_NULL(data, ret);
                                if (soap_check_xml_ref(&ret, data TSRMLS_CC)) {
                                        return ret;
                                }
diff --git a/ext/soap/tests/bugs/bug55323.phpt b/ext/soap/tests/bugs/bug55323.phpt
new file mode 100644 (file)
index 0000000..7855dd8
--- /dev/null
@@ -0,0 +1,45 @@
+--TEST--
+Bug #55323 (SoapClient segmentation fault when XSD_TYPEKIND_EXTENSION contains itself)
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+ini_set("soap.wsdl_cache_enabled",0);
+$timestamp = "2011-07-30T03:25:00-05:00";
+$wsdl = dirname(__FILE__)."/bug55323.wsdl";
+
+class TestSoapClient extends SoapClient {
+
+  function __construct($wsdl, $options) {
+    parent::__construct($wsdl, $options);
+  }
+
+  function __doRequest($request, $location, $action, $version, $one_way = 0) {
+    return <<<EOF
+<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test.com/soap/v3/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
+   <SOAP-ENV:Body>
+      <ns1:getObjectResponse>
+         <getObjectReturn xsi:type="ns1:Customer" id="ref1">
+            <accountId xsi:type="xsd:int">1234</accountId>
+            <parent href="#ref1"/>
+         </getObjectReturn>
+      </ns1:getObjectResponse>
+   </SOAP-ENV:Body>
+</SOAP-ENV:Envelope>
+EOF;
+  }
+
+}
+
+$soapClient = new TestSoapClient($wsdl,
+        array('trace' => 1, 'exceptions' => 0));
+$result = $soapClient->getObject();
+var_dump($result);
+?>
+--EXPECTF--
+object(stdClass)#%d (2) {
+  ["accountId"]=>
+  int(1234)
+  ["parent"]=>
+  *RECURSION*
+}
diff --git a/ext/soap/tests/bugs/bug55323.wsdl b/ext/soap/tests/bugs/bug55323.wsdl
new file mode 100644 (file)
index 0000000..c260d34
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://test.com/soap/v3/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" name="slApi" targetNamespace="http://test.com/soap/v3/">
+  <types>
+    <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema"
+      targetNamespace="http://test.com/soap/v3/"
+      xmlns:tns="http://test.com/soap/v3/"
+      xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
+      xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+      elementFormDefault="qualified">
+      <complexType name="Customer">
+        <complexContent>
+          <extension base="tns:Interface">
+            <sequence>
+              <element minOccurs="0" maxOccurs="1" nillable="true" name="accountId" type="int"/>
+              <element minOccurs="0" maxOccurs="1" name="parent" type="tns:Customer"/>
+            </sequence>
+          </extension>
+        </complexContent>
+      </complexType>
+      <complexType name="Interface" abstract="true"/>
+    </xsd:schema>                                                              
+  </types>
+  <message name="getObject"/>
+  <message name="getObjectResponse">
+    <part name="getObjectReturn" type="tns:Customer"/>
+  </message>
+  <portType name="CustomerPortType">
+    <operation name="getObject">
+      <input message="tns:getObject"/>
+      <output message="tns:getObjectResponse"/>
+    </operation>
+  </portType>
+  <binding name="CustomerBinding" type="tns:CustomerPortType">
+    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
+    <operation name="getObject">
+      <soap:operation soapAction="http://test.com/soap/v3/CustomerAction"/>
+      <input>
+        <soap:body namespace="http://test.com/soap/v3/" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+      </input>
+      <output>
+        <soap:body namespace="http://test.com/soap/v3/" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+      </output>
+    </operation>
+  </binding>
+  <service name="CustomerService">
+    <port name="CustomerPort" binding="tns:CustomerBinding">
+      <soap:address location="test://"/>
+    </port>
+  </service>
+</definitions>