Skip to content

Commit a955ed1

Browse files
committed
ext/soap: call userland functions directly
1 parent a01ff38 commit a955ed1

File tree

1 file changed

+68
-59
lines changed

1 file changed

+68
-59
lines changed

ext/soap/soap.c

Lines changed: 68 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,12 +1274,11 @@ PHP_METHOD(SoapServer, handle)
12741274
sdlPtr old_sdl = NULL;
12751275
soapServicePtr service;
12761276
xmlDocPtr doc_request = NULL, doc_return = NULL;
1277-
zval function_name, *params, *soap_obj, retval;
1277+
zval function_name, *params, retval;
12781278
char cont_len[30];
12791279
uint32_t num_params = 0;
1280-
int size, i, call_status = 0;
1280+
int size, i;
12811281
xmlChar *buf;
1282-
HashTable *function_table;
12831282
soapHeader *soap_headers = NULL;
12841283
sdlFunctionPtr function;
12851284
char *arg = NULL;
@@ -1454,10 +1453,15 @@ PHP_METHOD(SoapServer, handle)
14541453

14551454
service->soap_headers_ptr = &soap_headers;
14561455

1457-
soap_obj = NULL;
1456+
zval *soap_obj = NULL;
1457+
zend_object *soap_zobj = NULL;
1458+
zend_class_entry *soap_obj_ce = NULL;
1459+
HashTable *function_table;
14581460
if (service->type == SOAP_OBJECT) {
14591461
soap_obj = &service->soap_object;
1460-
function_table = &((Z_OBJCE_P(soap_obj))->function_table);
1462+
soap_zobj = Z_OBJ_P(soap_obj);
1463+
soap_obj_ce = Z_OBJCE_P(soap_obj);
1464+
function_table = &soap_obj_ce->function_table;
14611465
} else if (service->type == SOAP_CLASS) {
14621466
/* If persistent then set soap_obj from the previous created session (if available) */
14631467
#ifdef SOAP_HAS_SESSION_SUPPORT
@@ -1515,7 +1519,9 @@ PHP_METHOD(SoapServer, handle)
15151519
soap_obj = &tmp_soap;
15161520
}
15171521
}
1518-
function_table = &((Z_OBJCE_P(soap_obj))->function_table);
1522+
soap_zobj = Z_OBJ_P(soap_obj);
1523+
soap_obj_ce = Z_OBJCE_P(soap_obj);
1524+
function_table = &soap_obj_ce->function_table;
15191525
} else {
15201526
if (service->soap_functions.functions_all) {
15211527
function_table = EG(function_table);
@@ -1540,44 +1546,52 @@ PHP_METHOD(SoapServer, handle)
15401546
}
15411547
}
15421548
#endif
1543-
if (zend_hash_find_ptr_lc(function_table, Z_STR(h->function_name)) != NULL ||
1544-
((service->type == SOAP_CLASS || service->type == SOAP_OBJECT) &&
1545-
zend_hash_str_exists(function_table, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
1546-
call_status = call_user_function(NULL, soap_obj, &h->function_name, &h->retval, h->num_params, h->parameters);
1547-
if (call_status != SUCCESS) {
1548-
php_error_docref(NULL, E_WARNING, "Function '%s' call failed", Z_STRVAL(h->function_name));
1549-
return;
1549+
zend_function *header_fn = zend_hash_find_ptr_lc(function_table, Z_STR(h->function_name));
1550+
if (UNEXPECTED(header_fn == NULL)) {
1551+
if (soap_obj_ce && soap_obj_ce->__call) {
1552+
header_fn = zend_get_call_trampoline_func(soap_obj_ce, Z_STR(function_name), false);
1553+
goto soap_header_func_call;
15501554
}
1551-
if (Z_TYPE(h->retval) == IS_OBJECT &&
1552-
instanceof_function(Z_OBJCE(h->retval), soap_fault_class_entry)) {
1553-
php_output_discard();
1554-
soap_server_fault_ex(function, &h->retval, h);
1555-
if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);}
1556-
goto fail;
1557-
} else if (EG(exception)) {
1558-
php_output_discard();
1559-
_soap_server_exception(service, function, ZEND_THIS);
1560-
if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);}
1555+
if (h->mustUnderstand) {
1556+
soap_server_fault_en("MustUnderstand","Header not understood", NULL, NULL, NULL);
15611557
goto fail;
15621558
}
1563-
} else if (h->mustUnderstand) {
1564-
soap_server_fault_en("MustUnderstand","Header not understood", NULL, NULL, NULL);
1559+
continue;
1560+
}
1561+
1562+
soap_header_func_call:
1563+
zend_call_known_function(header_fn, soap_zobj, soap_obj_ce, &h->retval, h->num_params, h->parameters, NULL);
1564+
if (Z_TYPE(h->retval) == IS_OBJECT &&
1565+
instanceof_function(Z_OBJCE(h->retval), soap_fault_class_entry)) {
1566+
php_output_discard();
1567+
soap_server_fault_ex(function, &h->retval, h);
1568+
if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);}
1569+
goto fail;
1570+
} else if (EG(exception)) {
1571+
php_output_discard();
1572+
_soap_server_exception(service, function, ZEND_THIS);
1573+
if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);}
1574+
goto fail;
15651575
}
15661576
}
15671577
}
15681578

