Skip to content

Commit

Permalink
Fix uouv on oom on object allocation
Browse files Browse the repository at this point in the history
We may OOM during object initialization. In this case, free_obj needs to guard
against NULL values. There may be more cases where this is an issue, these were
the ones I was able to discover via script.

Fixes phpGH-11734
  • Loading branch information
iluuu1994 committed Aug 9, 2023
1 parent efc73f2 commit 7603da8
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 9 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 2>&1");
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 "Class $class failed\n";
echo $output, "\n";
}
}

?>
===DONE===
--EXPECT--
===DONE===
6 changes: 6 additions & 0 deletions ext/pdo/pdo_dbh.c
Original file line number Diff line number Diff line change
Expand Up @@ -1414,6 +1414,12 @@ static void dbh_free(pdo_dbh_t *dbh, bool free_persistent)
static void pdo_dbh_free_storage(zend_object *std)
{
pdo_dbh_t *dbh = php_pdo_dbh_fetch_inner(std);

/* dbh might be null if we OOMed during object initialization. */
if (!dbh) {
return;
}

if (dbh->driver_data && dbh->methods && dbh->methods->rollback && pdo_is_in_transaction(dbh)) {
dbh->methods->rollback(dbh);
dbh->in_txn = false;
Expand Down
11 changes: 6 additions & 5 deletions ext/spl/spl_dllist.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,12 +295,13 @@ static void spl_dllist_object_free_storage(zend_object *object) /* {{{ */

zend_object_std_dtor(&intern->std);

while (intern->llist->count > 0) {
spl_ptr_llist_pop(intern->llist, &tmp);
zval_ptr_dtor(&tmp);
if (intern->llist) {
while (intern->llist->count > 0) {
spl_ptr_llist_pop(intern->llist, &tmp);
zval_ptr_dtor(&tmp);
}
spl_ptr_llist_destroy(intern->llist);
}

spl_ptr_llist_destroy(intern->llist);
SPL_LLIST_CHECK_DELREF(intern->traverse_pointer);
}
/* }}} */
Expand Down
5 changes: 5 additions & 0 deletions ext/spl/spl_heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,11 @@ static spl_ptr_heap *spl_ptr_heap_clone(spl_ptr_heap *from) { /* {{{ */
/* }}} */

static void spl_ptr_heap_destroy(spl_ptr_heap *heap) { /* {{{ */
/* Heap might be null if we OOMed during object initialization. */
if (!heap) {
return;
}

int i;

for (i = 0; i < heap->count; ++i) {
Expand Down
12 changes: 8 additions & 4 deletions ext/xsl/php_xsl.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,15 @@ void xsl_objects_free_storage(zend_object *object)

zend_object_std_dtor(&intern->std);

zend_hash_destroy(intern->parameter);
FREE_HASHTABLE(intern->parameter);
if (intern->parameter) {
zend_hash_destroy(intern->parameter);
FREE_HASHTABLE(intern->parameter);
}

zend_hash_destroy(intern->registered_phpfunctions);
FREE_HASHTABLE(intern->registered_phpfunctions);
if (intern->registered_phpfunctions) {
zend_hash_destroy(intern->registered_phpfunctions);
FREE_HASHTABLE(intern->registered_phpfunctions);
}

if (intern->node_list) {
zend_hash_destroy(intern->node_list);
Expand Down

0 comments on commit 7603da8

Please sign in to comment.