Use custom object instead of resource for soap server service

The "service" resource is a purely internal structure used by
SoapServer, which userland code cannot interact with. Instead of
storing it as a resource in an object propperty, use a custom
object structure instead.
This commit is contained in:
Nikita Popov 2021-11-28 18:37:29 +01:00
parent f0dd79a7e4
commit c5d6f59e96
3 changed files with 39 additions and 25 deletions

View file

@ -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 {

View file

@ -54,9 +54,6 @@ class SoapVar
class SoapServer
{
/** @var resource */
private $service;
private ?SoapFault $__soap_fault = null;
public function __construct(?string $wsdl, array $options = []) {}

View file

@ -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);