Skip to content

Commit 78375aa

Browse files
committed
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.
1 parent cfeda97 commit 78375aa

File tree

3 files changed

+46
-8
lines changed

3 files changed

+46
-8
lines changed

ext/soap/php_encoding.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1519,7 +1519,13 @@ static zval *to_zval_object_ex(zval *ret, encodeTypePtr type, xmlNodePtr data, z
15191519
text = xmlNewText(BAD_CAST(str_val));
15201520
xmlAddChild(dummy, text);
15211521
ZVAL_NULL(&data);
1522-
master_to_zval(&data, attr->encode, dummy);
1522+
/* TODO: There are other places using dummy nodes -- generalize? */
1523+
zend_try {
1524+
master_to_zval(&data, attr->encode, dummy);
1525+
} zend_catch {
1526+
xmlFreeNode(dummy);
1527+
zend_bailout();
1528+
} zend_end_try();
15231529
xmlFreeNode(dummy);
15241530
set_zval_property(ret, attr->name, &data);
15251531
}

ext/soap/php_sdl.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,9 @@ static sdlPtr load_wsdl(zval *this_ptr, char *struri)
739739
zend_hash_init(&ctx.portTypes, 0, NULL, NULL, 0);
740740
zend_hash_init(&ctx.services, 0, NULL, NULL, 0);
741741

742-
load_wsdl_ex(this_ptr, struri,&ctx, 0);
742+
load_wsdl_ex(this_ptr, struri, &ctx, 0);
743+
zend_try {
744+
743745
schema_pass2(&ctx);
744746

745747
n = zend_hash_num_elements(&ctx.services);
@@ -1166,6 +1168,12 @@ static sdlPtr load_wsdl(zval *this_ptr, char *struri)
11661168
soap_error0(E_ERROR, "Parsing WSDL: Could not find any usable binding services in WSDL.");
11671169
}
11681170

1171+
} zend_catch {
1172+
/* Avoid persistent memory leak. */
1173+
zend_hash_destroy(&ctx.docs);
1174+
zend_bailout();
1175+
} zend_end_try();
1176+
11691177
zend_hash_destroy(&ctx.messages);
11701178
zend_hash_destroy(&ctx.bindings);
11711179
zend_hash_destroy(&ctx.portTypes);

ext/soap/soap.c

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,7 +1643,15 @@ PHP_METHOD(SoapServer, handle)
16431643
old_features = SOAP_GLOBAL(features);
16441644
SOAP_GLOBAL(features) = service->features;
16451645
old_soap_version = SOAP_GLOBAL(soap_version);
1646-
function = deserialize_function_call(service->sdl, doc_request, service->actor, &function_name, &num_params, &params, &soap_version, &soap_headers);
1646+
1647+
zend_try {
1648+
function = deserialize_function_call(service->sdl, doc_request, service->actor, &function_name, &num_params, &params, &soap_version, &soap_headers);
1649+
} zend_catch {
1650+
/* Avoid leaking persistent memory */
1651+
xmlFreeDoc(doc_request);
1652+
zend_bailout();
1653+
} zend_end_try();
1654+
16471655
xmlFreeDoc(doc_request);
16481656

16491657
if (EG(exception)) {
@@ -3821,6 +3829,8 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
38213829
encode_reset_ns();
38223830

38233831
doc = xmlNewDoc(BAD_CAST("1.0"));
3832+
zend_try {
3833+
38243834
doc->charset = XML_CHAR_ENCODING_UTF8;
38253835
doc->encoding = xmlCharStrdup("UTF-8");
38263836

@@ -4162,6 +4172,12 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
41624172

41634173
encode_finish();
41644174

4175+
} zend_catch {
4176+
/* Avoid persistent memory leak. */
4177+
xmlFreeDoc(doc);
4178+
zend_bailout();
4179+
} zend_end_try();
4180+
41654181
if (function && function->responseName == NULL &&
41664182
body->children == NULL && head == NULL) {
41674183
xmlFreeDoc(doc);
@@ -4183,6 +4199,8 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
41834199
encode_reset_ns();
41844200

41854201
doc = xmlNewDoc(BAD_CAST("1.0"));
4202+
zend_try {
4203+
41864204
doc->encoding = xmlCharStrdup("UTF-8");
41874205
doc->charset = XML_CHAR_ENCODING_UTF8;
41884206
if (version == SOAP_1_1) {
@@ -4222,7 +4240,7 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
42224240
}
42234241
} else {
42244242
if ((zstyle = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "style", sizeof("style")-1)) != NULL &&
4225-
Z_TYPE_P(zstyle) == IS_LONG) {
4243+
Z_TYPE_P(zstyle) == IS_LONG) {
42264244
style = Z_LVAL_P(zstyle);
42274245
} else {
42284246
style = SOAP_RPC;
@@ -4245,7 +4263,7 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
42454263
}
42464264

42474265
if ((zuse = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "use", sizeof("use")-1)) != NULL &&
4248-
Z_TYPE_P(zuse) == IS_LONG && Z_LVAL_P(zuse) == SOAP_LITERAL) {
4266+
Z_TYPE_P(zuse) == IS_LONG && Z_LVAL_P(zuse) == SOAP_LITERAL) {
42494267
use = SOAP_LITERAL;
42504268
} else {
42514269
use = SOAP_ENCODED;
@@ -4307,9 +4325,9 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
43074325

43084326
ht = Z_OBJPROP_P(header);
43094327
if ((name = zend_hash_str_find(ht, "name", sizeof("name")-1)) != NULL &&
4310-
Z_TYPE_P(name) == IS_STRING &&
4311-
(ns = zend_hash_str_find(ht, "namespace", sizeof("namespace")-1)) != NULL &&
4312-
Z_TYPE_P(ns) == IS_STRING) {
4328+
Z_TYPE_P(name) == IS_STRING &&
4329+
(ns = zend_hash_str_find(ht, "namespace", sizeof("namespace")-1)) != NULL &&
4330+
Z_TYPE_P(ns) == IS_STRING) {
43134331
xmlNodePtr h;
43144332
xmlNsPtr nsptr;
43154333
int hdr_use = SOAP_LITERAL;
@@ -4362,6 +4380,12 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
43624380

43634381
encode_finish();
43644382

4383+
} zend_catch {
4384+
/* Avoid persistent memory leak. */
4385+
xmlFreeDoc(doc);
4386+
zend_bailout();
4387+
} zend_end_try();
4388+
43654389
return doc;
43664390
}
43674391
/* }}} */

0 commit comments

Comments
 (0)