Skip to content

Commit

Permalink
Fix uouv on oom on object allocation
Browse files Browse the repository at this point in the history
We should initialize object handlers before trying to allocate more memory,
because if we OOM we'll look for the free_obj handler which has not been
initialized. Furthermore, free_obj can run before the object is fully
initialized, requiring guards for potentially unset fields.

Fixes phpGH-11734
  • Loading branch information
iluuu1994 committed Aug 7, 2023
1 parent ed27d70 commit f39e7e4
Show file tree
Hide file tree
Showing 68 changed files with 177 additions and 136 deletions.
15 changes: 15 additions & 0 deletions Zend/tests/new_oom.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

$mb_used = (int) ceil(memory_get_usage() / (1024 ** 2));
ini_set('memory_limit', ($mb_used + 1) . 'M');

$class = $argv[1];
$objects = [];

try {
while (true) {
$rc = new ReflectionClass($class);
$objects[] = $rc->newInstanceWithoutConstructor();
}
} catch (Throwable) {
}
24 changes: 24 additions & 0 deletions Zend/tests/new_oom.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
--TEST--
Test OOM on new of each class
--SKIPIF--
<?php
if (getenv("SKIP_SLOW_TESTS")) die('skip slow test');
?>
--FILE--
<?php

$file = __DIR__ . '/new_oom.inc';
$php = PHP_BINARY;

foreach (get_declared_classes() as $class) {
$output = shell_exec("$php $file $class");
echo "Class $class failed\n";
if ($output && preg_match('(^\nFatal error: Allowed memory size of [0-9]+ bytes exhausted[^\r\n]* \(tried to allocate [0-9]+ bytes\) in [^\r\n]+ on line [0-9]+$)', $output) !== 1) {
echo $output;
}
}

?>
===DONE===
--EXPECT--
===DONE===
2 changes: 1 addition & 1 deletion Zend/zend_closures.c
Original file line number Diff line number Diff line change
Expand Up @@ -506,8 +506,8 @@ static zend_object *zend_closure_new(zend_class_entry *class_type) /* {{{ */
closure = emalloc(sizeof(zend_closure));
memset(closure, 0, sizeof(zend_closure));

zend_object_std_init(&closure->std, class_type);
closure->std.handlers = &closure_handlers;
zend_object_std_init(&closure->std, class_type);

return (zend_object*)closure;
}
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_fibers.c
Original file line number Diff line number Diff line change
Expand Up @@ -581,8 +581,8 @@ static zend_object *zend_fiber_object_create(zend_class_entry *ce)

memset(fiber, 0, sizeof(zend_fiber));

zend_object_std_init(&fiber->std, ce);
fiber->std.handlers = &zend_fiber_handlers;
zend_object_std_init(&fiber->std, ce);

