Commit:    552e8b2b4c5708cb90faf148bd99e3f67fa926b5
Author:    Dmitry Stogov <dmi...@zend.com>         Tue, 10 Dec 2013 17:57:05 
+0400
Parents:   a46f644b3ac4abe7577165de4e4850e5c2c88227
Branches:  PHP-5.5 PHP-5.6 master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=552e8b2b4c5708cb90faf148bd99e3f67fa926b5

Log:
Fixed bug #66112 (Use after free condition in SOAP extension). (martin dot 
koegler at brz dot gv dot at)

Bugs:
https://bugs.php.net/66112

Changed paths:
  M  NEWS
  M  ext/soap/soap.c
  A  ext/soap/tests/bugs/bug66112.phpt
  A  ext/soap/tests/bugs/bug66112.wsdl

diff --git a/NEWS b/NEWS
index 0d6edf2..1e7ce53 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,10 @@ PHP                                                          
              NEWS
 - Filter:
   . Fixed bug #66229 (128.0.0.0/16 isn't reserved any longer). (Adam)
 
+- SOAP
+  . Fixed bug #66112 (Use after free condition in SOAP extension).
+    (martin dot koegler at brz dot gv dot at)
+
 - Sockets:
   . Fixed bug #65923 (ext/socket assumes AI_V4MAPPED is defined). (Felipe)
 
diff --git a/ext/soap/soap.c b/ext/soap/soap.c
index 0404096..3448df4 100644
--- a/ext/soap/soap.c
+++ b/ext/soap/soap.c
@@ -2694,124 +2694,133 @@ static void do_soap_call(zval* this_ptr,
                SOAP_GLOBAL(features) = 0;
        }
 
