mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Merge branch 'PHP-8.4'
* PHP-8.4: Fixed GH-16233: Observer segfault when calling user function in internal function via trampoline
This commit is contained in:
@@ -32,6 +32,7 @@
|
|||||||
#include "zend_compile.h"
|
#include "zend_compile.h"
|
||||||
#include "zend_hash.h"
|
#include "zend_hash.h"
|
||||||
#include "zend_property_hooks.h"
|
#include "zend_property_hooks.h"
|
||||||
|
#include "zend_observer.h"
|
||||||
|
|
||||||
#define DEBUG_OBJECT_HANDLERS 0
|
#define DEBUG_OBJECT_HANDLERS 0
|
||||||
|
|
||||||
@@ -1627,7 +1628,8 @@ ZEND_API zend_function *zend_get_call_trampoline_func(const zend_class_entry *ce
|
|||||||
* value so that it doesn't contain garbage when the engine allocates space for the next stack
|
* value so that it doesn't contain garbage when the engine allocates space for the next stack
|
||||||
* frame. This didn't cause any issues until now due to "lucky" structure layout. */
|
* frame. This didn't cause any issues until now due to "lucky" structure layout. */
|
||||||
func->last_var = 0;
|
func->last_var = 0;
|
||||||
func->T = (fbc->type == ZEND_USER_FUNCTION)? MAX(fbc->op_array.last_var + fbc->op_array.T, 2) : 2;
|
uint32_t min_T = 2 + ZEND_OBSERVER_ENABLED;
|
||||||
|
func->T = (fbc->type == ZEND_USER_FUNCTION)? MAX(fbc->op_array.last_var + fbc->op_array.T, min_T) : min_T;
|
||||||
func->filename = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.filename : ZSTR_EMPTY_ALLOC();
|
func->filename = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.filename : ZSTR_EMPTY_ALLOC();
|
||||||
func->line_start = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_start : 0;
|
func->line_start = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_start : 0;
|
||||||
func->line_end = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_end : 0;
|
func->line_end = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_end : 0;
|
||||||
|
|||||||
@@ -1091,6 +1091,23 @@ static ZEND_METHOD(_ZendTestMagicCall, __call)
|
|||||||
RETURN_ARR(zend_new_pair(&name_zv, arguments));
|
RETURN_ARR(zend_new_pair(&name_zv, arguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ZEND_METHOD(_ZendTestMagicCallForward, __call)
|
||||||
|
{
|
||||||
|
zend_string *name;
|
||||||
|
zval *arguments;
|
||||||
|
|
||||||
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
||||||
|
Z_PARAM_STR(name)
|
||||||
|
Z_PARAM_ARRAY(arguments)
|
||||||
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
|
ZEND_IGNORE_VALUE(arguments);
|
||||||
|
|
||||||
|
zval func;
|
||||||
|
ZVAL_STR(&func, name);
|
||||||
|
call_user_function(NULL, NULL, &func, return_value, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
PHP_INI_BEGIN()
|
PHP_INI_BEGIN()
|
||||||
STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals)
|
STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals)
|
||||||
STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals)
|
STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals)
|
||||||
@@ -1280,6 +1297,8 @@ PHP_MINIT_FUNCTION(zend_test)
|
|||||||
|
|
||||||
zend_test_magic_call = register_class__ZendTestMagicCall();
|
zend_test_magic_call = register_class__ZendTestMagicCall();
|
||||||
|
|
||||||
|
register_class__ZendTestMagicCallForward();
|
||||||
|
|
||||||
zend_register_functions(NULL, ext_function_legacy, NULL, EG(current_module)->type);
|
zend_register_functions(NULL, ext_function_legacy, NULL, EG(current_module)->type);
|
||||||
|
|
||||||
// Loading via dl() not supported with the observer API
|
// Loading via dl() not supported with the observer API
|
||||||
|
|||||||
@@ -75,6 +75,11 @@ namespace {
|
|||||||
public function __call(string $name, array $args): mixed {}
|
public function __call(string $name, array $args): mixed {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _ZendTestMagicCallForward
|
||||||
|
{
|
||||||
|
public function __call(string $name, array $args): mixed {}
|
||||||
|
}
|
||||||
|
|
||||||
class _ZendTestChildClass extends _ZendTestClass
|
class _ZendTestChildClass extends _ZendTestClass
|
||||||
{
|
{
|
||||||
public function returnsThrowable(): Exception {}
|
public function returnsThrowable(): Exception {}
|
||||||
|
|||||||
24
ext/zend_test/test_arginfo.h
generated
24
ext/zend_test/test_arginfo.h
generated
@@ -1,5 +1,5 @@
|
|||||||
/* This is a generated file, edit the .stub.php file instead.
|
/* This is a generated file, edit the .stub.php file instead.
|
||||||
* Stub hash: 470b6d507911cf05279de3557df03831858dd8c1 */
|
* Stub hash: 5ba6aceffff4e81330182eb84014928630fc9cdd */
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
|
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
@@ -204,6 +204,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class__ZendTestMagicCall___call,
|
|||||||
ZEND_ARG_TYPE_INFO(0, args, IS_ARRAY, 0)
|
ZEND_ARG_TYPE_INFO(0, args, IS_ARRAY, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
#define arginfo_class__ZendTestMagicCallForward___call arginfo_class__ZendTestMagicCall___call
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class__ZendTestChildClass_returnsThrowable, 0, 0, Exception, 0)
|
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class__ZendTestChildClass_returnsThrowable, 0, 0, Exception, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
@@ -307,6 +309,7 @@ static ZEND_METHOD(_ZendTestClass, returnsThrowable);
|
|||||||
static ZEND_METHOD(_ZendTestClass, variadicTest);
|
static ZEND_METHOD(_ZendTestClass, variadicTest);
|
||||||
static ZEND_METHOD(_ZendTestClass, takesUnionType);
|
static ZEND_METHOD(_ZendTestClass, takesUnionType);
|
||||||
static ZEND_METHOD(_ZendTestMagicCall, __call);
|
static ZEND_METHOD(_ZendTestMagicCall, __call);
|
||||||
|
static ZEND_METHOD(_ZendTestMagicCallForward, __call);
|
||||||
static ZEND_METHOD(_ZendTestChildClass, returnsThrowable);
|
static ZEND_METHOD(_ZendTestChildClass, returnsThrowable);
|
||||||
static ZEND_METHOD(ZendAttributeTest, testMethod);
|
static ZEND_METHOD(ZendAttributeTest, testMethod);
|
||||||
static ZEND_METHOD(_ZendTestTrait, testMethod);
|
static ZEND_METHOD(_ZendTestTrait, testMethod);
|
||||||
@@ -457,6 +460,11 @@ static const zend_function_entry class__ZendTestMagicCall_methods[] = {
|
|||||||
ZEND_FE_END
|
ZEND_FE_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const zend_function_entry class__ZendTestMagicCallForward_methods[] = {
|
||||||
|
ZEND_ME(_ZendTestMagicCallForward, __call, arginfo_class__ZendTestMagicCallForward___call, ZEND_ACC_PUBLIC)
|
||||||
|
ZEND_FE_END
|
||||||
|
};
|
||||||
|
|
||||||
static const zend_function_entry class__ZendTestChildClass_methods[] = {
|
static const zend_function_entry class__ZendTestChildClass_methods[] = {
|
||||||
ZEND_ME(_ZendTestChildClass, returnsThrowable, arginfo_class__ZendTestChildClass_returnsThrowable, ZEND_ACC_PUBLIC)
|
ZEND_ME(_ZendTestChildClass, returnsThrowable, arginfo_class__ZendTestChildClass_returnsThrowable, ZEND_ACC_PUBLIC)
|
||||||
ZEND_FE_END
|
ZEND_FE_END
|
||||||
@@ -732,6 +740,20 @@ static zend_class_entry *register_class__ZendTestMagicCall(void)
|
|||||||
return class_entry;
|
return class_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static zend_class_entry *register_class__ZendTestMagicCallForward(void)
|
||||||
|
{
|
||||||
|
zend_class_entry ce, *class_entry;
|
||||||
|
|
||||||
|
INIT_CLASS_ENTRY(ce, "_ZendTestMagicCallForward", class__ZendTestMagicCallForward_methods);
|
||||||
|
#if (PHP_VERSION_ID >= 80400)
|
||||||
|
class_entry = zend_register_internal_class_with_flags(&ce, NULL, 0);
|
||||||
|
#else
|
||||||
|
class_entry = zend_register_internal_class_ex(&ce, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return class_entry;
|
||||||
|
}
|
||||||
|
|
||||||
static zend_class_entry *register_class__ZendTestChildClass(zend_class_entry *class_entry__ZendTestClass)
|
static zend_class_entry *register_class__ZendTestChildClass(zend_class_entry *class_entry__ZendTestClass)
|
||||||
{
|
{
|
||||||
zend_class_entry ce, *class_entry;
|
zend_class_entry ce, *class_entry;
|
||||||
|
|||||||
32
ext/zend_test/tests/gh16233.phpt
Normal file
32
ext/zend_test/tests/gh16233.phpt
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
--TEST--
|
||||||
|
GH-16233 (Observer segfault when calling user function in internal function via trampoline)
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--INI--
|
||||||
|
zend_test.observer.enabled=1
|
||||||
|
zend_test.observer.show_output=1
|
||||||
|
zend_test.observer.observe_all=1
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function callee() {
|
||||||
|
echo "in callee\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$test = new _ZendTestMagicCallForward;
|
||||||
|
$test->callee();
|
||||||
|
echo "done\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
<!-- init '%sgh16233.php' -->
|
||||||
|
<file '%sgh16233.php'>
|
||||||
|
<!-- init _ZendTestMagicCallForward::__call() -->
|
||||||
|
<_ZendTestMagicCallForward::__call>
|
||||||
|
<!-- init callee() -->
|
||||||
|
<callee>
|
||||||
|
in callee
|
||||||
|
</callee>
|
||||||
|
</_ZendTestMagicCallForward::__call>
|
||||||
|
done
|
||||||
|
</file '%sgh16233.php'>
|
||||||
Reference in New Issue
Block a user