return &fiber->std;
}
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_generators.c
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ static zend_object *zend_generator_create(zend_class_entry *class_type) /* {{{ *

generator = emalloc(sizeof(zend_generator));
memset(generator, 0, sizeof(zend_generator));
generator->std.handlers = &zend_generator_handlers;

/* The key will be incremented on first use, so it'll start at 0 */
generator->largest_used_integer_key = -1;
Expand All @@ -421,7 +422,6 @@ static zend_object *zend_generator_create(zend_class_entry *class_type) /* {{{ *
generator->node.ptr.root = NULL;

zend_object_std_init(&generator->std, class_type);
generator->std.handlers = &zend_generator_handlers;

return (zend_object*)generator;
}
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_interfaces.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,8 +448,8 @@ typedef struct {

static zend_object *zend_internal_iterator_create(zend_class_entry *ce) {
zend_internal_iterator *intern = emalloc(sizeof(zend_internal_iterator));
zend_object_std_init(&intern->std, ce);
intern->std.handlers = &zend_internal_iterator_handlers;
zend_object_std_init(&intern->std, ce);
intern->iter = NULL;
intern->rewind_called = 0;
return &intern->std;
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_iterators.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ static HashTable *iter_wrapper_get_gc(zend_object *object, zval **table, int *n)

ZEND_API void zend_iterator_init(zend_object_iterator *iter)
{
zend_object_std_init(&iter->std, &zend_iterator_class_entry);
iter->std.handlers = &iterator_object_handlers;
zend_object_std_init(&iter->std, &zend_iterator_class_entry);
}

ZEND_API void zend_iterator_dtor(zend_object_iterator *iter)
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ ZEND_API zend_object* ZEND_FASTCALL zend_objects_new(zend_class_entry *ce)
{
zend_object *object = emalloc(sizeof(zend_object) + zend_object_properties_size(ce));

_zend_object_std_init(object, ce);
object->handlers = &std_object_handlers;
_zend_object_std_init(object, ce);
return object;
}

Expand Down
6 changes: 3 additions & 3 deletions Zend/zend_weakrefs.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,10 @@ void zend_weakrefs_shutdown(void) {
static zend_object* zend_weakref_new(zend_class_entry *ce) {
zend_weakref *wr = zend_object_alloc(sizeof(zend_weakref), zend_ce_weakref);

zend_object_std_init(&wr->std, zend_ce_weakref);

wr->std.handlers = &zend_weakref_handlers;

zend_object_std_init(&wr->std, zend_ce_weakref);

return &wr->std;
}

Expand Down Expand Up @@ -284,8 +284,8 @@ ZEND_METHOD(WeakReference, get)
static zend_object *zend_weakmap_create_object(zend_class_entry *ce)
{
zend_weakmap *wm = zend_object_alloc(sizeof(zend_weakmap), ce);
zend_object_std_init(&wm->std, ce);
wm->std.handlers = &zend_weakmap_handlers;
zend_object_std_init(&wm->std, ce);

zend_hash_init(&wm->ht, 0, NULL, ZVAL_PTR_DTOR, 0);
return &wm->std;
Expand Down
2 changes: 1 addition & 1 deletion ext/com_dotnet/com_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -627,8 +627,8 @@ zend_object* php_com_object_new(zend_class_entry *ce)
obj->code_page = CP_ACP;
obj->ce = ce;

zend_object_std_init(&obj->zo, ce);
obj->zo.handlers = &php_com_object_handlers;
zend_object_std_init(&obj->zo, ce);

obj->typeinfo = NULL;

Expand Down
4 changes: 2 additions & 2 deletions ext/com_dotnet/com_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ PHP_COM_DOTNET_API void php_com_wrap_dispatch(zval *z, IDispatch *disp,
IDispatch_AddRef(V_DISPATCH(&obj->v));
IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo);

zend_object_std_init(&obj->zo, php_com_variant_class_entry);
obj->zo.handlers = &php_com_object_handlers;
zend_object_std_init(&obj->zo, php_com_variant_class_entry);
ZVAL_OBJ(z, &obj->zo);
}

Expand All @@ -84,8 +84,8 @@ PHP_COM_DOTNET_API void php_com_wrap_variant(zval *z, VARIANT *v,
IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo);
}

zend_object_std_init(&obj->zo, php_com_variant_class_entry);
obj->zo.handlers = &php_com_object_handlers;
zend_object_std_init(&obj->zo, php_com_variant_class_entry);
ZVAL_OBJ(z, &obj->zo);
}

Expand Down
2 changes: 1 addition & 1 deletion ext/com_dotnet/com_persist.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,8 +713,8 @@ static zend_object* helper_new(zend_class_entry *ce)
helper = emalloc(sizeof(*helper));
memset(helper, 0, sizeof(*helper));

zend_object_std_init(&helper->std, helper_ce);
helper->std.handlers = &helper_handlers;
zend_object_std_init(&helper->std, helper_ce);

return &helper->std;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/com_dotnet/com_saproxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,8 @@ int php_com_saproxy_create(zend_object *com_object, zval *proxy_out, zval *index

ZVAL_DUP(&proxy->indices[proxy->dimensions-1], index);

zend_object_std_init(&proxy->std, php_com_saproxy_class_entry);
proxy->std.handlers = &php_com_saproxy_handlers;
zend_object_std_init(&proxy->std, php_com_saproxy_class_entry);
ZVAL_OBJ(proxy_out, &proxy->std);

return 1;
Expand Down
2 changes: 1 addition & 1 deletion ext/curl/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -1221,9 +1221,9 @@ PHP_MINIT_FUNCTION(curl)
static zend_object *curl_create_object(zend_class_entry *class_type) {
php_curl *intern = zend_object_alloc(sizeof(php_curl), class_type);

intern->std.handlers = &curl_object_handlers;
zend_object_std_init(&intern->std, class_type);
object_properties_init(&intern->std, class_type);
intern->std.handlers = &curl_object_handlers;

return &intern->std;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/curl/multi.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,9 +517,9 @@ static zend_object_handlers curl_multi_handlers;
static zend_object *curl_multi_create_object(zend_class_entry *class_type) {
php_curlm *intern = zend_object_alloc(sizeof(php_curlm), class_type);

intern->std.handlers = &curl_multi_handlers;
zend_object_std_init(&intern->std, class_type);
object_properties_init(&intern->std, class_type);
intern->std.handlers = &curl_multi_handlers;

return &intern->std;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/curl/share.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ static zend_object_handlers curl_share_handlers;
static zend_object *curl_share_create_object(zend_class_entry *class_type) {
php_curlsh *intern = zend_object_alloc(sizeof(php_curlsh), class_type);

intern->std.handlers = &curl_share_handlers;
zend_object_std_init(&intern->std, class_type);
object_properties_init(&intern->std, class_type);
intern->std.handlers = &curl_share_handlers;

return &intern->std;
}
Expand Down
9 changes: 4 additions & 5 deletions ext/date/php_date.c
Original file line number Diff line number Diff line change
Expand Up @@ -1749,9 +1749,9 @@ static zend_object *date_object_new_date(zend_class_entry *class_type) /* {{{ */
{
php_date_obj *intern = zend_object_alloc(sizeof(php_date_obj), class_type);

intern->std.handlers = &date_object_handlers_date;
zend_object_std_init(&intern->std, class_type);
object_properties_init(&intern->std, class_type);
intern->std.handlers = &date_object_handlers_date;

return &intern->std;
} /* }}} */
Expand Down Expand Up @@ -1884,9 +1884,9 @@ static zend_object *date_object_new_timezone(zend_class_entry *class_type) /* {{
{
php_timezone_obj *intern = zend_object_alloc(sizeof(php_timezone_obj), class_type);

intern->std.handlers = &date_object_handlers_timezone;
zend_object_std_init(&intern->std, class_type);
object_properties_init(&intern->std, class_type);
intern->std.handlers = &date_object_handlers_timezone;

return &intern->std;
} /* }}} */
Expand Down Expand Up @@ -2043,9 +2043,9 @@ static zend_object *date_object_new_interval(zend_class_entry *class_type) /* {{
{
php_interval_obj *intern = zend_object_alloc(sizeof(php_interval_obj), class_type);

intern->std.handlers = &date_object_handlers_interval;
zend_object_std_init(&intern->std, class_type);
object_properties_init(&intern->std, class_type);
intern->std.handlers = &date_object_handlers_interval;

return &intern->std;
} /* }}} */
Expand Down Expand Up @@ -2118,11 +2118,10 @@ static zend_object *date_object_new_period(zend_class_entry *class_type) /* {{{
{
php_period_obj *intern = zend_object_alloc(sizeof(php_period_obj), class_type);

intern->std.handlers = &date_object_handlers_period;
zend_object_std_init(&intern->std, class_type);
object_properties_init(&intern->std, class_type);

intern->std.handlers = &date_object_handlers_period;

return &intern->std;
} /* }}} */

