diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 11a4984d02c..91f71e3fc12 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -30,7 +30,6 @@ static int le_sdl = 0; int le_url = 0; -static int le_service = 0; static int le_typemap = 0; typedef struct _soapHeader { @@ -150,8 +149,7 @@ static void soap_error_handler(int error_num, zend_string *error_filename, const #define Z_HEADER_MUST_UNDERSTAND_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 3)) #define Z_HEADER_ACTOR_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 4)) -#define Z_SERVER_SERVICE_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 0)) -#define Z_SERVER_SOAP_FAULT_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 1)) +#define Z_SERVER_SOAP_FAULT_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 0)) /* SoapFault extends Exception, so take those properties into account. */ #define FAULT_PROP_START_OFFSET zend_ce_exception->default_properties_count @@ -165,8 +163,7 @@ static void soap_error_handler(int error_num, zend_string *error_filename, const #define FETCH_THIS_SERVICE(ss) \ { \ - zval *tmp = Z_SERVER_SERVICE_P(ZEND_THIS); \ - ss = (soapServicePtr)zend_fetch_resource_ex(tmp, "service", le_service); \ + ss = soap_server_object_fetch(Z_OBJ_P(ZEND_THIS))->service; \ if (!ss) { \ zend_throw_error(NULL, "Cannot fetch SoapServer object"); \ SOAP_SERVER_END_CODE(); \ @@ -181,6 +178,34 @@ static zend_class_entry* soap_header_class_entry; static zend_class_entry* soap_param_class_entry; zend_class_entry* soap_var_class_entry; +static zend_object_handlers soap_server_object_handlers; + +typedef struct { + soapServicePtr service; + zend_object std; +} soap_server_object; + +static inline soap_server_object *soap_server_object_fetch(zend_object *obj) { + return (soap_server_object *) ((char *) obj - XtOffsetOf(soap_server_object, std)); +} + +static zend_object *soap_server_object_create(zend_class_entry *ce) +{ + soap_server_object *obj = zend_object_alloc(sizeof(soap_server_object), ce); + zend_object_std_init(&obj->std, ce); + object_properties_init(&obj->std, ce); + obj->std.handlers = &soap_server_object_handlers; + return &obj->std; +} + +static void soap_server_object_free(zend_object *obj) { + soap_server_object *server_obj = soap_server_object_fetch(obj); + if (server_obj->service) { + delete_service(server_obj->service); + } + zend_object_std_dtor(obj); +} + ZEND_DECLARE_MODULE_GLOBALS(soap) static void (*old_error_handler)(int, zend_string *, const uint32_t, zend_string *); @@ -361,11 +386,6 @@ static void delete_url_res(zend_resource *res) delete_url(res->ptr); } -static void delete_service_res(zend_resource *res) -{ - delete_service(res->ptr); -} - static void delete_hashtable_res(zend_resource *res) { delete_hashtable(res->ptr); @@ -386,6 +406,11 @@ PHP_MINIT_FUNCTION(soap) /* Register SoapServer class */ soap_server_class_entry = register_class_SoapServer(); + soap_server_class_entry->create_object = soap_server_object_create; + + memcpy(&soap_server_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + soap_server_object_handlers.offset = XtOffsetOf(soap_server_object, std); + soap_server_object_handlers.free_obj = soap_server_object_free; /* Register SoapFault class */ soap_fault_class_entry = register_class_SoapFault(zend_ce_exception); @@ -397,7 +422,6 @@ PHP_MINIT_FUNCTION(soap) le_sdl = zend_register_list_destructors_ex(delete_sdl_res, NULL, "SOAP SDL", module_number); le_url = zend_register_list_destructors_ex(delete_url_res, NULL, "SOAP URL", module_number); - le_service = zend_register_list_destructors_ex(delete_service_res, NULL, "SOAP service", module_number); le_typemap = zend_register_list_destructors_ex(delete_hashtable_res, NULL, "SOAP table", module_number); REGISTER_LONG_CONSTANT("SOAP_1_1", SOAP_1_1, CONST_CS | CONST_PERSISTENT); @@ -832,7 +856,6 @@ PHP_METHOD(SoapServer, __construct) soapServicePtr service; zval *options = NULL; zend_string *wsdl; - zend_resource *res; int version = SOAP_1_1; zend_long cache_wsdl; HashTable *typemap_ht = NULL; @@ -942,8 +965,8 @@ PHP_METHOD(SoapServer, __construct) service->typemap = soap_create_typemap(service->sdl, typemap_ht); } - res = zend_register_resource(service, le_service); - ZVAL_RES(Z_SERVER_SERVICE_P(ZEND_THIS), res); + soap_server_object *server_obj = soap_server_object_fetch(Z_OBJ_P(ZEND_THIS)); + server_obj->service = service; SOAP_SERVER_END_CODE(); } @@ -1824,7 +1847,7 @@ static zend_never_inline ZEND_COLD void soap_real_error_handler(int error_num, z } if (Z_OBJ_P(error_object) && instanceof_function(Z_OBJCE_P(error_object), soap_server_class_entry) && - (service = (soapServicePtr)zend_fetch_resource_ex(Z_SERVER_SERVICE_P(error_object), "service", le_service)) && + (service = soap_server_object_fetch(Z_OBJ_P(error_object))->service) && !service->send_errors) { buffer = zend_string_init("Internal Error", sizeof("Internal Error")-1, 0); } else { diff --git a/ext/soap/soap.stub.php b/ext/soap/soap.stub.php index 52613178d8d..d21b715cd75 100644 --- a/ext/soap/soap.stub.php +++ b/ext/soap/soap.stub.php @@ -54,9 +54,6 @@ class SoapVar class SoapServer { - /** @var resource */ - private $service; - private ?SoapFault $__soap_fault = null; public function __construct(?string $wsdl, array $options = []) {} diff --git a/ext/soap/soap_arginfo.h b/ext/soap/soap_arginfo.h index b6bd7f7e355..3cf1c19ada2 100644 --- a/ext/soap/soap_arginfo.h +++ b/ext/soap/soap_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: ab057422ee42f574e7d00462f3bf173caf14ecc1 */ + * Stub hash: 96c82014f1fe922cee14d0cd55dd14a6ba3ffe5f */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_use_soap_error_handler, 0, 0, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, enable, _IS_BOOL, 0, "true") @@ -400,12 +400,6 @@ static zend_class_entry *register_class_SoapServer(void) INIT_CLASS_ENTRY(ce, "SoapServer", class_SoapServer_methods); class_entry = zend_register_internal_class_ex(&ce, NULL); - zval property_service_default_value; - ZVAL_NULL(&property_service_default_value); - zend_string *property_service_name = zend_string_init("service", sizeof("service") - 1, 1); - zend_declare_property_ex(class_entry, property_service_name, &property_service_default_value, ZEND_ACC_PRIVATE, NULL); - zend_string_release(property_service_name); - zend_string *property___soap_fault_class_SoapFault = zend_string_init("SoapFault", sizeof("SoapFault")-1, 1); zval property___soap_fault_default_value; ZVAL_NULL(&property___soap_fault_default_value);