mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Fix uouv on oom on object allocation
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 GH-11734
This commit is contained in:
parent
2196e2299f
commit
ee000ea186
2
NEWS
2
NEWS
@ -4,6 +4,8 @@ PHP NEWS
|
||||
|
||||
- Core:
|
||||
. Fixed strerror_r detection at configuration time. (Kévin Dunglas)
|
||||
. Fixed segfault during freeing of some incompletely initialized objects due
|
||||
to OOM error (PDO, SPL, XSL). (ilutov)
|
||||
|
||||
- DOM:
|
||||
. adoptNode now respects the strict error checking property. (nielsdos)
|
||||
|
15
Zend/tests/new_oom.inc
Normal file
15
Zend/tests/new_oom.inc
Normal file
@ -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
Zend/tests/new_oom.phpt
Normal file
24
Zend/tests/new_oom.phpt
Normal file
@ -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===
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user