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 GH-11734
  • Loading branch information
iluuu1994 committed Jul 31, 2023
1 parent b0bc057 commit d8bc94e
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 2 deletions.
14 changes: 14 additions & 0 deletions Zend/tests/new_oom.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

ini_set('memory_limit', '1M');

$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");
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;
}
}

?>
===DONE===
--EXPECT--
===DONE===
9 changes: 7 additions & 2 deletions ext/spl/spl_heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,11 @@ static spl_ptr_heap *spl_ptr_heap_clone(spl_ptr_heap *from) { /* {{{ */
static void spl_ptr_heap_destroy(spl_ptr_heap *heap) { /* {{{ */
int i;

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

for (i = 0; i < heap->count; ++i) {
heap->dtor(spl_heap_elem(heap, i));
}
Expand Down Expand Up @@ -438,18 +443,18 @@ static zend_object *spl_heap_object_new_ex(zend_class_entry *class_type, zend_ob

while (parent) {
if (parent == spl_ce_SplPriorityQueue) {
intern->heap = spl_ptr_heap_init(spl_ptr_pqueue_elem_cmp, spl_ptr_heap_pqueue_elem_ctor, spl_ptr_heap_pqueue_elem_dtor, sizeof(spl_pqueue_elem));
intern->std.handlers = &spl_handler_SplPriorityQueue;
intern->heap = spl_ptr_heap_init(spl_ptr_pqueue_elem_cmp, spl_ptr_heap_pqueue_elem_ctor, spl_ptr_heap_pqueue_elem_dtor, sizeof(spl_pqueue_elem));
intern->flags = SPL_PQUEUE_EXTR_DATA;
break;
}

if (parent == spl_ce_SplMinHeap || parent == spl_ce_SplMaxHeap
|| parent == spl_ce_SplHeap) {
intern->std.handlers = &spl_handler_SplHeap;
intern->heap = spl_ptr_heap_init(
parent == spl_ce_SplMinHeap ? spl_ptr_heap_zval_min_cmp : spl_ptr_heap_zval_max_cmp,
spl_ptr_heap_zval_ctor, spl_ptr_heap_zval_dtor, sizeof(zval));
intern->std.handlers = &spl_handler_SplHeap;
break;
}

Expand Down

0 comments on commit d8bc94e

Please sign in to comment.