Fix persistent XML memory leaks in SOAP

SOAP uses a horrible bailout based error handling approach -- avoid
leaking persistent XML memory by catching bailouts in a number of
places.
This commit is contained in:
Nikita Popov 2019-06-27 10:57:49 +02:00
parent cfeda978df
commit 78375aa52f
3 changed files with 46 additions and 8 deletions

View file

@ -1519,7 +1519,13 @@ static zval *to_zval_object_ex(zval *ret, encodeTypePtr type, xmlNodePtr data, z
text = xmlNewText(BAD_CAST(str_val));
xmlAddChild(dummy, text);
ZVAL_NULL(&data);
/* TODO: There are other places using dummy nodes -- generalize? */
zend_try {
master_to_zval(&data, attr->encode, dummy);
} zend_catch {
xmlFreeNode(dummy);
zend_bailout();
} zend_end_try();
xmlFreeNode(dummy);
set_zval_property(ret, attr->name, &data);
}

View file

@ -739,7 +739,9 @@ static sdlPtr load_wsdl(zval *this_ptr, char *struri)
zend_hash_init(&ctx.portTypes, 0, NULL, NULL, 0);
zend_hash_init(&ctx.services, 0, NULL, NULL, 0);
load_wsdl_ex(this_ptr, struri,&ctx, 0);
load_wsdl_ex(this_ptr, struri, &ctx, 0);
zend_try {
schema_pass2(&ctx);
n = zend_hash_num_elements(&ctx.services);
@ -1166,6 +1168,12 @@ static sdlPtr load_wsdl(zval *this_ptr, char *struri)
soap_error0(E_ERROR, "Parsing WSDL: Could not find any usable binding services in WSDL.");
}
} zend_catch {
/* Avoid persistent memory leak. */
zend_hash_destroy(&ctx.docs);
zend_bailout();
} zend_end_try();
zend_hash_destroy(&ctx.messages);
zend_hash_destroy(&ctx.bindings);
zend_hash_destroy(&ctx.portTypes);

View file

@ -1643,7 +1643,15 @@ PHP_METHOD(SoapServer, handle)
old_features = SOAP_GLOBAL(features);
SOAP_GLOBAL(features) = service->features;
old_soap_version = SOAP_GLOBAL(soap_version);
zend_try {
function = deserialize_function_call(service->sdl, doc_request, service->actor, &function_name, &num_params, &params, &soap_version, &soap_headers);
} zend_catch {
/* Avoid leaking persistent memory */
xmlFreeDoc(doc_request);
zend_bailout();
} zend_end_try();
xmlFreeDoc(doc_request);
if (EG(exception)) {
@ -3821,6 +3829,8 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
encode_reset_ns();
doc = xmlNewDoc(BAD_CAST("1.0"));
zend_try {
doc->charset = XML_CHAR_ENCODING_UTF8;
doc->encoding = xmlCharStrdup("UTF-8");
@ -4162,6 +4172,12 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
encode_finish();
} zend_catch {
/* Avoid persistent memory leak. */
xmlFreeDoc(doc);
zend_bailout();
} zend_end_try();
if (function && function->responseName == NULL &&
body->children == NULL && head == NULL) {
xmlFreeDoc(doc);
@ -4183,6 +4199,8 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
encode_reset_ns();
doc = xmlNewDoc(BAD_CAST("1.0"));
zend_try {
doc->encoding = xmlCharStrdup("UTF-8");
doc->charset = XML_CHAR_ENCODING_UTF8;
if (version == SOAP_1_1) {
@ -4362,6 +4380,12 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
encode_finish();
} zend_catch {
/* Avoid persistent memory leak. */
xmlFreeDoc(doc);
zend_bailout();
} zend_end_try();
return doc;
}
/* }}} */