Skip to content

Commit a61204b

Browse files
committed
Experiment with moving away from bailout in soap
1 parent 7bf5b7f commit a61204b

File tree

1 file changed

+47
-22
lines changed

1 file changed

+47
-22
lines changed

ext/soap/soap.c

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ static void type_to_string(sdlTypePtr type, smart_str *buf, int level);
5151
static void clear_soap_fault(zval *obj);
5252
static void set_soap_fault(zval *obj, const char *fault_code_ns, const char *fault_code, const char *fault_string, const char *fault_actor, zval *fault_detail, zend_string *name);
5353
static void add_soap_fault_ex(zval *fault, zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail);
54-
static ZEND_NORETURN void soap_server_fault(char* code, char* string, char *actor, zval* details, zend_string *name);
54+
static void soap_server_fault(char* code, char* string, char *actor, zval* details, zend_string *name);
5555
static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeader* hdr);
5656

5757
static sdlParamPtr get_param(sdlFunctionPtr function, const char *param_name, zend_ulong index, int);
@@ -1273,6 +1273,7 @@ PHP_METHOD(SoapServer, handle)
12731273
HashTable *old_class_map, *old_typemap;
12741274
int old_features;
12751275
zval tmp_soap;
1276+
bool free_tmp_soap = false;
12761277

12771278
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!", &arg, &arg_len) == FAILURE) {
12781279
RETURN_THROWS();
@@ -1393,8 +1394,8 @@ PHP_METHOD(SoapServer, handle)
13931394