Expand Down
4 changes: 2 additions & 2 deletions ext/enchant/enchant.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ static inline enchant_broker *enchant_broker_from_obj(zend_object *obj) {
static zend_object *enchant_broker_create_object(zend_class_entry *class_type) {
enchant_broker *intern = zend_object_alloc(sizeof(enchant_broker), class_type);

intern->std.handlers = &enchant_broker_handlers;
zend_object_std_init(&intern->std, class_type);
object_properties_init(&intern->std, class_type);
intern->std.handlers = &enchant_broker_handlers;

return &intern->std;
}
Expand All @@ -71,9 +71,9 @@ static inline enchant_dict *enchant_dict_from_obj(zend_object *obj) {
static zend_object *enchant_dict_create_object(zend_class_entry *class_type) {
enchant_dict *intern = zend_object_alloc(sizeof(enchant_dict), class_type);

intern->std.handlers = &enchant_dict_handlers;
zend_object_std_init(&intern->std, class_type);
object_properties_init(&intern->std, class_type);
intern->std.handlers = &enchant_dict_handlers;

return &intern->std;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/fileinfo/fileinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ PHP_FILEINFO_API zend_object *finfo_objects_new(zend_class_entry *class_type)

intern = zend_object_alloc(sizeof(finfo_object), class_type);

intern->zo.handlers = &finfo_object_handlers;
zend_object_std_init(&intern->zo, class_type);
object_properties_init(&intern->zo, class_type);
intern->zo.handlers = &finfo_object_handlers;

return &intern->zo;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/ftp/php_ftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ static zend_object* ftp_object_create(zend_class_entry* ce) {
php_ftp_object *obj = zend_object_alloc(sizeof(php_ftp_object), ce);
zend_object *zobj = ftp_object_to_zend_object(obj);
obj->ftp = NULL;
zobj->handlers = &ftp_object_handlers;
zend_object_std_init(zobj, ce);
object_properties_init(zobj, ce);
zobj->handlers = &ftp_object_handlers;

return zobj;
}
Expand Down
4 changes: 2 additions & 2 deletions ext/gd/gd.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,9 @@ zend_object *php_gd_image_object_create(zend_class_entry *class_type)
php_gd_image_object *intern = emalloc(block_len);
memset(intern, 0, block_len);

intern->std.handlers = &php_gd_image_object_handlers;
zend_object_std_init(&intern->std, class_type);
object_properties_init(&intern->std, class_type);
intern->std.handlers = &php_gd_image_object_handlers;

return &intern->std;
}
Expand Down Expand Up @@ -263,9 +263,9 @@ static zend_object *php_gd_font_object_create(zend_class_entry *ce)
zend_object *zobj = php_gd_font_object_to_zend_object(obj);

obj->font = NULL;
zobj->handlers = &php_gd_font_object_handlers;
zend_object_std_init(zobj, ce);
object_properties_init(zobj, ce);
zobj->handlers = &php_gd_font_object_handlers;

return zobj;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/gmp/gmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,12 @@ static inline zend_object *gmp_create_object_ex(zend_class_entry *ce, mpz_ptr *g
{
gmp_object *intern = emalloc(sizeof(gmp_object) + zend_object_properties_size(ce));

intern->std.handlers = &gmp_object_handlers;
zend_object_std_init(&intern->std, ce);
object_properties_init(&intern->std, ce);

mpz_init(intern->num);
*gmpnum_target = intern->num;
intern->std.handlers = &gmp_object_handlers;

return &intern->std;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/hash/hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -1369,9 +1369,9 @@ static zend_object* php_hashcontext_create(zend_class_entry *ce) {
php_hashcontext_object *objval = zend_object_alloc(sizeof(php_hashcontext_object), ce);
zend_object *zobj = &objval->std;

zobj->handlers = &php_hashcontext_handlers;
zend_object_std_init(zobj, ce);
object_properties_init(zobj, ce);
zobj->handlers = &php_hashcontext_handlers;

return zobj;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/imap/php_imap.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,9 @@ static zend_object* imap_object_create(zend_class_entry* ce) {
zend_object *zobj = imap_object_to_zend_object(obj);
obj->imap_stream = NULL;
obj->flags = 0;
zobj->handlers = &imap_object_handlers;
zend_object_std_init(zobj, ce);
object_properties_init(zobj, ce);
zobj->handlers = &imap_object_handlers;

return zobj;
}
Expand Down
3 changes: 1 addition & 2 deletions ext/intl/breakiterator/breakiterator_class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,11 @@ static zend_object *BreakIterator_object_create(zend_class_entry *ce)

intern = (BreakIterator_object*) zend_object_alloc(sizeof(BreakIterator_object), ce);

intern->zo.handlers = &BreakIterator_handlers;
zend_object_std_init(&intern->zo, ce);
object_properties_init(&intern->zo, ce);
breakiterator_object_init(intern);

intern->zo.handlers = &BreakIterator_handlers;

return &intern->zo;
}
/* }}} */
Expand Down
4 changes: 1 addition & 3 deletions ext/intl/calendar/calendar_class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,13 +252,11 @@ static zend_object *Calendar_object_create(zend_class_entry *ce)

intern = (Calendar_object*)ecalloc(1, sizeof(Calendar_object) + sizeof(zval) * (ce->default_properties_count - 1));

intern->zo.handlers = &Calendar_handlers;
zend_object_std_init(&intern->zo, ce);
object_properties_init(&intern->zo, ce);
calendar_object_init(intern);


intern->zo.handlers = &Calendar_handlers;

return &intern->zo;
}
/* }}} */
Expand Down

0 comments on commit f39e7e4

Please sign in to comment.