3737#include "Zend/Optimizer/zend_optimizer.h"
3838#include "Zend/zend_alloc.h"
3939#include "test_arginfo.h"
40+ #include "tmp_methods_arginfo.h"
4041#include "zend_call_stack.h"
4142#include "zend_exceptions.h"
4243#include "zend_mm_custom_handlers.h"
4344#include "ext/uri/php_uri.h"
45+ #include "zend_observer.h"
4446
4547#if defined(HAVE_LIBXML ) && !defined(PHP_WIN32 )
4648# include <libxml/globals.h>
@@ -1023,16 +1025,38 @@ static ZEND_FUNCTION(zend_test_log_err_debug)
10231025 php_log_err_with_severity (ZSTR_VAL (str ), LOG_DEBUG );
10241026}
10251027
1028+ typedef struct _zend_test_object {
1029+ zend_internal_function * tmp_method ;
1030+ zend_object std ;
1031+ } zend_test_object ;
1032+
10261033static zend_object * zend_test_class_new (zend_class_entry * class_type )
10271034{
1028- zend_object * obj = zend_objects_new (class_type );
1029- object_properties_init (obj , class_type );
1030- obj -> handlers = & zend_test_class_handlers ;
1031- return obj ;
1035+ zend_test_object * intern = zend_object_alloc (sizeof (zend_test_object ), class_type );
1036+ zend_object_std_init (& intern -> std , class_type );
1037+ object_properties_init (& intern -> std , class_type );
1038+ return & intern -> std ;
1039+ }
1040+
1041+ static void zend_test_class_free_obj (zend_object * object )
1042+ {
1043+ zend_test_object * intern = (zend_test_object * )((char * )object - XtOffsetOf (zend_test_object , std ));
1044+
1045+ if (intern -> tmp_method ) {
1046+ zend_internal_function * func = intern -> tmp_method ;
1047+ intern -> tmp_method = NULL ;
1048+ zend_string_release_ex (func -> function_name , 0 );
1049+ zend_free_internal_arg_info (func , false);
1050+ efree (func );
1051+ }
1052+
1053+ zend_object_std_dtor (object );
10321054}
10331055
10341056static zend_function * zend_test_class_method_get (zend_object * * object , zend_string * name , const zval * key )
10351057{
1058+ zend_test_object * intern = (zend_test_object * )((char * )(* object ) - XtOffsetOf (zend_test_object , std ));
1059+
10361060 if (zend_string_equals_literal_ci (name , "test" )) {
10371061 zend_internal_function * fptr ;
10381062
@@ -1050,6 +1074,41 @@ static zend_function *zend_test_class_method_get(zend_object **object, zend_stri
10501074 fptr -> handler = ZEND_FN (zend_test_func );
10511075 fptr -> doc_comment = NULL ;
10521076
1077+ return (zend_function * )fptr ;
1078+ } else if (zend_string_equals_literal_ci (name , "testTmpMethodWithArgInfo" )) {
1079+ if (intern -> tmp_method ) {
1080+ return (zend_function * )intern -> tmp_method ;
1081+ }
1082+
1083+ const zend_function_entry * entry = & class_ZendTestTmpMethods_methods [0 ];
1084+ zend_internal_function * fptr = emalloc (sizeof (zend_internal_function ));
1085+ memset (fptr , 0 , sizeof (zend_internal_function ));
1086+ fptr -> type = ZEND_INTERNAL_FUNCTION ;
1087+ fptr -> handler = entry -> handler ;
1088+ fptr -> function_name = zend_string_init (entry -> fname , strlen (entry -> fname ), false);
1089+ fptr -> scope = intern -> std .ce ;
1090+ fptr -> prototype = NULL ;
1091+ fptr -> T = ZEND_OBSERVER_ENABLED ;
1092+ fptr -> fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_NEVER_CACHE ;
1093+
1094+ zend_internal_function_info * info = (zend_internal_function_info * )entry -> arg_info ;
1095+
1096+ uint32_t num_arg_info = 1 + entry -> num_args ;
1097+ zend_arg_info * arg_info = safe_emalloc (num_arg_info , sizeof (zend_arg_info ), 0 );
1098+ for (uint32_t i = 0 ; i < num_arg_info ; i ++ ) {
1099+ zend_convert_internal_arg_info (& arg_info [i ], & entry -> arg_info [i ], i == 0 , false);
1100+ }
1101+
1102+ fptr -> arg_info = arg_info + 1 ;
1103+ fptr -> num_args = entry -> num_args ;
1104+ if (info -> required_num_args == (uint32_t )-1 ) {
1105+ fptr -> required_num_args = entry -> num_args ;
1106+ } else {
1107+ fptr -> required_num_args = info -> required_num_args ;
1108+ }
1109+
1110+ intern -> tmp_method = fptr ;
1111+
10531112 return (zend_function * )fptr ;
10541113 }
10551114 return zend_std_get_method (object , name , key );
@@ -1136,6 +1195,18 @@ static ZEND_METHOD(_ZendTestClass, variadicTest) {
11361195 object_init_ex (return_value , zend_get_called_scope (execute_data ));
11371196}
11381197
1198+ ZEND_METHOD (ZendTestTmpMethods , testTmpMethodWithArgInfo )
1199+ {
1200+ zend_object * obj ;
1201+ zend_string * str ;
1202+
1203+ ZEND_PARSE_PARAMETERS_START (0 , 2 );
1204+ Z_PARAM_OPTIONAL ;
1205+ Z_PARAM_OBJ_OR_NULL (obj );
1206+ Z_PARAM_STR (str );
1207+ ZEND_PARSE_PARAMETERS_END ();
1208+ }
1209+
11391210static ZEND_METHOD (_ZendTestChildClass , returnsThrowable )
11401211{
11411212 ZEND_PARSE_PARAMETERS_NONE ();
@@ -1441,11 +1512,14 @@ PHP_MINIT_FUNCTION(zend_test)
14411512 register_ZendTestClass_dnf_property (zend_test_class );
14421513 zend_test_class -> create_object = zend_test_class_new ;
14431514 zend_test_class -> get_static_method = zend_test_class_static_method_get ;
1515+ zend_test_class -> default_object_handlers = & zend_test_class_handlers ;
14441516
14451517 zend_test_child_class = register_class__ZendTestChildClass (zend_test_class );
14461518
14471519 memcpy (& zend_test_class_handlers , & std_object_handlers , sizeof (zend_object_handlers ));
14481520 zend_test_class_handlers .get_method = zend_test_class_method_get ;
1521+ zend_test_class_handlers .free_obj = zend_test_class_free_obj ;
1522+ zend_test_class_handlers .offset = XtOffsetOf (zend_test_object , std );
14491523
14501524 zend_test_gen_stub_flag_compatibility_test = register_class_ZendTestGenStubFlagCompatibilityTest ();
14511525
0 commit comments