13941395
if (doc_request == NULL) {
13951396
soap_server_fault("Client", "Bad Request", NULL, NULL, NULL);
1396-
}
1397-
if (xmlGetIntSubset(doc_request) != NULL) {
1397+
goto fail;
1398+
} else if (xmlGetIntSubset(doc_request) != NULL) {
13981399
xmlNodePtr env = get_node(doc_request->children,"Envelope");
13991400
if (env && env->ns) {
14001401
if (strcmp((char*)env->ns->href, SOAP_1_1_ENV_NAMESPACE) == 0) {
@@ -1405,6 +1406,7 @@ PHP_METHOD(SoapServer, handle)
14051406
}
14061407
xmlFreeDoc(doc_request);
14071408
soap_server_fault("Server", "DTD are not supported by SOAP", NULL, NULL, NULL);
1409+
goto fail;
14081410
}
14091411

14101412
old_sdl = SOAP_GLOBAL(sdl);
@@ -1461,6 +1463,7 @@ PHP_METHOD(SoapServer, handle)
14611463
} else if (Z_OBJCE_P(tmp_soap_p) == php_ce_incomplete_class) {
14621464
/* See #51561, communicate limitation to user */
14631465
soap_server_fault("Server", "SoapServer class was deserialized from the session prior to loading the class passed to SoapServer::setClass(). Start the session after loading all classes to resolve this issue.", NULL, NULL, NULL);
1466+
goto fail;
14641467
}
14651468
}
14661469
}
@@ -1478,7 +1481,6 @@ PHP_METHOD(SoapServer, handle)
14781481
if (EG(exception)) {
14791482
php_output_discard();
14801483
_soap_server_exception(service, function, ZEND_THIS);
1481-
zval_ptr_dtor(&tmp_soap);
14821484
goto fail;
14831485
}
14841486
}
@@ -1492,12 +1494,14 @@ PHP_METHOD(SoapServer, handle)
14921494
soap_obj = tmp_soap_p;
14931495
} else {
14941496
soap_obj = &tmp_soap;
1497+
free_tmp_soap = true;
14951498
}
14961499
zend_string_release_ex(session_var_name, false);
14971500
} else
14981501
#endif
14991502
{
15001503
soap_obj = &tmp_soap;
1504+
free_tmp_soap = true;
15011505
}
15021506
}
15031507
function_table = &((Z_OBJCE_P(soap_obj))->function_table);
@@ -1520,6 +1524,7 @@ PHP_METHOD(SoapServer, handle)
15201524
if (service->sdl && !h->function && !h->hdr) {
15211525
if (h->mustUnderstand) {
15221526
soap_server_fault("MustUnderstand","Header not understood", NULL, NULL, NULL);
1527+
abort();
15231528
} else {
15241529
continue;
15251530
}
@@ -1541,16 +1546,17 @@ PHP_METHOD(SoapServer, handle)
15411546
instanceof_function(Z_OBJCE(h->retval), soap_fault_class_entry)) {
15421547
php_output_discard();
15431548
soap_server_fault_ex(function, &h->retval, h);
1544-
if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);}
1549+
if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj); free_tmp_soap = false; }
15451550
goto fail;
15461551
} else if (EG(exception)) {
15471552
php_output_discard();
15481553
_soap_server_exception(service, function, ZEND_THIS);
1549-
if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);}
1554+
if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj); free_tmp_soap = false; }
15501555
goto fail;
15511556
}
15521557
} else if (h->mustUnderstand) {
15531558
soap_server_fault("MustUnderstand","Header not understood", NULL, NULL, NULL);
1559+
goto fail;
15541560
}
15551561
}
15561562
}
@@ -1563,7 +1569,7 @@ PHP_METHOD(SoapServer, handle)
15631569
if (service->type == SOAP_CLASS) {
15641570
if (service->soap_class.persistence != SOAP_PERSISTENCE_SESSION) {
15651571
zval_ptr_dtor(soap_obj);
1566-
soap_obj = NULL;
1572+
free_tmp_soap = false;
15671573
}
15681574
}
15691575
} else {
@@ -1577,11 +1583,6 @@ PHP_METHOD(SoapServer, handle)
15771583
if (!zend_is_unwind_exit(EG(exception))) {
15781584
php_output_discard();
15791585
_soap_server_exception(service, function, ZEND_THIS);
1580-
if (service->type == SOAP_CLASS) {
1581-
if (soap_obj && service->soap_class.persistence != SOAP_PERSISTENCE_SESSION) {
1582-
zval_ptr_dtor(soap_obj);
1583-
}
1584-
}
15851586
}
15861587
goto fail;
15871588
}
@@ -1617,11 +1618,6 @@ PHP_METHOD(SoapServer, handle)
16171618
if (EG(exception)) {
16181619
php_output_discard();
16191620
_soap_server_exception(service, function, ZEND_THIS);
1620-
if (service->type == SOAP_CLASS) {
1621-
if (soap_obj && service->soap_class.persistence != SOAP_PERSISTENCE_SESSION) {
1622-
zval_ptr_dtor(soap_obj);
1623-
}
1624-
}
16251621
goto fail;
16261622
}
16271623

@@ -1662,6 +1658,10 @@ PHP_METHOD(SoapServer, handle)
16621658
}
16631659

16641660
fail:
1661+
if (free_tmp_soap) { // TODO ???
1662+
zval_ptr_dtor(&tmp_soap);
1663+
}
1664+
16651665
SOAP_GLOBAL(soap_version) = old_soap_version;
16661666
SOAP_GLOBAL(encoding) = old_encoding;
16671667
SOAP_GLOBAL(sdl) = old_sdl;
@@ -1786,6 +1786,7 @@ static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeade
17861786
soap_version = SOAP_GLOBAL(soap_version);
17871787

17881788
doc_return = serialize_response_call(function, NULL, NULL, fault, hdr, soap_version);
1789+
// TODO: doc_return can be NULL!
17891790

17901791
xmlDocDumpMemory(doc_return, &buf, &size);
17911792

@@ -1823,15 +1824,16 @@ static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeade
18231824
}
18241825
/* }}} */
18251826

