Prevent direct instantiation of com_safearray_proxy (GH-10278)

* Prevent direct instantiation of com_safearray_proxy

The `com_safearray_proxy` class is meant for internal usage, but so far
it was possible to instantiate it from userland, although that made no
sense.  However, a while ago there was a relevant change[1], namely
that its `default_object_handlers` are now assigned when the class is
registered, while previously they only have been assigned when an
instance had been created internally.  So now when freeing a manually
created object, `free_obj()` is called, although the object never has
been properly initialized (causing segfaults).

We fix this by introducing a `create_object()` handler which properly
initializes the object with dummy values.  Since a manually created
`com_safearray_proxy` still does not make sense, we disallow its
instantiation.

[1] <94ee4f9834>

Co-authored-by: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
This commit is contained in:
Christoph M. Becker 2024-10-07 11:35:59 +02:00 committed by GitHub
parent 1cc913bc69
commit 2f52dbd7b7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 28 additions and 2 deletions

View file

@ -182,6 +182,7 @@ PHP_MINIT_FUNCTION(com_dotnet)
php_com_saproxy_class_entry = register_class_com_safearray_proxy(); php_com_saproxy_class_entry = register_class_com_safearray_proxy();
/* php_com_saproxy_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; */ /* php_com_saproxy_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; */
php_com_saproxy_class_entry->create_object = php_com_saproxy_create_object;
php_com_saproxy_class_entry->default_object_handlers = &php_com_saproxy_handlers; php_com_saproxy_class_entry->default_object_handlers = &php_com_saproxy_handlers;
php_com_saproxy_class_entry->get_iterator = php_com_saproxy_iter_get; php_com_saproxy_class_entry->get_iterator = php_com_saproxy_iter_get;

View file

@ -57,6 +57,14 @@ typedef struct {
#define SA_FETCH(zv) (php_com_saproxy*)Z_OBJ_P(zv) #define SA_FETCH(zv) (php_com_saproxy*)Z_OBJ_P(zv)
zend_object *php_com_saproxy_create_object(zend_class_entry *class_type)
{
php_com_saproxy *intern = emalloc(sizeof(*intern));
memset(intern, 0, sizeof(*intern));
zend_object_std_init(&intern->std, class_type);
return &intern->std;
}
static inline void clone_indices(php_com_saproxy *dest, php_com_saproxy *src, int ndims) static inline void clone_indices(php_com_saproxy *dest, php_com_saproxy *src, int ndims)
{ {
int i; int i;
@ -317,7 +325,7 @@ static zend_function *saproxy_method_get(zend_object **object, zend_string *name
static zend_function *saproxy_constructor_get(zend_object *object) static zend_function *saproxy_constructor_get(zend_object *object)
{ {
/* user cannot instantiate */ zend_throw_error(NULL, "Cannot directly construct com_safeproxy_array; it is for internal usage only");
return NULL; return NULL;
} }
@ -365,7 +373,9 @@ static void saproxy_free_storage(zend_object *object)
//??? } //??? }
//??? } //??? }
if (proxy->obj != NULL) {
OBJ_RELEASE(&proxy->obj->zo); OBJ_RELEASE(&proxy->obj->zo);
}
zend_object_std_dtor(object); zend_object_std_dtor(object);

View file

@ -76,6 +76,7 @@ extern zend_object_handlers php_com_object_handlers;
void php_com_object_enable_event_sink(php_com_dotnet_object *obj, bool enable); void php_com_object_enable_event_sink(php_com_dotnet_object *obj, bool enable);
/* com_saproxy.c */ /* com_saproxy.c */
zend_object *php_com_saproxy_create_object(zend_class_entry *class_type);
zend_object_iterator *php_com_saproxy_iter_get(zend_class_entry *ce, zval *object, int by_ref); zend_object_iterator *php_com_saproxy_iter_get(zend_class_entry *ce, zval *object, int by_ref);
void php_com_saproxy_create(zend_object *com_object, zval *proxy_out, zval *index); void php_com_saproxy_create(zend_object *com_object, zval *proxy_out, zval *index);
extern zend_object_handlers php_com_saproxy_handlers; extern zend_object_handlers php_com_saproxy_handlers;

View file

@ -0,0 +1,14 @@
--TEST--
Manual instantiation of com_safearray_proxy is not allowed
--EXTENSIONS--
com_dotnet
--FILE--
<?php
try {
new com_safearray_proxy();
} catch (Error $e) {
echo $e->getMessage(), PHP_EOL;
}
?>
--EXPECT--
Cannot directly construct com_safeproxy_array; it is for internal usage only