mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3: Fix GH-16604: Memory leaks in SPL constructors
This commit is contained in:
1
NEWS
1
NEWS
@@ -35,6 +35,7 @@ PHP NEWS
|
|||||||
. Fix GH-16477 (Segmentation fault when calling __debugInfo() after failed
|
. Fix GH-16477 (Segmentation fault when calling __debugInfo() after failed
|
||||||
SplFileObject::__constructor). (Girgias)
|
SplFileObject::__constructor). (Girgias)
|
||||||
. Fixed bug GH-16589 (UAF in SplDoublyLinked->serialize()). (nielsdos)
|
. Fixed bug GH-16589 (UAF in SplDoublyLinked->serialize()). (nielsdos)
|
||||||
|
. Fixed bug GH-16604 (Memory leaks in SPL constructors). (nielsdos)
|
||||||
|
|
||||||
- SysVShm:
|
- SysVShm:
|
||||||
. Fixed bug GH-16591 (Assertion error in shm_put_var). (nielsdos, cmb)
|
. Fixed bug GH-16591 (Assertion error in shm_put_var). (nielsdos, cmb)
|
||||||
|
|||||||
@@ -2027,6 +2027,12 @@ PHP_METHOD(SplFileObject, __construct)
|
|||||||
RETURN_THROWS();
|
RETURN_THROWS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prevent reinitialization of Object */
|
||||||
|
if (UNEXPECTED(intern->u.file.stream)) {
|
||||||
|
zend_throw_error(NULL, "Cannot call constructor twice");
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
intern->u.file.open_mode = zend_string_copy(open_mode);
|
intern->u.file.open_mode = zend_string_copy(open_mode);
|
||||||
/* file_name and zcontext are copied by spl_filesystem_file_open() */
|
/* file_name and zcontext are copied by spl_filesystem_file_open() */
|
||||||
intern->file_name = file_name;
|
intern->file_name = file_name;
|
||||||
@@ -2070,7 +2076,7 @@ PHP_METHOD(SplTempFileObject, __construct)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Prevent reinitialization of Object */
|
/* Prevent reinitialization of Object */
|
||||||
if (intern->u.file.stream) {
|
if (UNEXPECTED(intern->u.file.stream)) {
|
||||||
zend_throw_error(NULL, "Cannot call constructor twice");
|
zend_throw_error(NULL, "Cannot call constructor twice");
|
||||||
RETURN_THROWS();
|
RETURN_THROWS();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -524,6 +524,20 @@ static zend_result spl_get_iterator_from_aggregate(zval *retval, zend_class_entr
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void spl_RecursiveIteratorIterator_free_iterators(spl_recursive_it_object *object)
|
||||||
|
{
|
||||||
|
if (object->iterators) {
|
||||||
|
while (object->level >= 0) {
|
||||||
|
zend_object_iterator *sub_iter = object->iterators[object->level].iterator;
|
||||||
|
zend_iterator_dtor(sub_iter);
|
||||||
|
zval_ptr_dtor(&object->iterators[object->level].zobject);
|
||||||
|
object->level--;
|
||||||
|
}
|
||||||
|
efree(object->iterators);
|
||||||
|
object->iterators = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_base, zend_class_entry *ce_inner, recursive_it_it_type rit_type)
|
static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_base, zend_class_entry *ce_inner, recursive_it_it_type rit_type)
|
||||||
{
|
{
|
||||||
zval *object = ZEND_THIS;
|
zval *object = ZEND_THIS;
|
||||||
@@ -594,6 +608,7 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla
|
|||||||
}
|
}
|
||||||
|
|
||||||
intern = Z_SPLRECURSIVE_IT_P(object);
|
intern = Z_SPLRECURSIVE_IT_P(object);
|
||||||
|
spl_RecursiveIteratorIterator_free_iterators(intern);
|
||||||
intern->iterators = emalloc(sizeof(spl_sub_iterator));
|
intern->iterators = emalloc(sizeof(spl_sub_iterator));
|
||||||
intern->level = 0;
|
intern->level = 0;
|
||||||
intern->mode = mode;
|
intern->mode = mode;
|
||||||
@@ -640,6 +655,7 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla
|
|||||||
intern->iterators[0].getchildren = NULL;
|
intern->iterators[0].getchildren = NULL;
|
||||||
|
|
||||||
if (EG(exception)) {
|
if (EG(exception)) {
|
||||||
|
// TODO: use spl_RecursiveIteratorIterator_free_iterators
|
||||||
zend_object_iterator *sub_iter;
|
zend_object_iterator *sub_iter;
|
||||||
|
|
||||||
while (intern->level >= 0) {
|
while (intern->level >= 0) {
|
||||||
@@ -912,16 +928,7 @@ static void spl_RecursiveIteratorIterator_free_storage(zend_object *_object)
|
|||||||
{
|
{
|
||||||
spl_recursive_it_object *object = spl_recursive_it_from_obj(_object);
|
spl_recursive_it_object *object = spl_recursive_it_from_obj(_object);
|
||||||
|
|
||||||
if (object->iterators) {
|
spl_RecursiveIteratorIterator_free_iterators(object);
|
||||||
while (object->level >= 0) {
|
|
||||||
zend_object_iterator *sub_iter = object->iterators[object->level].iterator;
|
|
||||||
zend_iterator_dtor(sub_iter);
|
|
||||||
zval_ptr_dtor(&object->iterators[object->level].zobject);
|
|
||||||
object->level--;
|
|
||||||
}
|
|
||||||
efree(object->iterators);
|
|
||||||
object->iterators = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
zend_object_std_dtor(&object->std);
|
zend_object_std_dtor(&object->std);
|
||||||
for (size_t i = 0; i < 6; i++) {
|
for (size_t i = 0; i < 6; i++) {
|
||||||
|
|||||||
15
ext/spl/tests/gh16604_1.phpt
Normal file
15
ext/spl/tests/gh16604_1.phpt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
--TEST--
|
||||||
|
GH-16604 (Memory leaks in SPL constructors) - recursive iterators
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$traversable = new RecursiveArrayIterator( [] );
|
||||||
|
|
||||||
|
$obj = new RecursiveIteratorIterator( $traversable );
|
||||||
|
$obj->__construct( $traversable );
|
||||||
|
|
||||||
|
$obj = new RecursiveTreeIterator( $traversable );
|
||||||
|
$obj->__construct( $traversable );
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
21
ext/spl/tests/gh16604_2.phpt
Normal file
21
ext/spl/tests/gh16604_2.phpt
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
--TEST--
|
||||||
|
GH-16604 (Memory leaks in SPL constructors) - SplFileObject
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
file_put_contents(__DIR__.'/gh16604_2.tmp', 'hello');
|
||||||
|
|
||||||
|
$obj = new SplFileObject(__DIR__.'/gh16604_2.tmp');
|
||||||
|
try {
|
||||||
|
$obj->__construct(__DIR__.'/gh16604_2.tmp');
|
||||||
|
} catch (Error $e) {
|
||||||
|
echo $e->getMessage(), "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--CLEAN--
|
||||||
|
<?php
|
||||||
|
@unlink(__DIR__.'/gh16604_2.tmp');
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Cannot call constructor twice
|
||||||
Reference in New Issue
Block a user