1826-
static ZEND_NORETURN void soap_server_fault(char* code, char* string, char *actor, zval* details, zend_string* name) /* {{{ */
1827+
static void soap_server_fault(char* code, char* string, char *actor, zval* details, zend_string* name) /* {{{ */
18271828
{
18281829
zval ret;
18291830

18301831
ZVAL_NULL(&ret);
18311832
set_soap_fault(&ret, NULL, code, string, actor, details, name);
18321833
/* TODO: Which function */
18331834
soap_server_fault_ex(NULL, &ret, NULL);
1834-
zend_bailout();
1835+
zval_ptr_dtor(&ret); // TODO ??
1836+
zend_throw_unwind_exit();
18351837
}
18361838
/* }}} */
18371839

@@ -3108,10 +3110,12 @@ static xmlNodePtr get_envelope(xmlNodePtr trav, int *version, char **envelope_ns
31083110
}
31093111

31103112
soap_server_fault("VersionMismatch", "Wrong Version", NULL, NULL, NULL);
3113+
return NULL;
31113114
}
31123115
trav = trav->next;
31133116
}
31143117

3118+
soap_server_fault("Client", "looks like we got XML without \"Envelope\" element", NULL, NULL, NULL);
31153119
return NULL;
31163120
}
31173121

@@ -3127,18 +3131,21 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c
31273131
/* Get <Envelope> element */
31283132
env = get_envelope(request->children, version, &envelope_ns);
31293133
if (!env) {
3130-
soap_server_fault("Client", "looks like we got XML without \"Envelope\" element", NULL, NULL, NULL);
3134+
return NULL;
31313135
}
31323136

31333137
attr = env->properties;
31343138
while (attr != NULL) {
31353139
if (attr->ns == NULL) {
31363140
soap_server_fault("Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL, NULL);
3141+
return NULL;
31373142
} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
31383143
if (*version == SOAP_1_2) {
31393144
soap_server_fault("Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL, NULL);
3145+
return NULL;
31403146
} else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
31413147
soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL);
3148+
return NULL;
31423149
}
31433150
}
31443151
attr = attr->next;
@@ -3169,25 +3176,30 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c
31693176
}
31703177
if (body == NULL) {
31713178
soap_server_fault("Client", "Body must be present in a SOAP envelope", NULL, NULL, NULL);
3179+
return NULL;
31723180
}
31733181
attr = body->properties;
31743182
while (attr != NULL) {
31753183
if (attr->ns == NULL) {
31763184
if (*version == SOAP_1_2) {
31773185
soap_server_fault("Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL, NULL);
3186+
return NULL;
31783187
}
31793188
} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
31803189
if (*version == SOAP_1_2) {
31813190
soap_server_fault("Client", "encodingStyle cannot be specified on the Body", NULL, NULL, NULL);
3191+
return NULL;
31823192
} else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
31833193
soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL);
3194+
return NULL;
31843195
}
31853196
}
31863197
attr = attr->next;
31873198
}
31883199