1569-
if (zend_hash_find_ptr_lc(function_table, Z_STR(function_name)) != NULL ||
1570-
((service->type == SOAP_CLASS || service->type == SOAP_OBJECT) &&
1571-
zend_hash_str_exists(function_table, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
1572-
call_status = call_user_function(NULL, soap_obj, &function_name, &retval, num_params, params);
1573-
if (service->type == SOAP_CLASS) {
1574-
if (service->soap_class.persistence != SOAP_PERSISTENCE_SESSION) {
1575-
zval_ptr_dtor(soap_obj);
1576-
soap_obj = NULL;
1577-
}
1579+
zend_function *fn = zend_hash_find_ptr_lc(function_table, Z_STR(function_name));
1580+
if (UNEXPECTED(fn == NULL)) {
1581+
if (soap_obj_ce && soap_obj_ce->__call) {
1582+
fn = zend_get_call_trampoline_func(soap_obj_ce, Z_STR(function_name), false);
1583+
} else {
1584+
php_error(E_ERROR, "Function '%s' doesn't exist", Z_STRVAL(function_name));
1585+
goto fail;
1586+
}
1587+
}
1588+
zend_call_known_function(fn, soap_zobj, soap_obj_ce, &retval, num_params, params, NULL);
1589+
1590+
if (service->type == SOAP_CLASS) {
1591+
if (service->soap_class.persistence != SOAP_PERSISTENCE_SESSION) {
1592+
zval_ptr_dtor(soap_obj);
1593+
soap_obj = NULL;
15781594
}
1579-
} else {
1580-
php_error(E_ERROR, "Function '%s' doesn't exist", Z_STRVAL(function_name));
15811595
}
15821596

15831597
if (EG(exception)) {
@@ -1593,32 +1607,27 @@ PHP_METHOD(SoapServer, handle)
15931607
goto fail;
15941608
}
15951609

1596-
if (call_status == SUCCESS) {
1597-
char *response_name;
1598-
1599-
if (Z_TYPE(retval) == IS_OBJECT &&
1600-
instanceof_function(Z_OBJCE(retval), soap_fault_class_entry)) {
1601-
php_output_discard();
1602-
soap_server_fault_ex(function, &retval, NULL);
1603-
goto fail;
1604-
}
1610+
char *response_name;
16051611

1606-
bool has_response_name = function && function->responseName;
1607-
if (has_response_name) {
1608-
response_name = function->responseName;
1609-
} else {
1610-
response_name = emalloc(Z_STRLEN(function_name) + sizeof("Response"));
1611-
memcpy(response_name,Z_STRVAL(function_name),Z_STRLEN(function_name));
1612-
memcpy(response_name+Z_STRLEN(function_name),"Response",sizeof("Response"));
1613-
}
1614-
doc_return = serialize_response_call(function, response_name, service->uri, &retval, soap_headers, soap_version);
1612+
if (Z_TYPE(retval) == IS_OBJECT &&
1613+
instanceof_function(Z_OBJCE(retval), soap_fault_class_entry)) {
1614+
php_output_discard();
1615+
soap_server_fault_ex(function, &retval, NULL);
1616+
goto fail;
1617+
}
16151618

1616-
if (!has_response_name) {
1617-
efree(response_name);
1618-
}
1619+
bool has_response_name = function && function->responseName;
1620+
if (has_response_name) {
1621+
response_name = function->responseName;
16191622
} else {
1620-
php_error_docref(NULL, E_WARNING, "Function '%s' call failed", Z_STRVAL(function_name));
1621-
return;
1623+
response_name = emalloc(Z_STRLEN(function_name) + sizeof("Response"));
1624+
memcpy(response_name,Z_STRVAL(function_name),Z_STRLEN(function_name));
1625+
memcpy(response_name+Z_STRLEN(function_name),"Response",sizeof("Response"));
1626+
}
1627+
doc_return = serialize_response_call(function, response_name, service->uri, &retval, soap_headers, soap_version);
1628+
1629+
if (!has_response_name) {
1630+
efree(response_name);
16221631
}
16231632

16241633
if (EG(exception)) {

0 commit comments

Comments
 (0)