Skip to content

Commit

Permalink
Merge branch 'PHP-5.6'
Browse files Browse the repository at this point in the history
* PHP-5.6:
  Fixed bug #66112 (Use after free condition in SOAP extension). (martin dot koegler at brz dot gv dot at)
  • Loading branch information
dstogov committed Dec 10, 2013
2 parents d439b39 + fe93347 commit ad4f0c7
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 94 deletions.
197 changes: 103 additions & 94 deletions ext/soap/soap.c
Expand Up @@ -2691,124 +2691,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();
}

Expand Down
35 changes: 35 additions & 0 deletions 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
42 changes: 42 additions & 0 deletions 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>

0 comments on commit ad4f0c7

Please sign in to comment.