-       if (sdl != NULL) {
-               fn = get_function(sdl, function);
-               if (fn != NULL) {
-                       sdlBindingPtr binding = fn->binding;
-                       int one_way = 0;
-
-                       if (fn->responseName == NULL &&
-                           fn->responseParameters == NULL &&
-                           soap_headers == NULL) {
-                               one_way = 1;
-                       }
+       zend_try {
+               if (sdl != NULL) {
+                       fn = get_function(sdl, function);
+                       if (fn != NULL) {
+                               sdlBindingPtr binding = fn->binding;
+                               int one_way = 0;
+
+                               if (fn->responseName == NULL &&
+                                   fn->responseParameters == NULL &&
+                                   soap_headers == NULL) {
+                                       one_way = 1;
+                               }
 
-                       if (location == NULL) {
-                               location = binding->location;
-                       }
-                       if (binding->bindingType == BINDING_SOAP) {
-                               sdlSoapBindingFunctionPtr fnb = 
(sdlSoapBindingFunctionPtr)fn->bindingAttributes;
-                               request = serialize_function_call(this_ptr, fn, 
NULL, fnb->input.ns, real_args, arg_count, soap_version, soap_headers 
TSRMLS_CC);
-                               ret = do_request(this_ptr, request, location, 
fnb->soapAction, soap_version, one_way, &response TSRMLS_CC);
-                       }       else {
-                               request = serialize_function_call(this_ptr, fn, 
NULL, sdl->target_ns, real_args, arg_count, soap_version, soap_headers 
TSRMLS_CC);
-                               ret = do_request(this_ptr, request, location, 
NULL, soap_version, one_way, &response TSRMLS_CC);
-                       }
-
-                       xmlFreeDoc(request);
-
-                       if (ret && Z_TYPE(response) == IS_STRING) {
-                               encode_reset_ns();
-                               ret = parse_packet_soap(this_ptr, 
Z_STRVAL(response), Z_STRLEN(response), fn, NULL, return_value, output_headers 
TSRMLS_CC);
-                               encode_finish();
-                       }
+                               if (location == NULL) {
+                                       location = binding->location;
+                               }
+                               if (binding->bindingType == BINDING_SOAP) {
+                                       sdlSoapBindingFunctionPtr fnb = 
(sdlSoapBindingFunctionPtr)fn->bindingAttributes;
+                                       request = 
serialize_function_call(this_ptr, fn, NULL, fnb->input.ns, real_args, 
arg_count, soap_version, soap_headers TSRMLS_CC);
+                                       ret = do_request(this_ptr, request, 
location, fnb->soapAction, soap_version, one_way, &response TSRMLS_CC);
+                               } else {
+                                       request = 
serialize_function_call(this_ptr, fn, NULL, sdl->target_ns, real_args, 
arg_count, soap_version, soap_headers TSRMLS_CC);
+                                       ret = do_request(this_ptr, request, 
location, NULL, soap_version, one_way, &response TSRMLS_CC);
+                               }
+
+                               xmlFreeDoc(request);
+
+                               if (ret && Z_TYPE(response) == IS_STRING) {
+                                       encode_reset_ns();
+                                       ret = parse_packet_soap(this_ptr, 
Z_STRVAL(response), Z_STRLEN(response), fn, NULL, return_value, output_headers 
TSRMLS_CC);
+                                       encode_finish();
+                               }
 
-                       zval_dtor(&response);
+                               zval_dtor(&response);
 
-               } else {
-                       smart_str error = {0};
-                       smart_str_appends(&error,"Function (\"");
-                       smart_str_appends(&error,function);
-                       smart_str_appends(&error,"\") is not a valid method for 
this service");
-                       smart_str_0(&error);
-                       add_soap_fault(this_ptr, "Client", error.c, NULL, NULL 
TSRMLS_CC);
-                       smart_str_free(&error);
-               }
-       } else {
-               zval **uri;
-               smart_str action = {0};
-
-               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "uri", sizeof("uri"), 
(void *)&uri) == FAILURE) {
-                       add_soap_fault(this_ptr, "Client", "Error finding 
\"uri\" property", NULL, NULL TSRMLS_CC);
-               } else if (location == NULL) {
-                       add_soap_fault(this_ptr, "Client", "Error could not 
find \"location\" property", NULL, NULL TSRMLS_CC);
-               } else {
-                       if (call_uri == NULL) {
-                               call_uri = Z_STRVAL_PP(uri);
+                       } else {
+                               smart_str error = {0};
+                               smart_str_appends(&error,"Function (\"");
+                               smart_str_appends(&error,function);
+                               smart_str_appends(&error,"\") is not a valid 
method for this service");
+                               smart_str_0(&error);
+                               add_soap_fault(this_ptr, "Client", error.c, 
NULL, NULL TSRMLS_CC);
+                               smart_str_free(&error);
                        }
-                       request = serialize_function_call(this_ptr, NULL, 
function, call_uri, real_args, arg_count, soap_version, soap_headers TSRMLS_CC);
+               } else {
+                       zval **uri;
+                       smart_str action = {0};
 
-                       if (soap_action == NULL) {
-                               smart_str_appends(&action, call_uri);
-                               smart_str_appendc(&action, '#');
-                               smart_str_appends(&action, function);
+                       if (zend_hash_find(Z_OBJPROP_P(this_ptr), "uri", 
sizeof("uri"), (void *)&uri) == FAILURE) {
+                               add_soap_fault(this_ptr, "Client", "Error 
finding \"uri\" property", NULL, NULL TSRMLS_CC);
+                       } else if (location == NULL) {
+                               add_soap_fault(this_ptr, "Client", "Error could 
not find \"location\" property", NULL, NULL TSRMLS_CC);
                        } else {
-                               smart_str_appends(&action, soap_action);
-                       }
-                       smart_str_0(&action);
+                               if (call_uri == NULL) {
+                                       call_uri = Z_STRVAL_PP(uri);
+                               }
+                               request = serialize_function_call(this_ptr, 
NULL, function, call_uri, real_args, arg_count, soap_version, soap_headers 
TSRMLS_CC);
 
-                       ret = do_request(this_ptr, request, location, action.c, 
soap_version, 0, &response TSRMLS_CC);
+                               if (soap_action == NULL) {
+                                       smart_str_appends(&action, call_uri);
+                                       smart_str_appendc(&action, '#');
+                                       smart_str_appends(&action, function);
+                               } else {
+                                       smart_str_appends(&action, soap_action);
+                               }
+                               smart_str_0(&action);
 
-                       smart_str_free(&action);
-                       xmlFreeDoc(request);
+                               ret = do_request(this_ptr, request, location, 
action.c, soap_version, 0, &response TSRMLS_CC);
 
-                       if (ret && Z_TYPE(response) == IS_STRING) {
-                               encode_reset_ns();
-                               ret = parse_packet_soap(this_ptr, 
Z_STRVAL(response), Z_STRLEN(response), NULL, function, return_value, 
output_headers TSRMLS_CC);
-                               encode_finish();
-                       }
+                               smart_str_free(&action);
+                               xmlFreeDoc(request);
 
-                       zval_dtor(&response);
-               }
-       }
+                               if (ret && Z_TYPE(response) == IS_STRING) {
+                                       encode_reset_ns();
+                                       ret = parse_packet_soap(this_ptr, 
Z_STRVAL(response), Z_STRLEN(response), NULL, function, return_value, 
output_headers TSRMLS_CC);
+                                       encode_finish();
+                               }
 
-       if (!ret) {
-               zval** fault;
-               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", 
sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
-                       *return_value = **fault;
-                       zval_copy_ctor(return_value);
+                               zval_dtor(&response);
+                       }
+               }
+
+               if (!ret) {
+                       zval** fault;
+                       if (zend_hash_find(Z_OBJPROP_P(this_ptr), 
"__soap_fault", sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
+                               *return_value = **fault;
+                               zval_copy_ctor(return_value);
+                       } else {
+                               *return_value = *add_soap_fault(this_ptr, 
"Client", "Unknown Error", NULL, NULL TSRMLS_CC);
+                               zval_copy_ctor(return_value);
+                       }
                } else {
-                       *return_value = *add_soap_fault(this_ptr, "Client", 
"Unknown Error", NULL, NULL TSRMLS_CC);
-                       zval_copy_ctor(return_value);
-               }
-       } else {
-               zval** fault;
-               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", 
sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
-                       *return_value = **fault;
-                       zval_copy_ctor(return_value);
+                       zval** fault;
+                       if (zend_hash_find(Z_OBJPROP_P(this_ptr), 
"__soap_fault", sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
+                               *return_value = **fault;
+                               zval_copy_ctor(return_value);
+                       }
                }
-       }
 
-       if (!EG(exception) &&
-           Z_TYPE_P(return_value) == IS_OBJECT &&
-           instanceof_function(Z_OBJCE_P(return_value), soap_fault_class_entry 
TSRMLS_CC) &&
-           (zend_hash_find(Z_OBJPROP_P(this_ptr), "_exceptions", 
sizeof("_exceptions"), (void **) &tmp) != SUCCESS ||
-                  Z_TYPE_PP(tmp) != IS_BOOL || Z_LVAL_PP(tmp) != 0)) {
-               zval *exception;
+               if (!EG(exception) &&
+                   Z_TYPE_P(return_value) == IS_OBJECT &&
+                   instanceof_function(Z_OBJCE_P(return_value), 
soap_fault_class_entry TSRMLS_CC) &&
+                   (zend_hash_find(Z_OBJPROP_P(this_ptr), "_exceptions", 
sizeof("_exceptions"), (void **) &tmp) != SUCCESS ||
+                          Z_TYPE_PP(tmp) != IS_BOOL || Z_LVAL_PP(tmp) != 0)) {
+                       zval *exception;
 
-               MAKE_STD_ZVAL(exception);
-               MAKE_COPY_ZVAL(&return_value, exception);
-               zend_throw_exception_object(exception TSRMLS_CC);
-       }
+                       MAKE_STD_ZVAL(exception);
+                       MAKE_COPY_ZVAL(&return_value, exception);
+                       zend_throw_exception_object(exception TSRMLS_CC);
+               }
 
+       } zend_catch {
+               _bailout = 1;
+       } zend_end_try();
+       
        if (SOAP_GLOBAL(encoding) != NULL) {
                xmlCharEncCloseFunc(SOAP_GLOBAL(encoding));
        }
+
        SOAP_GLOBAL(features) = old_features;
        SOAP_GLOBAL(typemap) = old_typemap;
        SOAP_GLOBAL(class_map) = old_class_map;
        SOAP_GLOBAL(encoding) = old_encoding;
        SOAP_GLOBAL(sdl) = old_sdl;
+       if (_bailout) {
+               zend_bailout();
+       }
        SOAP_CLIENT_END_CODE();
 }
 
diff --git a/ext/soap/tests/bugs/bug66112.phpt 
b/ext/soap/tests/bugs/bug66112.phpt
new file mode 100644
index 0000000..6df3a4e
--- /dev/null
+++ b/ext/soap/tests/bugs/bug66112.phpt
@@ -0,0 +1,35 @@
+--TEST--
+Bug #66112 (Use after free condition in SOAP extension)
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--INI--
+soap.wsdl_cache_enabled=0
+--FILE--
+<?php
+define('WSDL', dirname(__FILE__)."/bug66112.wsdl");
+function Mist($p) {
+       $client=new soapclient(WSDL, 
array('typemap'=>array(array("type_ns"=>"uri:mist", "type_name"=>"A"))));
+       try{
+               $client->Mist(array("XX"=>"xx"));
+       }catch(SoapFault $x){
+       }
+       return array("A"=>"ABC","B"=>"sss");
+}
+$s = new SoapServer(WSDL, array('typemap'=>array(array("type_ns"=>"uri:mist", 
"type_name"=>"A"))));
+$s->addFunction("Mist");
+$_SERVER["REQUEST_METHOD"] = "POST";
+$HTTP_RAW_POST_DATA=<<<EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"; 
xmlns:uri="uri:mist">
+   <soapenv:Header/>
+   <soapenv:Body>
+      <uri:Request><uri:A>XXX</uri:A><uri:B>yyy</uri:B></uri:Request>
+   </soapenv:Body>
+</soapenv:Envelope>
+EOF;
+echo "OK\n";
+$s->handle($HTTP_RAW_POST_DATA);
+echo "BUG\n";
+?>
+--EXPECT--
+OK
diff --git a/ext/soap/tests/bugs/bug66112.wsdl 
b/ext/soap/tests/bugs/bug66112.wsdl
new file mode 100644
index 0000000..8589a46
--- /dev/null
+++ b/ext/soap/tests/bugs/bug66112.wsdl
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wsdl:definitions xmlns:tns="uri:mist" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"; 
xmlns:xs="http://www.w3.org/2001/XMLSchema"; 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; name="test" 
targetNamespace="uri:mist">
+  <wsdl:types>
+    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"; 
targetNamespace="uri:mist">
+      <xs:complexType name="T1">
+        <xs:sequence>
+          <xs:element name="A" type="xsd:string"/><xs:element name="B" 
type="xsd:string"/>
+        </xs:sequence>
+      </xs:complexType>
+      <xs:element name="Request" type="tns:T1"/><xs:element name="Response" 
type="tns:T1"/>
+    </xs:schema>
+  </wsdl:types>
+  <wsdl:message name="Request">
+    <wsdl:part name="Request" element="tns:Request"/>
+  </wsdl:message>
+  <wsdl:message name="Response">
+    <wsdl:part name="Response" element="tns:Response"/>
+  </wsdl:message>
+  <wsdl:portType name="test">
+    <wsdl:operation name="Mist">
+      <wsdl:input message="tns:Request"/>
+      <wsdl:output message="tns:Response"/>
+    </wsdl:operation>
+  </wsdl:portType>
+  <wsdl:binding name="test" type="tns:test">
+    <soap:binding style="document" 
transport="http://schemas.xmlsoap.org/soap/http"/>
+    <wsdl:operation name="Mist">
+      <soap:operation soapAction="Mist"/>
+      <wsdl:input>
+        <soap:body use="literal"/>
+      </wsdl:input>
+      <wsdl:output>
+        <soap:body use="literal"/>
+      </wsdl:output>
+    </wsdl:operation>
+  </wsdl:binding>
+  <wsdl:service name="test">
+    <wsdl:port name="test" binding="tns:test">
+      <soap:address location="http://127.0.0.1:81/mist.php"/>
+    </wsdl:port>
+  </wsdl:service>
+</wsdl:definitions>
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to