mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fix GH-20286: use-after-destroy during userland stream_close()
Closes GH-20493. Co-authored-by: David Carlier <devnexen@gmail.com>
This commit is contained in:
2
NEWS
2
NEWS
@@ -6,6 +6,8 @@ PHP NEWS
|
||||
. Sync all boost.context files with release 1.86.0. (mvorisek)
|
||||
. Fixed bug GH-20435 (SensitiveParameter doesn't work for named argument
|
||||
passing to variadic parameter). (ndossche)
|
||||
. Fixed bug GH-20286 (use-after-destroy during userland stream_close()).
|
||||
(ndossche, David Carlier)
|
||||
|
||||
- Bz2:
|
||||
. Fix assertion failures resulting in crashes with stream filter
|
||||
|
||||
@@ -214,21 +214,34 @@ void zend_init_rsrc_plist(void)
|
||||
|
||||
void zend_close_rsrc_list(HashTable *ht)
|
||||
{
|
||||
/* Reload ht->arData on each iteration, as it may be reallocated. */
|
||||
uint32_t i = ht->nNumUsed;
|
||||
uint32_t num = ht->nNumUsed;
|
||||
|
||||
retry:
|
||||
zend_try {
|
||||
while (i-- > 0) {
|
||||
/* Reload ht->arData on each iteration, as it may be reallocated. */
|
||||
zval *p = ZEND_HASH_ELEMENT(ht, i);
|
||||
if (Z_TYPE_P(p) != IS_UNDEF) {
|
||||
zend_resource *res = Z_PTR_P(p);
|
||||
if (res->type >= 0) {
|
||||
zend_resource_dtor(res);
|
||||
|
||||
if (UNEXPECTED(ht->nNumUsed != num)) {
|
||||
/* New resources were added, reloop from the start.
|
||||
* We need to keep the top->down order to avoid freeing resources
|
||||
* in use by the newly created resources. */
|
||||
i = num = ht->nNumUsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} zend_catch {
|
||||
if (UNEXPECTED(ht->nNumUsed != num)) {
|
||||
/* See above */
|
||||
i = num = ht->nNumUsed;
|
||||
}
|
||||
|
||||
/* If we have bailed, we probably executed user code (e.g. user stream
|
||||
* API). Keep closing resources so they don't leak. User handlers must be
|
||||
* called now so they aren't called in zend_deactivate() on
|
||||
|
||||
43
ext/standard/tests/streams/gh20286.phpt
Normal file
43
ext/standard/tests/streams/gh20286.phpt
Normal file
@@ -0,0 +1,43 @@
|
||||
--TEST--
|
||||
GH-20286 use after destroy on userland stream_close
|
||||
--CREDITS--
|
||||
vi3tL0u1s
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (substr(PHP_OS, 0, 3) == 'WIN') die('skip Aborts with STATUS_BAD_FUNCTION_TABLE on Windows');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
class lib {
|
||||
public $context;
|
||||
function stream_set() {}
|
||||
function stream_set_option() {}
|
||||
function stream_stat() {
|
||||
return true;
|
||||
}
|
||||
function stream_open() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function stream_read($count) {
|
||||
function a() {}
|
||||
include('lib://');
|
||||
}
|
||||
|
||||
function stream_close() {
|
||||
static $count = 0;
|
||||
if ($count++ < 3) // Prevent infinite loop
|
||||
include('lib://');
|
||||
}
|
||||
}
|
||||
stream_wrapper_register('lib', lib::class);
|
||||
include('lib://test.php');
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot redeclare a() (previously declared in %s:%d) in %s on line %d
|
||||
|
||||
Fatal error: Cannot redeclare a() (previously declared in %s on line %d
|
||||
|
||||
Fatal error: Cannot redeclare a() (previously declared in %s on line %d
|
||||
|
||||
Fatal error: Cannot redeclare a() (previously declared in %s on line %d
|
||||
@@ -254,6 +254,7 @@ typedef struct _php_userstream_data php_userstream_data_t;
|
||||
static zend_result call_method_if_exists(
|
||||
zval *object, zval *method_name, zval *retval, uint32_t param_count, zval *params)
|
||||
{
|
||||
ZEND_ASSERT(EG(active));
|
||||
return zend_call_method_if_exists(
|
||||
Z_OBJ_P(object), Z_STR_P(method_name), retval, param_count, params);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user