31893200
if (trav != NULL && *version == SOAP_1_2) {
31903201
soap_server_fault("Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL, NULL);
3202+
return NULL;
31913203
}
31923204

31933205
func = NULL;
@@ -3210,23 +3222,27 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c
32103222
ZVAL_STRING(function_name, (char *)function->functionName);
32113223
} else {
32123224
soap_server_fault("Client", "looks like we got \"Body\" without function call", NULL, NULL, NULL);
3225+
return NULL;
32133226
}
32143227
} else {
32153228
if (*version == SOAP_1_1) {
32163229
attr = get_attribute_ex(func->properties,"encodingStyle",SOAP_1_1_ENV_NAMESPACE);
32173230
if (attr && strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
32183231
soap_server_fault("Client","Unknown Data Encoding Style", NULL, NULL, NULL);
3232+
return NULL;
32193233
}
32203234
} else {
32213235
attr = get_attribute_ex(func->properties,"encodingStyle",SOAP_1_2_ENV_NAMESPACE);
32223236
if (attr && strcmp((char*)attr->children->content,SOAP_1_2_ENC_NAMESPACE) != 0) {
32233237
soap_server_fault("DataEncodingUnknown","Unknown Data Encoding Style", NULL, NULL, NULL);
3238+
return NULL;
32243239
}
32253240
}
32263241
function = find_function(sdl, func, function_name);
32273242
if (sdl != NULL && function == NULL) {
32283243
if (*version == SOAP_1_2) {
32293244
soap_server_fault("rpc:ProcedureNotPresent","Procedure not present", NULL, NULL, NULL);
3245+
return NULL;
32303246
} else {
32313247
php_error(E_ERROR, "Procedure '%s' not present", func->name);
32323248
}
@@ -3241,11 +3257,14 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c
32413257
while (attr != NULL) {
32423258
if (attr->ns == NULL) {
32433259
soap_server_fault("Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL, NULL);
3260+
return NULL;
32443261
} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
32453262
if (*version == SOAP_1_2) {
32463263
soap_server_fault("Client", "encodingStyle cannot be specified on the Header", NULL, NULL, NULL);
3264+
return NULL;
32473265
} else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
32483266
soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL);
3267+
return NULL;
32493268
}
32503269
}
32513270
attr = attr->next;
@@ -3260,6 +3279,7 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c
32603279
attr = get_attribute_ex(hdr_func->properties,"encodingStyle",SOAP_1_1_ENV_NAMESPACE);
32613280
if (attr && strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
32623281
soap_server_fault("Client","Unknown Data Encoding Style", NULL, NULL, NULL);
3282+
return NULL;
32633283
}
32643284
attr = get_attribute_ex(hdr_func->properties,"actor",envelope_ns);
32653285
if (attr != NULL) {
@@ -3272,6 +3292,7 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c
32723292
attr = get_attribute_ex(hdr_func->properties,"encodingStyle",SOAP_1_2_ENV_NAMESPACE);
32733293
if (attr && strcmp((char*)attr->children->content,SOAP_1_2_ENC_NAMESPACE) != 0) {
32743294
soap_server_fault("DataEncodingUnknown","Unknown Data Encoding Style", NULL, NULL, NULL);
3295+
return NULL;
32753296
}
32763297
attr = get_attribute_ex(hdr_func->properties,"role",envelope_ns);
32773298
if (attr != NULL) {
@@ -3292,6 +3313,7 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c
32923313
mustUnderstand = 0;
32933314
} else {
32943315
soap_server_fault("Client","mustUnderstand value is not boolean", NULL, NULL, NULL);
3316+
return NULL;
32953317
}
32963318
}
32973319
h = emalloc(sizeof(soapHeader));
@@ -3506,8 +3528,6 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, const char *fu
35063528
encode_reset_ns();
35073529

35083530
doc = xmlNewDoc(BAD_CAST("1.0"));
3509-
zend_try {
3510-
35113531
doc->charset = XML_CHAR_ENCODING_UTF8;
35123532
doc->encoding = xmlCharStrdup("UTF-8");
35133533

@@ -3520,10 +3540,15 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, const char *fu
35203540
ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENV_NAMESPACE), BAD_CAST(SOAP_1_2_ENV_NS_PREFIX));
35213541
xmlSetNs(envelope,ns);
35223542
} else {
3543+
xmlFreeDoc(doc);
35233544
soap_server_fault("Server", "Unknown SOAP version", NULL, NULL, NULL);
3545+
return NULL;
35243546
}
3547+
35253548
xmlDocSetRootElement(doc, envelope);
35263549

3550+
zend_try {
3551+
35273552
if (Z_TYPE_P(ret) == IS_OBJECT &&
35283553
instanceof_function(Z_OBJCE_P(ret), soap_fault_class_entry)) {
35293554
char *detail_name;

0 commit comments

Comments
 (0)