diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index e2503d6d3045d..de464010a74cd 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1077,6 +1077,14 @@ ZEND_API zend_result zend_call_method_if_exists( zend_object *object, zend_string *method_name, zval *retval, uint32_t param_count, zval *params) { + if (UNEXPECTED(!EG(active))) { +#if ZEND_DEBUG + ZEND_UNREACHABLE(); +#endif + ZVAL_UNDEF(retval); + return FAILURE; + } + zend_fcall_info fci; fci.size = sizeof(zend_fcall_info); fci.object = object; diff --git a/ext/standard/tests/streams/gh20286.phpt b/ext/standard/tests/streams/gh20286.phpt new file mode 100644 index 0000000000000..aa281fe3e4034 --- /dev/null +++ b/ext/standard/tests/streams/gh20286.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-20286 use after destroy on userland stream_close +--CREDITS-- +vi3tL0u1s +--SKIPIF-- + +--FILE-- + +--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:%d) in %s on line %d + +Fatal error: Cannot redeclare a() (previously declared in %s:%d) in %s on line %d diff --git a/main/streams/userspace.c b/main/streams/userspace.c index 8d15172ef1319..89984277611dc 100644 --- a/main/streams/userspace.c +++ b/main/streams/userspace.c @@ -695,6 +695,10 @@ static int php_userstreamop_close(php_stream *stream, int close_handle) assert(us != NULL); + if (UNEXPECTED(stream->wrapper->wops != &user_stream_wops)) { + stream->wrapper->wops = &user_stream_wops; + } + ZVAL_STRINGL(&func_name, USERSTREAM_CLOSE, sizeof(USERSTREAM_CLOSE)-1); call_method_if_exists(&us->object, &func_name, &retval, 0, NULL);