Skip to content

Commit 2f52dbd

Browse files
cmb69nielsdos
andauthored
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] <94ee4f9> Co-authored-by: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
1 parent 1cc913b commit 2f52dbd

File tree

4 files changed

+28
-2
lines changed

4 files changed

+28
-2
lines changed

ext/com_dotnet/com_extension.c

+1
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ PHP_MINIT_FUNCTION(com_dotnet)
182182

183183
php_com_saproxy_class_entry = register_class_com_safearray_proxy();
184184
/* php_com_saproxy_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; */
185+
php_com_saproxy_class_entry->create_object = php_com_saproxy_create_object;
185186
php_com_saproxy_class_entry->default_object_handlers = &php_com_saproxy_handlers;
186187
php_com_saproxy_class_entry->get_iterator = php_com_saproxy_iter_get;
187188

ext/com_dotnet/com_saproxy.c

+12-2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ typedef struct {
5757

5858
#define SA_FETCH(zv) (php_com_saproxy*)Z_OBJ_P(zv)
5959

60+
zend_object *php_com_saproxy_create_object(zend_class_entry *class_type)
61+
{
62+
php_com_saproxy *intern = emalloc(sizeof(*intern));
63+
memset(intern, 0, sizeof(*intern));
64+
zend_object_std_init(&intern->std, class_type);
65+
return &intern->std;
66+
}
67+
6068
static inline void clone_indices(php_com_saproxy *dest, php_com_saproxy *src, int ndims)
6169
{
6270
int i;
@@ -317,7 +325,7 @@ static zend_function *saproxy_method_get(zend_object **object, zend_string *name
317325

318326
static zend_function *saproxy_constructor_get(zend_object *object)
319327
{
320-
/* user cannot instantiate */
328+
zend_throw_error(NULL, "Cannot directly construct com_safeproxy_array; it is for internal usage only");
321329
return NULL;
322330
}
323331

@@ -365,7 +373,9 @@ static void saproxy_free_storage(zend_object *object)
365373
//??? }
366374
//??? }
367375

368-
OBJ_RELEASE(&proxy->obj->zo);
376+
if (proxy->obj != NULL) {
377+
OBJ_RELEASE(&proxy->obj->zo);
378+
}
369379

370380
zend_object_std_dtor(object);
371381

ext/com_dotnet/php_com_dotnet_internal.h

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ extern zend_object_handlers php_com_object_handlers;
7676
void php_com_object_enable_event_sink(php_com_dotnet_object *obj, bool enable);
7777

7878
/* com_saproxy.c */
79+
zend_object *php_com_saproxy_create_object(zend_class_entry *class_type);
7980
zend_object_iterator *php_com_saproxy_iter_get(zend_class_entry *ce, zval *object, int by_ref);
8081
void php_com_saproxy_create(zend_object *com_object, zval *proxy_out, zval *index);
8182
extern zend_object_handlers php_com_saproxy_handlers;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
Manual instantiation of com_safearray_proxy is not allowed
3+
--EXTENSIONS--
4+
com_dotnet
5+
--FILE--
6+
<?php
7+
try {
8+
new com_safearray_proxy();
9+
} catch (Error $e) {
10+
echo $e->getMessage(), PHP_EOL;
11+
}
12+
?>
13+
--EXPECT--
14+
Cannot directly construct com_safeproxy_array; it is for internal usage only

0 commit comments

Comments
 (0)