xref: /PHP-8.0/Zend/zend_API.h (revision b765d4cd)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) Zend Technologies Ltd. (http://www.zend.com)           |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 2.00 of the Zend license,     |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.zend.com/license/2_00.txt.                                |
11    | If you did not receive a copy of the Zend license and are unable to  |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@zend.com so we can mail you a copy immediately.              |
14    +----------------------------------------------------------------------+
15    | Authors: Andi Gutmans <andi@php.net>                                 |
16    |          Zeev Suraski <zeev@php.net>                                 |
17    |          Andrei Zmievski <andrei@php.net>                            |
18    |          Dmitry Stogov <dmitry@php.net>                              |
19    +----------------------------------------------------------------------+
20 */
21 
22 #ifndef ZEND_API_H
23 #define ZEND_API_H
24 
25 #include "zend_modules.h"
26 #include "zend_list.h"
27 #include "zend_operators.h"
28 #include "zend_variables.h"
29 #include "zend_execute.h"
30 #include "zend_type_info.h"
31 
32 
33 BEGIN_EXTERN_C()
34 
35 typedef struct _zend_function_entry {
36 	const char *fname;
37 	zif_handler handler;
38 	const struct _zend_internal_arg_info *arg_info;
39 	uint32_t num_args;
40 	uint32_t flags;
41 } zend_function_entry;
42 
43 typedef struct _zend_fcall_info {
44 	size_t size;
45 	zval function_name;
46 	zval *retval;
47 	zval *params;
48 	zend_object *object;
49 	uint32_t param_count;
50 	/* This hashtable can also contain positional arguments (with integer keys),
51 	 * which will be appended to the normal params[]. This makes it easier to
52 	 * integrate APIs like call_user_func_array(). The usual restriction that
53 	 * there may not be position arguments after named arguments applies. */
54 	HashTable *named_params;
55 } zend_fcall_info;
56 
57 typedef struct _zend_fcall_info_cache {
58 	zend_function *function_handler;
59 	zend_class_entry *calling_scope;
60 	zend_class_entry *called_scope;
61 	zend_object *object;
62 } zend_fcall_info_cache;
63 
64 #define ZEND_NS_NAME(ns, name)			ns "\\" name
65 
66 /* ZEND_FN/ZEND_MN are inlined below to prevent pre-scan macro expansion,
67  * which causes issues if the function name is also a macro name. */
68 #define ZEND_FN(name) zif_##name
69 #define ZEND_MN(name) zim_##name
70 
71 #define ZEND_NAMED_FUNCTION(name)		void ZEND_FASTCALL name(INTERNAL_FUNCTION_PARAMETERS)
72 #define ZEND_FUNCTION(name)				ZEND_NAMED_FUNCTION(zif_##name)
73 #define ZEND_METHOD(classname, name)	ZEND_NAMED_FUNCTION(zim_##classname##_##name)
74 
75 #define ZEND_FENTRY(zend_name, name, arg_info, flags)	{ #zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags },
76 
77 #define ZEND_RAW_FENTRY(zend_name, name, arg_info, flags)   { zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags },
78 
79 /* Same as ZEND_NAMED_FE */
80 #define ZEND_RAW_NAMED_FE(zend_name, name, arg_info) ZEND_RAW_FENTRY(#zend_name, name, arg_info, 0)
81 
82 #define ZEND_NAMED_FE(zend_name, name, arg_info)	ZEND_RAW_FENTRY(#zend_name, name, arg_info, 0)
83 #define ZEND_FE(name, arg_info)						ZEND_RAW_FENTRY(#name, zif_##name, arg_info, 0)
84 #define ZEND_DEP_FE(name, arg_info)                 ZEND_RAW_FENTRY(#name, zif_##name, arg_info, ZEND_ACC_DEPRECATED)
85 #define ZEND_FALIAS(name, alias, arg_info)			ZEND_RAW_FENTRY(#name, zif_##alias, arg_info, 0)
86 #define ZEND_DEP_FALIAS(name, alias, arg_info)		ZEND_RAW_FENTRY(#name, zif_##alias, arg_info, ZEND_ACC_DEPRECATED)
87 #define ZEND_NAMED_ME(zend_name, name, arg_info, flags)	ZEND_FENTRY(zend_name, name, arg_info, flags)
88 #define ZEND_ME(classname, name, arg_info, flags)	ZEND_RAW_FENTRY(#name, zim_##classname##_##name, arg_info, flags)
89 #define ZEND_DEP_ME(classname, name, arg_info, flags) ZEND_RAW_FENTRY(#name, zim_##classname##_##name, arg_info, flags | ZEND_ACC_DEPRECATED)
90 #define ZEND_ABSTRACT_ME(classname, name, arg_info)	ZEND_RAW_FENTRY(#name, NULL, arg_info, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT)
91 #define ZEND_ABSTRACT_ME_WITH_FLAGS(classname, name, arg_info, flags)	ZEND_RAW_FENTRY(#name, NULL, arg_info, flags)
92 #define ZEND_MALIAS(classname, name, alias, arg_info, flags) ZEND_RAW_FENTRY(#name, zim_##classname##_##alias, arg_info, flags)
93 #define ZEND_ME_MAPPING(name, func_name, arg_info, flags) ZEND_RAW_FENTRY(#name, zif_##func_name, arg_info, flags)
94 
95 #define ZEND_NS_FENTRY(ns, zend_name, name, arg_info, flags)		ZEND_RAW_FENTRY(ZEND_NS_NAME(ns, #zend_name), name, arg_info, flags)
96 
97 #define ZEND_NS_RAW_FENTRY(ns, zend_name, name, arg_info, flags)	ZEND_RAW_FENTRY(ZEND_NS_NAME(ns, zend_name), name, arg_info, flags)
98 
99 /* Same as ZEND_NS_NAMED_FE */
100 #define ZEND_NS_RAW_NAMED_FE(ns, zend_name, name, arg_info)			ZEND_NS_RAW_FENTRY(ns, #zend_name, name, arg_info, 0)
101 
102 #define ZEND_NS_NAMED_FE(ns, zend_name, name, arg_info)	ZEND_NS_RAW_FENTRY(ns, #zend_name, name, arg_info, 0)
103 #define ZEND_NS_FE(ns, name, arg_info)					ZEND_NS_RAW_FENTRY(ns, #name, zif_##name, arg_info, 0)
104 #define ZEND_NS_DEP_FE(ns, name, arg_info)				ZEND_NS_RAW_FENTRY(ns, #name, zif_##name, arg_info, ZEND_ACC_DEPRECATED)
105 #define ZEND_NS_FALIAS(ns, name, alias, arg_info)		ZEND_NS_RAW_FENTRY(ns, #name, zif_##alias, arg_info, 0)
106 #define ZEND_NS_DEP_FALIAS(ns, name, alias, arg_info)	ZEND_NS_RAW_FENTRY(ns, #name, zif_##alias, arg_info, ZEND_ACC_DEPRECATED)
107 
108 #define ZEND_FE_END            { NULL, NULL, NULL, 0, 0 }
109 
110 #define _ZEND_ARG_INFO_FLAGS(pass_by_ref, is_variadic) \
111 	(((pass_by_ref) << _ZEND_SEND_MODE_SHIFT) | ((is_variadic) ? _ZEND_IS_VARIADIC_BIT : 0))
112 
113 /* Arginfo structures without type information */
114 #define ZEND_ARG_INFO(pass_by_ref, name) \
115 	{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
116 #define ZEND_ARG_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, default_value) \
117 	{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
118 #define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) \
119 	{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), NULL },
120 /* Arginfo structures with simple type information */
121 #define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \
122 	{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
123 #define ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, type_hint, allow_null, default_value) \
124 	{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
125 #define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \
126 	{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), NULL },
127 /* Arginfo structures with complex type information */
128 #define ZEND_ARG_TYPE_MASK(pass_by_ref, name, type_mask, default_value) \
129 	{ #name, ZEND_TYPE_INIT_MASK(type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
130 #define ZEND_ARG_OBJ_TYPE_MASK(pass_by_ref, name, class_name, type_mask, default_value) \
131 	{ #name, ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
132 /* Arginfo structures with object type information */
133 #define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) \
134 	{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
135 #define ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, classname, allow_null, default_value) \
136 	{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
137 #define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, classname, allow_null) \
138 	{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), NULL },
139 /* Legacy arginfo structures */
140 #define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) \
141 	{ #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
142 #define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) \
143 	{ #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
144 
145 #define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \
146 	static const zend_internal_arg_info name[] = { \
147 		{ (const char*)(zend_uintptr_t)(required_num_args), \
148 			ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
149 
150 #define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO(name, class_name, allow_null) \
151 	ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, 0, -1, class_name, allow_null)
152 
153 #define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(name, return_reference, required_num_args, type) \
154 	static const zend_internal_arg_info name[] = { \
155 		{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_MASK(type | _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
156 
157 #define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(name, return_reference, required_num_args, class_name, type) \
158 	static const zend_internal_arg_info name[] = { \
159 		{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type | _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
160 
161 #define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
162 	static const zend_internal_arg_info name[] = { \
163 		{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
164 #define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(name, type, allow_null) \
165 	ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, 0, -1, type, allow_null)
166 
167 #define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args)	\
168 	static const zend_internal_arg_info name[] = { \
169 		{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
170 #define ZEND_BEGIN_ARG_INFO(name, _unused)	\
171 	ZEND_BEGIN_ARG_INFO_EX(name, {}, ZEND_RETURN_VALUE, -1)
172 #define ZEND_END_ARG_INFO()		};
173 
174 /* Name macros */
175 #define ZEND_MODULE_STARTUP_N(module)       zm_startup_##module
176 #define ZEND_MODULE_SHUTDOWN_N(module)		zm_shutdown_##module
177 #define ZEND_MODULE_ACTIVATE_N(module)		zm_activate_##module
178 #define ZEND_MODULE_DEACTIVATE_N(module)	zm_deactivate_##module
179 #define ZEND_MODULE_POST_ZEND_DEACTIVATE_N(module)	zm_post_zend_deactivate_##module
180 #define ZEND_MODULE_INFO_N(module)			zm_info_##module
181 #define ZEND_MODULE_GLOBALS_CTOR_N(module)  zm_globals_ctor_##module
182 #define ZEND_MODULE_GLOBALS_DTOR_N(module)  zm_globals_dtor_##module
183 
184 /* Declaration macros */
185 #define ZEND_MODULE_STARTUP_D(module)		zend_result ZEND_MODULE_STARTUP_N(module)(INIT_FUNC_ARGS)
186 #define ZEND_MODULE_SHUTDOWN_D(module)		zend_result ZEND_MODULE_SHUTDOWN_N(module)(SHUTDOWN_FUNC_ARGS)
187 #define ZEND_MODULE_ACTIVATE_D(module)		zend_result ZEND_MODULE_ACTIVATE_N(module)(INIT_FUNC_ARGS)
188 #define ZEND_MODULE_DEACTIVATE_D(module)	zend_result ZEND_MODULE_DEACTIVATE_N(module)(SHUTDOWN_FUNC_ARGS)
189 #define ZEND_MODULE_POST_ZEND_DEACTIVATE_D(module)	zend_result ZEND_MODULE_POST_ZEND_DEACTIVATE_N(module)(void)
190 #define ZEND_MODULE_INFO_D(module)			ZEND_COLD void ZEND_MODULE_INFO_N(module)(ZEND_MODULE_INFO_FUNC_ARGS)
191 #define ZEND_MODULE_GLOBALS_CTOR_D(module)  void ZEND_MODULE_GLOBALS_CTOR_N(module)(zend_##module##_globals *module##_globals)
192 #define ZEND_MODULE_GLOBALS_DTOR_D(module)  void ZEND_MODULE_GLOBALS_DTOR_N(module)(zend_##module##_globals *module##_globals)
193 
194 #define ZEND_GET_MODULE(name) \
195     BEGIN_EXTERN_C()\
196 	ZEND_DLEXPORT zend_module_entry *get_module(void) { return &name##_module_entry; }\
197     END_EXTERN_C()
198 
199 #define ZEND_BEGIN_MODULE_GLOBALS(module_name)		\
200 	typedef struct _zend_##module_name##_globals {
201 #define ZEND_END_MODULE_GLOBALS(module_name)		\
202 	} zend_##module_name##_globals;
203 
204 #ifdef ZTS
205 
206 #define ZEND_DECLARE_MODULE_GLOBALS(module_name)							\
207 	ts_rsrc_id module_name##_globals_id;
208 #define ZEND_EXTERN_MODULE_GLOBALS(module_name)								\
209 	extern ts_rsrc_id module_name##_globals_id;
210 #define ZEND_INIT_MODULE_GLOBALS(module_name, globals_ctor, globals_dtor)	\
211 	ts_allocate_id(&module_name##_globals_id, sizeof(zend_##module_name##_globals), (ts_allocate_ctor) globals_ctor, (ts_allocate_dtor) globals_dtor);
212 #define ZEND_MODULE_GLOBALS_ACCESSOR(module_name, v) ZEND_TSRMG(module_name##_globals_id, zend_##module_name##_globals *, v)
213 #ifdef ZEND_ENABLE_STATIC_TSRMLS_CACHE
214 #define ZEND_MODULE_GLOBALS_BULK(module_name) TSRMG_BULK_STATIC(module_name##_globals_id, zend_##module_name##_globals *)
215 #else
216 #define ZEND_MODULE_GLOBALS_BULK(module_name) TSRMG_BULK(module_name##_globals_id, zend_##module_name##_globals *)
217 #endif
218 
219 #else
220 
221 #define ZEND_DECLARE_MODULE_GLOBALS(module_name)							\
222 	zend_##module_name##_globals module_name##_globals;
223 #define ZEND_EXTERN_MODULE_GLOBALS(module_name)								\
224 	extern zend_##module_name##_globals module_name##_globals;
225 #define ZEND_INIT_MODULE_GLOBALS(module_name, globals_ctor, globals_dtor)	\
226 	globals_ctor(&module_name##_globals);
227 #define ZEND_MODULE_GLOBALS_ACCESSOR(module_name, v) (module_name##_globals.v)
228 #define ZEND_MODULE_GLOBALS_BULK(module_name) (&module_name##_globals)
229 
230 #endif
231 
232 #define INIT_CLASS_ENTRY(class_container, class_name, functions) \
233 	INIT_CLASS_ENTRY_EX(class_container, class_name, sizeof(class_name)-1, functions)
234 
235 #define INIT_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions) \
236 	{															\
237 		memset(&class_container, 0, sizeof(zend_class_entry)); \
238 		class_container.name = zend_string_init_interned(class_name, class_name_len, 1); \
239 		class_container.info.internal.builtin_functions = functions;	\
240 	}
241 
242 #define INIT_CLASS_ENTRY_INIT_METHODS(class_container, functions) \
243 	{															\
244 		class_container.constructor = NULL;						\
245 		class_container.destructor = NULL;						\
246 		class_container.clone = NULL;							\
247 		class_container.serialize = NULL;						\
248 		class_container.unserialize = NULL;						\
249 		class_container.create_object = NULL;					\
250 		class_container.get_static_method = NULL;				\
251 		class_container.__call = NULL;							\
252 		class_container.__callstatic = NULL;					\
253 		class_container.__tostring = NULL;						\
254 		class_container.__get = NULL;							\
255 		class_container.__set = NULL;							\
256 		class_container.__unset = NULL;							\
257 		class_container.__isset = NULL;							\
258 		class_container.__debugInfo = NULL;						\
259 		class_container.__serialize = NULL;						\
260 		class_container.__unserialize = NULL;					\
261 		class_container.parent = NULL;							\
262 		class_container.num_interfaces = 0;						\
263 		class_container.trait_names = NULL;						\
264 		class_container.num_traits = 0;							\
265 		class_container.trait_aliases = NULL;					\
266 		class_container.trait_precedences = NULL;				\
267 		class_container.interfaces = NULL;						\
268 		class_container.get_iterator = NULL;					\
269 		class_container.iterator_funcs_ptr = NULL;				\
270 		class_container.info.internal.module = NULL;			\
271 		class_container.info.internal.builtin_functions = functions;	\
272 	}
273 
274 
275 #define INIT_NS_CLASS_ENTRY(class_container, ns, class_name, functions) \
276 	INIT_CLASS_ENTRY(class_container, ZEND_NS_NAME(ns, class_name), functions)
277 
278 #define CE_STATIC_MEMBERS(ce) \
279 	((zval*)ZEND_MAP_PTR_GET((ce)->static_members_table))
280 
281 #define ZEND_FCI_INITIALIZED(fci) ((fci).size != 0)
282 
283 ZEND_API int zend_next_free_module(void);
284 
285 BEGIN_EXTERN_C()
286 ZEND_API zend_result _zend_get_parameters_array_ex(uint32_t param_count, zval *argument_array);
287 
288 /* internal function to efficiently copy parameters when executing __call() */
289 ZEND_API zend_result zend_copy_parameters_array(uint32_t param_count, zval *argument_array);
290 
291 #define zend_get_parameters_array(ht, param_count, argument_array) \
292 	_zend_get_parameters_array_ex(param_count, argument_array)
293 #define zend_get_parameters_array_ex(param_count, argument_array) \
294 	_zend_get_parameters_array_ex(param_count, argument_array)
295 #define zend_parse_parameters_none() \
296 	(EXPECTED(ZEND_NUM_ARGS() == 0) ? SUCCESS : (zend_wrong_parameters_none_error(), FAILURE))
297 #define zend_parse_parameters_none_throw() \
298 	zend_parse_parameters_none()
299 
300 /* Parameter parsing API -- andrei */
301 
302 #define ZEND_PARSE_PARAMS_THROW 0 /* No longer used, zpp always uses exceptions */
303 #define ZEND_PARSE_PARAMS_QUIET (1<<1)
304 ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec, ...);
305 ZEND_API zend_result zend_parse_parameters_ex(int flags, uint32_t num_args, const char *type_spec, ...);
306 /* NOTE: This must have at least one value in __VA_ARGS__ for the expression to be valid */
307 #define zend_parse_parameters_throw(num_args, ...) \
308 	zend_parse_parameters(num_args, __VA_ARGS__)
309 ZEND_API const char *zend_zval_type_name(const zval *arg);
310 ZEND_API zend_string *zend_zval_get_legacy_type(const zval *arg);
311 
312 ZEND_API zend_result zend_parse_method_parameters(uint32_t num_args, zval *this_ptr, const char *type_spec, ...);
313 ZEND_API zend_result zend_parse_method_parameters_ex(int flags, uint32_t num_args, zval *this_ptr, const char *type_spec, ...);
314 
315 ZEND_API zend_result zend_parse_parameter(int flags, uint32_t arg_num, zval *arg, const char *spec, ...);
316 
317 /* End of parameter parsing API -- andrei */
318 
319 ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type);
320 ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table);
321 ZEND_API zend_result zend_startup_module(zend_module_entry *module_entry);
322 ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module_entry);
323 ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module);
324 ZEND_API zend_result zend_startup_module_ex(zend_module_entry *module);
325 ZEND_API void zend_startup_modules(void);
326 ZEND_API void zend_collect_module_handlers(void);
327 ZEND_API void zend_destroy_modules(void);
328 ZEND_API void zend_check_magic_method_implementation(
329 		const zend_class_entry *ce, const zend_function *fptr, zend_string *lcname, int error_type);
330 ZEND_API void zend_add_magic_method(zend_class_entry *ce, zend_function *fptr, zend_string *lcname);
331 
332 ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *class_entry);
333 ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce);
334 ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry);
335 ZEND_API void zend_class_implements(zend_class_entry *class_entry, int num_interfaces, ...);
336 
337 ZEND_API zend_result zend_register_class_alias_ex(const char *name, size_t name_len, zend_class_entry *ce, bool persistent);
338 
339 #define zend_register_class_alias(name, ce) \
340 	zend_register_class_alias_ex(name, sizeof(name)-1, ce, 1)
341 #define zend_register_ns_class_alias(ns, name, ce) \
342 	zend_register_class_alias_ex(ZEND_NS_NAME(ns, name), sizeof(ZEND_NS_NAME(ns, name))-1, ce, 1)
343 
344 ZEND_API void zend_disable_functions(const char *function_list);
345 ZEND_API zend_result zend_disable_class(const char *class_name, size_t class_name_length);
346 
347 ZEND_API ZEND_COLD void zend_wrong_param_count(void);
348 
349 #define IS_CALLABLE_CHECK_SYNTAX_ONLY (1<<0)
350 #define IS_CALLABLE_CHECK_SILENT      (1<<3)
351 
352 ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc);
353 ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object);
354 ZEND_API zend_string *zend_get_callable_name(zval *callable);
355 ZEND_API zend_bool zend_is_callable_at_frame(
356 		zval *callable, zend_object *object, zend_execute_data *frame,
357 		uint32_t check_flags, zend_fcall_info_cache *fcc, char **error);
358 ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error);
359 ZEND_API zend_bool zend_is_callable(zval *callable, uint32_t check_flags, zend_string **callable_name);
360 ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_name);
361 ZEND_API const char *zend_get_module_version(const char *module_name);
362 ZEND_API int zend_get_module_started(const char *module_name);
363 
364 ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment, zend_type type);
365 
366 ZEND_API void zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment);
367 ZEND_API void zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type);
368 ZEND_API void zend_declare_property_null(zend_class_entry *ce, const char *name, size_t name_length, int access_type);
369 ZEND_API void zend_declare_property_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type);
370 ZEND_API void zend_declare_property_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type);
371 ZEND_API void zend_declare_property_double(zend_class_entry *ce, const char *name, size_t name_length, double value, int access_type);
372 ZEND_API void zend_declare_property_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value, int access_type);
373 ZEND_API void zend_declare_property_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_len, int access_type);
374 
375 ZEND_API zend_class_constant *zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int access_type, zend_string *doc_comment);
376 ZEND_API void zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value);
377 ZEND_API void zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length);
378 ZEND_API void zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value);
379 ZEND_API void zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value);
380 ZEND_API void zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value);
381 ZEND_API void zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length);
382 ZEND_API void zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value);
383 
384 ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type);
385 
386 ZEND_API void zend_update_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, zval *value);
387 ZEND_API void zend_update_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zval *value);
388 ZEND_API void zend_update_property_null(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length);
389 ZEND_API void zend_update_property_bool(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value);
390 ZEND_API void zend_update_property_long(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value);
391 ZEND_API void zend_update_property_double(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, double value);
392 ZEND_API void zend_update_property_str(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_string *value);
393 ZEND_API void zend_update_property_string(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value);
394 ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value, size_t value_length);
395 ZEND_API void zend_unset_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length);
396 
397 ZEND_API zend_result zend_update_static_property_ex(zend_class_entry *scope, zend_string *name, zval *value);
398 ZEND_API zend_result zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value);
399 ZEND_API zend_result zend_update_static_property_null(zend_class_entry *scope, const char *name, size_t name_length);
400 ZEND_API zend_result zend_update_static_property_bool(zend_class_entry *scope, const char *name, size_t name_length, zend_long value);
401 ZEND_API zend_result zend_update_static_property_long(zend_class_entry *scope, const char *name, size_t name_length, zend_long value);
402 ZEND_API zend_result zend_update_static_property_double(zend_class_entry *scope, const char *name, size_t name_length, double value);
403 ZEND_API zend_result zend_update_static_property_string(zend_class_entry *scope, const char *name, size_t name_length, const char *value);
404 ZEND_API zend_result zend_update_static_property_stringl(zend_class_entry *scope, const char *name, size_t name_length, const char *value, size_t value_length);
405 
406 ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, zend_bool silent, zval *rv);
407 ZEND_API zval *zend_read_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_bool silent, zval *rv);
408 
409 ZEND_API zval *zend_read_static_property_ex(zend_class_entry *scope, zend_string *name, zend_bool silent);
410 ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, zend_bool silent);
411 
412 ZEND_API const char *zend_get_type_by_const(int type);
413 
414 #define ZEND_THIS                           (&EX(This))
415 
416 #define getThis()							((Z_TYPE_P(ZEND_THIS) == IS_OBJECT) ? ZEND_THIS : NULL)
417 #define ZEND_IS_METHOD_CALL()				(EX(func)->common.scope != NULL)
418 
419 #define WRONG_PARAM_COUNT					ZEND_WRONG_PARAM_COUNT()
420 #define WRONG_PARAM_COUNT_WITH_RETVAL(ret)	ZEND_WRONG_PARAM_COUNT_WITH_RETVAL(ret)
421 #define ZEND_NUM_ARGS()						EX_NUM_ARGS()
422 #define ZEND_WRONG_PARAM_COUNT()					{ zend_wrong_param_count(); return; }
423 #define ZEND_WRONG_PARAM_COUNT_WITH_RETVAL(ret)		{ zend_wrong_param_count(); return ret; }
424 
425 #ifndef ZEND_WIN32
426 #define DLEXPORT
427 #endif
428 
429 #define array_init(arg)				ZVAL_ARR((arg), zend_new_array(0))
430 #define array_init_size(arg, size)	ZVAL_ARR((arg), zend_new_array(size))
431 ZEND_API void object_init(zval *arg);
432 ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *ce);
433 ZEND_API zend_result object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties);
434 ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type);
435 ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properties);
436 ZEND_API void object_properties_load(zend_object *object, HashTable *properties);
437 
438 ZEND_API void zend_merge_properties(zval *obj, HashTable *properties);
439 
440 ZEND_API void add_assoc_long_ex(zval *arg, const char *key, size_t key_len, zend_long n);
441 ZEND_API void add_assoc_null_ex(zval *arg, const char *key, size_t key_len);
442 ZEND_API void add_assoc_bool_ex(zval *arg, const char *key, size_t key_len, bool b);
443 ZEND_API void add_assoc_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r);
444 ZEND_API void add_assoc_double_ex(zval *arg, const char *key, size_t key_len, double d);
445 ZEND_API void add_assoc_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str);
446 ZEND_API void add_assoc_string_ex(zval *arg, const char *key, size_t key_len, const char *str);
447 ZEND_API void add_assoc_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length);
448 ZEND_API void add_assoc_zval_ex(zval *arg, const char *key, size_t key_len, zval *value);
449 
450 #define add_assoc_long(__arg, __key, __n) add_assoc_long_ex(__arg, __key, strlen(__key), __n)
451 #define add_assoc_null(__arg, __key) add_assoc_null_ex(__arg, __key, strlen(__key))
452 #define add_assoc_bool(__arg, __key, __b) add_assoc_bool_ex(__arg, __key, strlen(__key), __b)
453 #define add_assoc_resource(__arg, __key, __r) add_assoc_resource_ex(__arg, __key, strlen(__key), __r)
454 #define add_assoc_double(__arg, __key, __d) add_assoc_double_ex(__arg, __key, strlen(__key), __d)
455 #define add_assoc_str(__arg, __key, __str) add_assoc_str_ex(__arg, __key, strlen(__key), __str)
456 #define add_assoc_string(__arg, __key, __str) add_assoc_string_ex(__arg, __key, strlen(__key), __str)
457 #define add_assoc_stringl(__arg, __key, __str, __length) add_assoc_stringl_ex(__arg, __key, strlen(__key), __str, __length)
458 #define add_assoc_zval(__arg, __key, __value) add_assoc_zval_ex(__arg, __key, strlen(__key), __value)
459 
460 ZEND_API void add_index_long(zval *arg, zend_ulong index, zend_long n);
461 ZEND_API void add_index_null(zval *arg, zend_ulong index);
462 ZEND_API void add_index_bool(zval *arg, zend_ulong index, bool b);
463 ZEND_API void add_index_resource(zval *arg, zend_ulong index, zend_resource *r);
464 ZEND_API void add_index_double(zval *arg, zend_ulong index, double d);
465 ZEND_API void add_index_str(zval *arg, zend_ulong index, zend_string *str);
466 ZEND_API void add_index_string(zval *arg, zend_ulong index, const char *str);
467 ZEND_API void add_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length);
468 
add_index_zval(zval * arg,zend_ulong index,zval * value)469 static zend_always_inline zend_result add_index_zval(zval *arg, zend_ulong index, zval *value)
470 {
471 	return zend_hash_index_update(Z_ARRVAL_P(arg), index, value) ? SUCCESS : FAILURE;
472 }
473 
474 ZEND_API zend_result add_next_index_long(zval *arg, zend_long n);
475 ZEND_API zend_result add_next_index_null(zval *arg);
476 ZEND_API zend_result add_next_index_bool(zval *arg, zend_bool b);
477 ZEND_API zend_result add_next_index_resource(zval *arg, zend_resource *r);
478 ZEND_API zend_result add_next_index_double(zval *arg, double d);
479 ZEND_API zend_result add_next_index_str(zval *arg, zend_string *str);
480 ZEND_API zend_result add_next_index_string(zval *arg, const char *str);
481 ZEND_API zend_result add_next_index_stringl(zval *arg, const char *str, size_t length);
482 
add_next_index_zval(zval * arg,zval * value)483 static zend_always_inline zend_result add_next_index_zval(zval *arg, zval *value)
484 {
485 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), value) ? SUCCESS : FAILURE;
486 }
487 
488 ZEND_API zend_result array_set_zval_key(HashTable *ht, zval *key, zval *value);
489 
490 ZEND_API void add_property_long_ex(zval *arg, const char *key, size_t key_len, zend_long l);
491 ZEND_API void add_property_null_ex(zval *arg, const char *key, size_t key_len);
492 ZEND_API void add_property_bool_ex(zval *arg, const char *key, size_t key_len, zend_long b);
493 ZEND_API void add_property_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r);
494 ZEND_API void add_property_double_ex(zval *arg, const char *key, size_t key_len, double d);
495 ZEND_API void add_property_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str);
496 ZEND_API void add_property_string_ex(zval *arg, const char *key, size_t key_len, const char *str);
497 ZEND_API void add_property_stringl_ex(zval *arg, const char *key, size_t key_len,  const char *str, size_t length);
498 ZEND_API void add_property_zval_ex(zval *arg, const char *key, size_t key_len, zval *value);
499 
500 #define add_property_long(__arg, __key, __n) add_property_long_ex(__arg, __key, strlen(__key), __n)
501 #define add_property_null(__arg, __key) add_property_null_ex(__arg, __key, strlen(__key))
502 #define add_property_bool(__arg, __key, __b) add_property_bool_ex(__arg, __key, strlen(__key), __b)
503 #define add_property_resource(__arg, __key, __r) add_property_resource_ex(__arg, __key, strlen(__key), __r)
504 #define add_property_double(__arg, __key, __d) add_property_double_ex(__arg, __key, strlen(__key), __d)
505 #define add_property_str(__arg, __key, __str) add_property_str_ex(__arg, __key, strlen(__key), __str)
506 #define add_property_string(__arg, __key, __str) add_property_string_ex(__arg, __key, strlen(__key), __str)
507 #define add_property_stringl(__arg, __key, __str, __length) add_property_stringl_ex(__arg, __key, strlen(__key), __str, __length)
508 #define add_property_zval(__arg, __key, __value) add_property_zval_ex(__arg, __key, strlen(__key), __value)
509 
510 
511 ZEND_API zend_result _call_user_function_impl(zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], HashTable *named_params);
512 
513 #define call_user_function(function_table, object, function_name, retval_ptr, param_count, params) \
514 	_call_user_function_impl(object, function_name, retval_ptr, param_count, params, NULL)
515 
516 #define call_user_function_named(function_table, object, function_name, retval_ptr, param_count, params, named_params) \
517 	_call_user_function_impl(object, function_name, retval_ptr, param_count, params, named_params)
518 
519 ZEND_API extern const zend_fcall_info empty_fcall_info;
520 ZEND_API extern const zend_fcall_info_cache empty_fcall_info_cache;
521 
522 /** Build zend_call_info/cache from a zval*
523  *
524  * Caller is responsible to provide a return value (fci->retval), otherwise the we will crash.
525  * In order to pass parameters the following members need to be set:
526  * fci->param_count = 0;
527  * fci->params = NULL;
528  * The callable_name argument may be NULL.
529  */
530 ZEND_API zend_result zend_fcall_info_init(zval *callable, uint32_t check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string **callable_name, char **error);
531 
532 /** Clear arguments connected with zend_fcall_info *fci
533  * If free_mem is not zero then the params array gets free'd as well
534  */
535 ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, bool free_mem);
536 
537 /** Save current arguments from zend_fcall_info *fci
538  * params array will be set to NULL
539  */
540 ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, uint32_t *param_count, zval **params);
541 
542 /** Free arguments connected with zend_fcall_info *fci andset back saved ones.
543  */
544 ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, uint32_t param_count, zval *params);
545 
546 /** Set or clear the arguments in the zend_call_info struct taking care of
547  * refcount. If args is NULL and arguments are set then those are cleared.
548  */
549 ZEND_API zend_result zend_fcall_info_args(zend_fcall_info *fci, zval *args);
550 ZEND_API zend_result zend_fcall_info_args_ex(zend_fcall_info *fci, zend_function *func, zval *args);
551 
552 /** Set arguments in the zend_fcall_info struct taking care of refcount.
553  * If argc is 0 the arguments which are set will be cleared, else pass
554  * a variable amount of zval** arguments.
555  */
556 ZEND_API void zend_fcall_info_argp(zend_fcall_info *fci, uint32_t argc, zval *argv);
557 
558 /** Set arguments in the zend_fcall_info struct taking care of refcount.
559  * If argc is 0 the arguments which are set will be cleared, else pass
560  * a variable amount of zval** arguments.
561  */
562 ZEND_API void zend_fcall_info_argv(zend_fcall_info *fci, uint32_t argc, va_list *argv);
563 
564 /** Set arguments in the zend_fcall_info struct taking care of refcount.
565  * If argc is 0 the arguments which are set will be cleared, else pass
566  * a variable amount of zval** arguments.
567  */
568 ZEND_API void zend_fcall_info_argn(zend_fcall_info *fci, uint32_t argc, ...);
569 
570 /** Call a function using information created by zend_fcall_info_init()/args().
571  * If args is given then those replace the argument info in fci is temporarily.
572  */
573 ZEND_API zend_result zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *retval, zval *args);
574 
575 ZEND_API zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache);
576 
577 /* Call the provided zend_function with the given params.
578  * If retval_ptr is NULL, the return value is discarded.
579  * If object is NULL, this must be a free function or static call.
580  * called_scope must be provided for instance and static method calls. */
581 ZEND_API void zend_call_known_function(
582 		zend_function *fn, zend_object *object, zend_class_entry *called_scope, zval *retval_ptr,
583 		uint32_t param_count, zval *params, HashTable *named_params);
584 
585 /* Call the provided zend_function instance method on an object. */
zend_call_known_instance_method(zend_function * fn,zend_object * object,zval * retval_ptr,uint32_t param_count,zval * params)586 static zend_always_inline void zend_call_known_instance_method(
587 		zend_function *fn, zend_object *object, zval *retval_ptr,
588 		uint32_t param_count, zval *params)
589 {
590 	zend_call_known_function(fn, object, object->ce, retval_ptr, param_count, params, NULL);
591 }
592 
zend_call_known_instance_method_with_0_params(zend_function * fn,zend_object * object,zval * retval_ptr)593 static zend_always_inline void zend_call_known_instance_method_with_0_params(
594 		zend_function *fn, zend_object *object, zval *retval_ptr)
595 {
596 	zend_call_known_instance_method(fn, object, retval_ptr, 0, NULL);
597 }
598 
zend_call_known_instance_method_with_1_params(zend_function * fn,zend_object * object,zval * retval_ptr,zval * param)599 static zend_always_inline void zend_call_known_instance_method_with_1_params(
600 		zend_function *fn, zend_object *object, zval *retval_ptr, zval *param)
601 {
602 	zend_call_known_instance_method(fn, object, retval_ptr, 1, param);
603 }
604 
605 ZEND_API void zend_call_known_instance_method_with_2_params(
606 		zend_function *fn, zend_object *object, zval *retval_ptr, zval *param1, zval *param2);
607 
608 ZEND_API zend_result zend_set_hash_symbol(zval *symbol, const char *name, size_t name_length, zend_bool is_ref, int num_symbol_tables, ...);
609 
610 ZEND_API zend_result zend_delete_global_variable(zend_string *name);
611 
612 ZEND_API zend_array *zend_rebuild_symbol_table(void);
613 ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data);
614 ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data);
615 ZEND_API zend_result zend_set_local_var(zend_string *name, zval *value, bool force);
616 ZEND_API zend_result zend_set_local_var_str(const char *name, size_t len, zval *value, bool force);
617 
zend_forbid_dynamic_call(const char * func_name)618 static zend_always_inline zend_result zend_forbid_dynamic_call(const char *func_name)
619 {
620 	zend_execute_data *ex = EG(current_execute_data);
621 	ZEND_ASSERT(ex != NULL && ex->func != NULL);
622 
623 	if (ZEND_CALL_INFO(ex) & ZEND_CALL_DYNAMIC) {
624 		zend_throw_error(NULL, "Cannot call %s dynamically", func_name);
625 		return FAILURE;
626 	}
627 
628 	return SUCCESS;
629 }
630 
631 ZEND_API ZEND_COLD const char *zend_get_object_type(const zend_class_entry *ce);
632 
633 ZEND_API zend_bool zend_is_iterable(zval *iterable);
634 
635 ZEND_API zend_bool zend_is_countable(zval *countable);
636 
637 ZEND_API zend_result zend_get_default_from_internal_arg_info(
638 		zval *default_value_zval, zend_internal_arg_info *arg_info);
639 
640 END_EXTERN_C()
641 
642 #if ZEND_DEBUG
643 #define CHECK_ZVAL_STRING(str) \
644 	ZEND_ASSERT(ZSTR_VAL(str)[ZSTR_LEN(str)] == '\0' && "String is not null-terminated");
645 #else
646 #define CHECK_ZVAL_STRING(z)
647 #endif
648 
649 #define CHECK_ZVAL_NULL_PATH(p) (Z_STRLEN_P(p) != strlen(Z_STRVAL_P(p)))
650 #define CHECK_NULL_PATH(p, l) (strlen(p) != (size_t)(l))
651 
652 #define ZVAL_STRINGL(z, s, l) do {				\
653 		ZVAL_NEW_STR(z, zend_string_init(s, l, 0));		\
654 	} while (0)
655 
656 #define ZVAL_STRING(z, s) do {					\
657 		const char *_s = (s);					\
658 		ZVAL_STRINGL(z, _s, strlen(_s));		\
659 	} while (0)
660 
661 #define ZVAL_EMPTY_STRING(z) do {				\
662 		ZVAL_INTERNED_STR(z, ZSTR_EMPTY_ALLOC());		\
663 	} while (0)
664 
665 #define ZVAL_PSTRINGL(z, s, l) do {				\
666 		ZVAL_NEW_STR(z, zend_string_init(s, l, 1));		\
667 	} while (0)
668 
669 #define ZVAL_PSTRING(z, s) do {					\
670 		const char *_s = (s);					\
671 		ZVAL_PSTRINGL(z, _s, strlen(_s));		\
672 	} while (0)
673 
674 #define ZVAL_EMPTY_PSTRING(z) do {				\
675 		ZVAL_PSTRINGL(z, "", 0);				\
676 	} while (0)
677 
678 #define ZVAL_CHAR(z, c)  do {		            \
679 		char _c = (c);                          \
680 		ZVAL_INTERNED_STR(z, ZSTR_CHAR((zend_uchar) _c));	\
681 	} while (0)
682 
683 #define ZVAL_STRINGL_FAST(z, s, l) do {			\
684 		ZVAL_STR(z, zend_string_init_fast(s, l));	\
685 	} while (0)
686 
687 #define ZVAL_STRING_FAST(z, s) do {				\
688 		const char *_s = (s);					\
689 		ZVAL_STRINGL_FAST(z, _s, strlen(_s));	\
690 	} while (0)
691 
692 #define ZVAL_ZVAL(z, zv, copy, dtor) do {		\
693 		zval *__z = (z);						\
694 		zval *__zv = (zv);						\
695 		if (EXPECTED(!Z_ISREF_P(__zv))) {		\
696 			if (copy && !dtor) {				\
697 				ZVAL_COPY(__z, __zv);			\
698 			} else {							\
699 				ZVAL_COPY_VALUE(__z, __zv);		\
700 			}									\
701 		} else {								\
702 			ZVAL_COPY(__z, Z_REFVAL_P(__zv));	\
703 			if (dtor || !copy) {				\
704 				zval_ptr_dtor(__zv);			\
705 			}									\
706 		}										\
707 	} while (0)
708 
709 #define RETVAL_BOOL(b)					ZVAL_BOOL(return_value, b)
710 #define RETVAL_NULL()					ZVAL_NULL(return_value)
711 #define RETVAL_LONG(l)					ZVAL_LONG(return_value, l)
712 #define RETVAL_DOUBLE(d)				ZVAL_DOUBLE(return_value, d)
713 #define RETVAL_STR(s)					ZVAL_STR(return_value, s)
714 #define RETVAL_INTERNED_STR(s)			ZVAL_INTERNED_STR(return_value, s)
715 #define RETVAL_NEW_STR(s)				ZVAL_NEW_STR(return_value, s)
716 #define RETVAL_STR_COPY(s)				ZVAL_STR_COPY(return_value, s)
717 #define RETVAL_STRING(s)				ZVAL_STRING(return_value, s)
718 #define RETVAL_STRINGL(s, l)			ZVAL_STRINGL(return_value, s, l)
719 #define RETVAL_STRING_FAST(s)			ZVAL_STRING_FAST(return_value, s)
720 #define RETVAL_STRINGL_FAST(s, l)		ZVAL_STRINGL_FAST(return_value, s, l)
721 #define RETVAL_EMPTY_STRING()			ZVAL_EMPTY_STRING(return_value)
722 #define RETVAL_CHAR(c)		            ZVAL_CHAR(return_value, c)
723 #define RETVAL_RES(r)					ZVAL_RES(return_value, r)
724 #define RETVAL_ARR(r)					ZVAL_ARR(return_value, r)
725 #define RETVAL_EMPTY_ARRAY()			ZVAL_EMPTY_ARRAY(return_value)
726 #define RETVAL_OBJ(r)					ZVAL_OBJ(return_value, r)
727 #define RETVAL_OBJ_COPY(r)				ZVAL_OBJ_COPY(return_value, r)
728 #define RETVAL_COPY(zv)					ZVAL_COPY(return_value, zv)
729 #define RETVAL_COPY_VALUE(zv)			ZVAL_COPY_VALUE(return_value, zv)
730 #define RETVAL_ZVAL(zv, copy, dtor)		ZVAL_ZVAL(return_value, zv, copy, dtor)
731 #define RETVAL_FALSE					ZVAL_FALSE(return_value)
732 #define RETVAL_TRUE						ZVAL_TRUE(return_value)
733 
734 #define RETURN_BOOL(b)					do { RETVAL_BOOL(b); return; } while (0)
735 #define RETURN_NULL()					do { RETVAL_NULL(); return;} while (0)
736 #define RETURN_LONG(l)					do { RETVAL_LONG(l); return; } while (0)
737 #define RETURN_DOUBLE(d)				do { RETVAL_DOUBLE(d); return; } while (0)
738 #define RETURN_STR(s) 					do { RETVAL_STR(s); return; } while (0)
739 #define RETURN_INTERNED_STR(s)			do { RETVAL_INTERNED_STR(s); return; } while (0)
740 #define RETURN_NEW_STR(s)				do { RETVAL_NEW_STR(s); return; } while (0)
741 #define RETURN_STR_COPY(s)				do { RETVAL_STR_COPY(s); return; } while (0)
742 #define RETURN_STRING(s) 				do { RETVAL_STRING(s); return; } while (0)
743 #define RETURN_STRINGL(s, l) 			do { RETVAL_STRINGL(s, l); return; } while (0)
744 #define RETURN_STRING_FAST(s) 			do { RETVAL_STRING_FAST(s); return; } while (0)
745 #define RETURN_STRINGL_FAST(s, l)		do { RETVAL_STRINGL_FAST(s, l); return; } while (0)
746 #define RETURN_EMPTY_STRING() 			do { RETVAL_EMPTY_STRING(); return; } while (0)
747 #define RETURN_CHAR(c)		            do { RETVAL_CHAR(c); return; } while (0)
748 #define RETURN_RES(r)					do { RETVAL_RES(r); return; } while (0)
749 #define RETURN_ARR(r)					do { RETVAL_ARR(r); return; } while (0)
750 #define RETURN_EMPTY_ARRAY()			do { RETVAL_EMPTY_ARRAY(); return; } while (0)
751 #define RETURN_OBJ(r)					do { RETVAL_OBJ(r); return; } while (0)
752 #define RETURN_OBJ_COPY(r)				do { RETVAL_OBJ_COPY(r); return; } while (0)
753 #define RETURN_COPY(zv)					do { RETVAL_COPY(zv); return; } while (0)
754 #define RETURN_COPY_VALUE(zv)			do { RETVAL_COPY_VALUE(zv); return; } while (0)
755 #define RETURN_ZVAL(zv, copy, dtor)		do { RETVAL_ZVAL(zv, copy, dtor); return; } while (0)
756 #define RETURN_FALSE					do { RETVAL_FALSE; return; } while (0)
757 #define RETURN_TRUE						do { RETVAL_TRUE; return; } while (0)
758 #define RETURN_THROWS()					do { ZEND_ASSERT(EG(exception)); (void) return_value; return; } while (0)
759 
760 #define HASH_OF(p) (Z_TYPE_P(p)==IS_ARRAY ? Z_ARRVAL_P(p) : ((Z_TYPE_P(p)==IS_OBJECT ? Z_OBJ_HT_P(p)->get_properties(Z_OBJ_P(p)) : NULL)))
761 #define ZVAL_IS_NULL(z) (Z_TYPE_P(z) == IS_NULL)
762 
763 /* For compatibility */
764 #define ZEND_MINIT			ZEND_MODULE_STARTUP_N
765 #define ZEND_MSHUTDOWN		ZEND_MODULE_SHUTDOWN_N
766 #define ZEND_RINIT			ZEND_MODULE_ACTIVATE_N
767 #define ZEND_RSHUTDOWN		ZEND_MODULE_DEACTIVATE_N
768 #define ZEND_MINFO			ZEND_MODULE_INFO_N
769 #define ZEND_GINIT(module)		((void (*)(void*))(ZEND_MODULE_GLOBALS_CTOR_N(module)))
770 #define ZEND_GSHUTDOWN(module)	((void (*)(void*))(ZEND_MODULE_GLOBALS_DTOR_N(module)))
771 
772 #define ZEND_MINIT_FUNCTION			ZEND_MODULE_STARTUP_D
773 #define ZEND_MSHUTDOWN_FUNCTION		ZEND_MODULE_SHUTDOWN_D
774 #define ZEND_RINIT_FUNCTION			ZEND_MODULE_ACTIVATE_D
775 #define ZEND_RSHUTDOWN_FUNCTION		ZEND_MODULE_DEACTIVATE_D
776 #define ZEND_MINFO_FUNCTION			ZEND_MODULE_INFO_D
777 #define ZEND_GINIT_FUNCTION			ZEND_MODULE_GLOBALS_CTOR_D
778 #define ZEND_GSHUTDOWN_FUNCTION		ZEND_MODULE_GLOBALS_DTOR_D
779 
780 /* May modify arg in-place. Will free arg in failure case (and take ownership in success case).
781  * Prefer using the ZEND_TRY_ASSIGN_* macros over these APIs. */
782 ZEND_API zend_result zend_try_assign_typed_ref_ex(zend_reference *ref, zval *zv, zend_bool strict);
783 ZEND_API zend_result zend_try_assign_typed_ref(zend_reference *ref, zval *zv);
784 
785 ZEND_API zend_result zend_try_assign_typed_ref_null(zend_reference *ref);
786 ZEND_API zend_result zend_try_assign_typed_ref_bool(zend_reference *ref, zend_bool val);
787 ZEND_API zend_result zend_try_assign_typed_ref_long(zend_reference *ref, zend_long lval);
788 ZEND_API zend_result zend_try_assign_typed_ref_double(zend_reference *ref, double dval);
789 ZEND_API zend_result zend_try_assign_typed_ref_empty_string(zend_reference *ref);
790 ZEND_API zend_result zend_try_assign_typed_ref_str(zend_reference *ref, zend_string *str);
791 ZEND_API zend_result zend_try_assign_typed_ref_string(zend_reference *ref, const char *string);
792 ZEND_API zend_result zend_try_assign_typed_ref_stringl(zend_reference *ref, const char *string, size_t len);
793 ZEND_API zend_result zend_try_assign_typed_ref_arr(zend_reference *ref, zend_array *arr);
794 ZEND_API zend_result zend_try_assign_typed_ref_res(zend_reference *ref, zend_resource *res);
795 ZEND_API zend_result zend_try_assign_typed_ref_zval(zend_reference *ref, zval *zv);
796 ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval *zv, zend_bool strict);
797 
798 #define _ZEND_TRY_ASSIGN_NULL(zv, is_ref) do { \
799 	zval *_zv = zv; \
800 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
801 		zend_reference *ref = Z_REF_P(_zv); \
802 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
803 			zend_try_assign_typed_ref_null(ref); \
804 			break; \
805 		} \
806 		_zv = &ref->val; \
807 	} \
808 	zval_ptr_dtor(_zv); \
809 	ZVAL_NULL(_zv); \
810 } while (0)
811 
812 #define ZEND_TRY_ASSIGN_NULL(zv) \
813 	_ZEND_TRY_ASSIGN_NULL(zv, 0)
814 
815 #define ZEND_TRY_ASSIGN_REF_NULL(zv) do { \
816 	ZEND_ASSERT(Z_ISREF_P(zv)); \
817 	_ZEND_TRY_ASSIGN_NULL(zv, 1); \
818 } while (0)
819 
820 #define _ZEND_TRY_ASSIGN_FALSE(zv, is_ref) do { \
821 	zval *_zv = zv; \
822 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
823 		zend_reference *ref = Z_REF_P(_zv); \
824 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
825 			zend_try_assign_typed_ref_bool(ref, 0); \
826 			break; \
827 		} \
828 		_zv = &ref->val; \
829 	} \
830 	zval_ptr_dtor(_zv); \
831 	ZVAL_FALSE(_zv); \
832 } while (0)
833 
834 #define ZEND_TRY_ASSIGN_FALSE(zv) \
835 	_ZEND_TRY_ASSIGN_FALSE(zv, 0)
836 
837 #define ZEND_TRY_ASSIGN_REF_FALSE(zv) do { \
838 	ZEND_ASSERT(Z_ISREF_P(zv)); \
839 	_ZEND_TRY_ASSIGN_FALSE(zv, 1); \
840 } while (0)
841 
842 #define _ZEND_TRY_ASSIGN_TRUE(zv, is_ref) do { \
843 	zval *_zv = zv; \
844 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
845 		zend_reference *ref = Z_REF_P(_zv); \
846 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
847 			zend_try_assign_typed_ref_bool(ref, 1); \
848 			break; \
849 		} \
850 		_zv = &ref->val; \
851 	} \
852 	zval_ptr_dtor(_zv); \
853 	ZVAL_TRUE(_zv); \
854 } while (0)
855 
856 #define ZEND_TRY_ASSIGN_TRUE(zv) \
857 	_ZEND_TRY_ASSIGN_TRUE(zv, 0)
858 
859 #define ZEND_TRY_ASSIGN_REF_TRUE(zv) do { \
860 	ZEND_ASSERT(Z_ISREF_P(zv)); \
861 	_ZEND_TRY_ASSIGN_TRUE(zv, 1); \
862 } while (0)
863 
864 #define _ZEND_TRY_ASSIGN_BOOL(zv, bval, is_ref) do { \
865 	zval *_zv = zv; \
866 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
867 		zend_reference *ref = Z_REF_P(_zv); \
868 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
869 			zend_try_assign_typed_ref_bool(ref, 1); \
870 			break; \
871 		} \
872 		_zv = &ref->val; \
873 	} \
874 	zval_ptr_dtor(_zv); \
875 	ZVAL_BOOL(_zv, bval); \
876 } while (0)
877 
878 #define ZEND_TRY_ASSIGN_BOOL(zv, bval) \
879 	_ZEND_TRY_ASSIGN_BOOL(zv, bval, 0)
880 
881 #define ZEND_TRY_ASSIGN_REF_BOOL(zv, bval) do { \
882 	ZEND_ASSERT(Z_ISREF_P(zv)); \
883 	_ZEND_TRY_ASSIGN_BOOL(zv, bval, 1); \
884 } while (0)
885 
886 #define _ZEND_TRY_ASSIGN_LONG(zv, lval, is_ref) do { \
887 	zval *_zv = zv; \
888 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
889 		zend_reference *ref = Z_REF_P(_zv); \
890 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
891 			zend_try_assign_typed_ref_long(ref, lval); \
892 			break; \
893 		} \
894 		_zv = &ref->val; \
895 	} \
896 	zval_ptr_dtor(_zv); \
897 	ZVAL_LONG(_zv, lval); \
898 } while (0)
899 
900 #define ZEND_TRY_ASSIGN_LONG(zv, lval) \
901 	_ZEND_TRY_ASSIGN_LONG(zv, lval, 0)
902 
903 #define ZEND_TRY_ASSIGN_REF_LONG(zv, lval) do { \
904 	ZEND_ASSERT(Z_ISREF_P(zv)); \
905 	_ZEND_TRY_ASSIGN_LONG(zv, lval, 1); \
906 } while (0)
907 
908 #define _ZEND_TRY_ASSIGN_DOUBLE(zv, dval, is_ref) do { \
909 	zval *_zv = zv; \
910 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
911 		zend_reference *ref = Z_REF_P(_zv); \
912 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
913 			zend_try_assign_typed_ref_double(ref, dval); \
914 			break; \
915 		} \
916 		_zv = &ref->val; \
917 	} \
918 	zval_ptr_dtor(_zv); \
919 	ZVAL_DOUBLE(_zv, dval); \
920 } while (0)
921 
922 #define ZEND_TRY_ASSIGN_DOUBLE(zv, dval) \
923 	_ZEND_TRY_ASSIGN_DOUBLE(zv, dval, 0)
924 
925 #define ZEND_TRY_ASSIGN_REF_DOUBLE(zv, dval) do { \
926 	ZEND_ASSERT(Z_ISREF_P(zv)); \
927 	_ZEND_TRY_ASSIGN_DOUBLE(zv, dval, 1); \
928 } while (0)
929 
930 #define _ZEND_TRY_ASSIGN_EMPTY_STRING(zv, is_ref) do { \
931 	zval *_zv = zv; \
932 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
933 		zend_reference *ref = Z_REF_P(_zv); \
934 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
935 			zend_try_assign_typed_ref_empty_string(ref); \
936 			break; \
937 		} \
938 		_zv = &ref->val; \
939 	} \
940 	zval_ptr_dtor(_zv); \
941 	ZVAL_EMPTY_STRING(_zv); \
942 } while (0)
943 
944 #define ZEND_TRY_ASSIGN_EMPTY_STRING(zv) \
945 	_ZEND_TRY_ASSIGN_EMPTY_STRING(zv, 0)
946 
947 #define ZEND_TRY_ASSIGN_REF_EMPTY_STRING(zv) do { \
948 	ZEND_ASSERT(Z_ISREF_P(zv)); \
949 	_ZEND_TRY_ASSIGN_EMPTY_STRING(zv, 1); \
950 } while (0)
951 
952 #define _ZEND_TRY_ASSIGN_STR(zv, str, is_ref) do { \
953 	zval *_zv = zv; \
954 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
955 		zend_reference *ref = Z_REF_P(_zv); \
956 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
957 			zend_try_assign_typed_ref_str(ref, str); \
958 			break; \
959 		} \
960 		_zv = &ref->val; \
961 	} \
962 	zval_ptr_dtor(_zv); \
963 	ZVAL_STR(_zv, str); \
964 } while (0)
965 
966 #define ZEND_TRY_ASSIGN_STR(zv, str) \
967 	_ZEND_TRY_ASSIGN_STR(zv, str, 0)
968 
969 #define ZEND_TRY_ASSIGN_REF_STR(zv, str) do { \
970 	ZEND_ASSERT(Z_ISREF_P(zv)); \
971 	_ZEND_TRY_ASSIGN_STR(zv, str, 1); \
972 } while (0)
973 
974 #define _ZEND_TRY_ASSIGN_NEW_STR(zv, str, is_str) do { \
975 	zval *_zv = zv; \
976 	if (is_str || UNEXPECTED(Z_ISREF_P(_zv))) { \
977 		zend_reference *ref = Z_REF_P(_zv); \
978 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
979 			zend_try_assign_typed_ref_str(ref, str); \
980 			break; \
981 		} \
982 		_zv = &ref->val; \
983 	} \
984 	zval_ptr_dtor(_zv); \
985 	ZVAL_NEW_STR(_zv, str); \
986 } while (0)
987 
988 #define ZEND_TRY_ASSIGN_NEW_STR(zv, str) \
989 	_ZEND_TRY_ASSIGN_NEW_STR(zv, str, 0)
990 
991 #define ZEND_TRY_ASSIGN_REF_NEW_STR(zv, str) do { \
992 	ZEND_ASSERT(Z_ISREF_P(zv)); \
993 	_ZEND_TRY_ASSIGN_NEW_STR(zv, str, 1); \
994 } while (0)
995 
996 #define _ZEND_TRY_ASSIGN_STRING(zv, string, is_ref) do { \
997 	zval *_zv = zv; \
998 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
999 		zend_reference *ref = Z_REF_P(_zv); \
1000 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
1001 			zend_try_assign_typed_ref_string(ref, string); \
1002 			break; \
1003 		} \
1004 		_zv = &ref->val; \
1005 	} \
1006 	zval_ptr_dtor(_zv); \
1007 	ZVAL_STRING(_zv, string); \
1008 } while (0)
1009 
1010 #define ZEND_TRY_ASSIGN_STRING(zv, string) \
1011 	_ZEND_TRY_ASSIGN_STRING(zv, string, 0)
1012 
1013 #define ZEND_TRY_ASSIGN_REF_STRING(zv, string) do { \
1014 	ZEND_ASSERT(Z_ISREF_P(zv)); \
1015 	_ZEND_TRY_ASSIGN_STRING(zv, string, 1); \
1016 } while (0)
1017 
1018 #define _ZEND_TRY_ASSIGN_STRINGL(zv, string, len, is_ref) do { \
1019 	zval *_zv = zv; \
1020 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
1021 		zend_reference *ref = Z_REF_P(_zv); \
1022 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
1023 			zend_try_assign_typed_ref_stringl(ref, string, len); \
1024 			break; \
1025 		} \
1026 		_zv = &ref->val; \
1027 	} \
1028 	zval_ptr_dtor(_zv); \
1029 	ZVAL_STRINGL(_zv, string, len); \
1030 } while (0)
1031 
1032 #define ZEND_TRY_ASSIGN_STRINGL(zv, string, len) \
1033 	_ZEND_TRY_ASSIGN_STRINGL(zv, string, len, 0)
1034 
1035 #define ZEND_TRY_ASSIGN_REF_STRINGL(zv, string, len) do { \
1036 	ZEND_ASSERT(Z_ISREF_P(zv)); \
1037 	_ZEND_TRY_ASSIGN_STRINGL(zv, string, len, 1); \
1038 } while (0)
1039 
1040 #define _ZEND_TRY_ASSIGN_ARR(zv, arr, is_ref) do { \
1041 	zval *_zv = zv; \
1042 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
1043 		zend_reference *ref = Z_REF_P(_zv); \
1044 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
1045 			zend_try_assign_typed_ref_arr(ref, arr); \
1046 			break; \
1047 		} \
1048 		_zv = &ref->val; \
1049 	} \
1050 	zval_ptr_dtor(_zv); \
1051 	ZVAL_ARR(_zv, arr); \
1052 } while (0)
1053 
1054 #define ZEND_TRY_ASSIGN_ARR(zv, arr) \
1055 	_ZEND_TRY_ASSIGN_ARR(zv, arr, 0)
1056 
1057 #define ZEND_TRY_ASSIGN_REF_ARR(zv, arr) do { \
1058 	ZEND_ASSERT(Z_ISREF_P(zv)); \
1059 	_ZEND_TRY_ASSIGN_ARR(zv, arr, 1); \
1060 } while (0)
1061 
1062 #define _ZEND_TRY_ASSIGN_RES(zv, res, is_ref) do { \
1063 	zval *_zv = zv; \
1064 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
1065 		zend_reference *ref = Z_REF_P(_zv); \
1066 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
1067 			zend_try_assign_typed_ref_res(ref, res); \
1068 			break; \
1069 		} \
1070 		_zv = &ref->val; \
1071 	} \
1072 	zval_ptr_dtor(_zv); \
1073 	ZVAL_RES(_zv, res); \
1074 } while (0)
1075 
1076 #define ZEND_TRY_ASSIGN_RES(zv, res) \
1077 	_ZEND_TRY_ASSIGN_RES(zv, res, 0)
1078 
1079 #define ZEND_TRY_ASSIGN_REF_RES(zv, res) do { \
1080 	ZEND_ASSERT(Z_ISREF_P(zv)); \
1081 	_ZEND_TRY_ASSIGN_RES(zv, res, 1); \
1082 } while (0)
1083 
1084 #define _ZEND_TRY_ASSIGN_TMP(zv, other_zv, is_ref) do { \
1085 	zval *_zv = zv; \
1086 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
1087 		zend_reference *ref = Z_REF_P(_zv); \
1088 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
1089 			zend_try_assign_typed_ref(ref, other_zv); \
1090 			break; \
1091 		} \
1092 		_zv = &ref->val; \
1093 	} \
1094 	zval_ptr_dtor(_zv); \
1095 	ZVAL_COPY_VALUE(_zv, other_zv); \
1096 } while (0)
1097 
1098 #define ZEND_TRY_ASSIGN_TMP(zv, other_zv) \
1099 	_ZEND_TRY_ASSIGN_TMP(zv, other_zv, 0)
1100 
1101 #define ZEND_TRY_ASSIGN_REF_TMP(zv, other_zv) do { \
1102 	ZEND_ASSERT(Z_ISREF_P(zv)); \
1103 	_ZEND_TRY_ASSIGN_TMP(zv, other_zv, 1); \
1104 } while (0)
1105 
1106 #define _ZEND_TRY_ASSIGN_VALUE(zv, other_zv, is_ref) do { \
1107 	zval *_zv = zv; \
1108 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
1109 		zend_reference *ref = Z_REF_P(_zv); \
1110 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
1111 			zend_try_assign_typed_ref_zval(ref, other_zv); \
1112 			break; \
1113 		} \
1114 		_zv = &ref->val; \
1115 	} \
1116 	zval_ptr_dtor(_zv); \
1117 	ZVAL_COPY_VALUE(_zv, other_zv); \
1118 } while (0)
1119 
1120 #define ZEND_TRY_ASSIGN_VALUE(zv, other_zv) \
1121 	_ZEND_TRY_ASSIGN_VALUE(zv, other_zv, 0)
1122 
1123 #define ZEND_TRY_ASSIGN_REF_VALUE(zv, other_zv) do { \
1124 	ZEND_ASSERT(Z_ISREF_P(zv)); \
1125 	_ZEND_TRY_ASSIGN_VALUE(zv, other_zv, 1); \
1126 } while (0)
1127 
1128 #define ZEND_TRY_ASSIGN_COPY(zv, other_zv) do { \
1129 	Z_TRY_ADDREF_P(other_zv); \
1130 	ZEND_TRY_ASSIGN_VALUE(zv, other_zv); \
1131 } while (0)
1132 
1133 #define ZEND_TRY_ASSIGN_REF_COPY(zv, other_zv) do { \
1134 	Z_TRY_ADDREF_P(other_zv); \
1135 	ZEND_TRY_ASSIGN_REF_VALUE(zv, other_zv); \
1136 } while (0)
1137 
1138 #define _ZEND_TRY_ASSIGN_VALUE_EX(zv, other_zv, strict, is_ref) do { \
1139 	zval *_zv = zv; \
1140 	if (is_ref || UNEXPECTED(Z_ISREF_P(_zv))) { \
1141 		zend_reference *ref = Z_REF_P(_zv); \
1142 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { \
1143 			zend_try_assign_typed_ref_zval_ex(ref, other_zv, strict); \
1144 			break; \
1145 		} \
1146 		_zv = &ref->val; \
1147 	} \
1148 	zval_ptr_dtor(_zv); \
1149 	ZVAL_COPY_VALUE(_zv, other_zv); \
1150 } while (0)
1151 
1152 #define ZEND_TRY_ASSIGN_VALUE_EX(zv, other_zv, strict) \
1153 	_ZEND_TRY_ASSIGN_VALUE_EX(zv, other_zv, strict, 0)
1154 
1155 #define ZEND_TRY_ASSIGN_REF_VALUE_EX(zv, other_zv, strict) do { \
1156 	ZEND_ASSERT(Z_ISREF_P(zv)); \
1157 	_ZEND_TRY_ASSIGN_VALUE_EX(zv, other_zv, strict, 1); \
1158 } while (0)
1159 
1160 #define ZEND_TRY_ASSIGN_COPY_EX(zv, other_zv, strict) do { \
1161 	Z_TRY_ADDREF_P(other_zv); \
1162 	ZEND_TRY_ASSIGN_VALUE_EX(zv, other_zv, strict); \
1163 } while (0)
1164 
1165 #define ZEND_TRY_ASSIGN_REF_COPY_EX(zv, other_zv, strict) do { \
1166 	Z_TRY_ADDREF_P(other_zv); \
1167 	ZEND_TRY_ASSIGN_REF_VALUE_EX(zv, other_zv, strict); \
1168 } while (0)
1169 
1170 /* Initializes a reference to an empty array and returns dereferenced zval,
1171  * or NULL if the initialization failed. */
zend_try_array_init_size(zval * zv,uint32_t size)1172 static zend_always_inline zval *zend_try_array_init_size(zval *zv, uint32_t size)
1173 {
1174 	zend_array *arr = zend_new_array(size);
1175 
1176 	if (EXPECTED(Z_ISREF_P(zv))) {
1177 		zend_reference *ref = Z_REF_P(zv);
1178 		if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
1179 			if (zend_try_assign_typed_ref_arr(ref, arr) == FAILURE) {
1180 				return NULL;
1181 			}
1182 			return &ref->val;
1183 		}
1184 		zv = &ref->val;
1185 	}
1186 	zval_ptr_dtor(zv);
1187 	ZVAL_ARR(zv, arr);
1188 	return zv;
1189 }
1190 
zend_try_array_init(zval * zv)1191 static zend_always_inline zval *zend_try_array_init(zval *zv)
1192 {
1193 	return zend_try_array_init_size(zv, 0);
1194 }
1195 
1196 /* Fast parameter parsing API */
1197 
1198 /* Fast ZPP is always enabled now; this define is left in for compatibility
1199  * with any existing conditional compilation blocks.
1200  */
1201 #define FAST_ZPP 1
1202 
1203 #define Z_EXPECTED_TYPES(_) \
1204 	_(Z_EXPECTED_LONG,				"of type int") \
1205 	_(Z_EXPECTED_LONG_OR_NULL,		"of type ?int") \
1206 	_(Z_EXPECTED_BOOL,				"of type bool") \
1207 	_(Z_EXPECTED_BOOL_OR_NULL,		"of type ?bool") \
1208 	_(Z_EXPECTED_STRING,			"of type string") \
1209 	_(Z_EXPECTED_STRING_OR_NULL,	"of type ?string") \
1210 	_(Z_EXPECTED_ARRAY,				"of type array") \
1211 	_(Z_EXPECTED_ARRAY_OR_NULL,		"of type ?array") \
1212 	_(Z_EXPECTED_ARRAY_OR_LONG,		"of type array|int") \
1213 	_(Z_EXPECTED_ARRAY_OR_LONG_OR_NULL, "of type array|int|null") \
1214 	_(Z_EXPECTED_ITERABLE,				"of type iterable") \
1215 	_(Z_EXPECTED_ITERABLE_OR_NULL,		"of type ?iterable") \
1216 	_(Z_EXPECTED_FUNC,				"a valid callback") \
1217 	_(Z_EXPECTED_FUNC_OR_NULL,		"a valid callback or null") \
1218 	_(Z_EXPECTED_RESOURCE,			"of type resource") \
1219 	_(Z_EXPECTED_RESOURCE_OR_NULL,	"of type resource or null") \
1220 	_(Z_EXPECTED_PATH,				"of type string") \
1221 	_(Z_EXPECTED_PATH_OR_NULL,		"of type ?string") \
1222 	_(Z_EXPECTED_OBJECT,			"of type object") \
1223 	_(Z_EXPECTED_OBJECT_OR_NULL,	"of type ?object") \
1224 	_(Z_EXPECTED_DOUBLE,			"of type float") \
1225 	_(Z_EXPECTED_DOUBLE_OR_NULL,	"of type ?float") \
1226 	_(Z_EXPECTED_NUMBER,			"of type int|float") \
1227 	_(Z_EXPECTED_NUMBER_OR_NULL,	"of type int|float|null") \
1228 	_(Z_EXPECTED_ARRAY_OR_STRING,	"of type array|string") \
1229 	_(Z_EXPECTED_ARRAY_OR_STRING_OR_NULL, "of type array|string|null") \
1230 	_(Z_EXPECTED_STRING_OR_LONG,	"of type string|int") \
1231 	_(Z_EXPECTED_STRING_OR_LONG_OR_NULL, "of type string|int|null") \
1232 	_(Z_EXPECTED_OBJECT_OR_CLASS_NAME,	"an object or a valid class name") \
1233 	_(Z_EXPECTED_OBJECT_OR_CLASS_NAME_OR_NULL, "an object, a valid class name, or null") \
1234 	_(Z_EXPECTED_OBJECT_OR_STRING,	"of type object|string") \
1235 	_(Z_EXPECTED_OBJECT_OR_STRING_OR_NULL, "of type object|string|null") \
1236 
1237 #define Z_EXPECTED_TYPE
1238 
1239 #define Z_EXPECTED_TYPE_ENUM(id, str) id,
1240 #define Z_EXPECTED_TYPE_STR(id, str)  str,
1241 
1242 typedef enum _zend_expected_type {
1243 	Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_ENUM)
1244 	Z_EXPECTED_LAST
1245 } zend_expected_type;
1246 
1247 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_none_error(void);
1248 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(uint32_t min_num_args, uint32_t max_num_args);
1249 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_error(int error_code, uint32_t num, char *name, zend_expected_type expected_type, zval *arg);
1250 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(uint32_t num, zend_expected_type expected_type, zval *arg);
1251 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(uint32_t num, const char *name, zval *arg);
1252 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_null_error(uint32_t num, const char *name, zval *arg);
1253 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_error(uint32_t num, const char *name, zval *arg);
1254 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_or_null_error(uint32_t num, const char *name, zval *arg);
1255 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_error(uint32_t num, const char *name, zval *arg);
1256 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_or_null_error(uint32_t num, const char *name, zval *arg);
1257 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(uint32_t num, char *error);
1258 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_unexpected_extra_named_error(void);
1259 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic(zend_class_entry *error_ce, uint32_t arg_num, const char *format, va_list va);
1260 ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format, ...);
1261 ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format, ...);
1262 ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format, ...);
1263 
1264 #define ZPP_ERROR_OK                            0
1265 #define ZPP_ERROR_FAILURE                       1
1266 #define ZPP_ERROR_WRONG_CALLBACK                2
1267 #define ZPP_ERROR_WRONG_CLASS                   3
1268 #define ZPP_ERROR_WRONG_CLASS_OR_NULL           4
1269 #define ZPP_ERROR_WRONG_CLASS_OR_STRING         5
1270 #define ZPP_ERROR_WRONG_CLASS_OR_STRING_OR_NULL 6
1271 #define ZPP_ERROR_WRONG_CLASS_OR_LONG           7
1272 #define ZPP_ERROR_WRONG_CLASS_OR_LONG_OR_NULL   8
1273 #define ZPP_ERROR_WRONG_ARG                     9
1274 #define ZPP_ERROR_WRONG_COUNT                   10
1275 #define ZPP_ERROR_UNEXPECTED_EXTRA_NAMED        11
1276 
1277 #define ZEND_PARSE_PARAMETERS_START_EX(flags, min_num_args, max_num_args) do { \
1278 		const int _flags = (flags); \
1279 		uint32_t _min_num_args = (min_num_args); \
1280 		uint32_t _max_num_args = (uint32_t) (max_num_args); \
1281 		uint32_t _num_args = EX_NUM_ARGS(); \
1282 		uint32_t _i = 0; \
1283 		zval *_real_arg, *_arg = NULL; \
1284 		zend_expected_type _expected_type = Z_EXPECTED_LONG; \
1285 		char *_error = NULL; \
1286 		zend_bool _dummy = 0; \
1287 		zend_bool _optional = 0; \
1288 		int _error_code = ZPP_ERROR_OK; \
1289 		((void)_i); \
1290 		((void)_real_arg); \
1291 		((void)_arg); \
1292 		((void)_expected_type); \
1293 		((void)_error); \
1294 		((void)_optional); \
1295 		((void)_dummy); \
1296 		\
1297 		do { \
1298 			if (UNEXPECTED(_num_args < _min_num_args) || \
1299 			    UNEXPECTED(_num_args > _max_num_args)) { \
1300 				if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
1301 					zend_wrong_parameters_count_error(_min_num_args, _max_num_args); \
1302 				} \
1303 				_error_code = ZPP_ERROR_FAILURE; \
1304 				break; \
1305 			} \
1306 			_real_arg = ZEND_CALL_ARG(execute_data, 0);
1307 
1308 #define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args) \
1309 	ZEND_PARSE_PARAMETERS_START_EX(0, min_num_args, max_num_args)
1310 
1311 #define ZEND_PARSE_PARAMETERS_NONE() do { \
1312 		if (UNEXPECTED(ZEND_NUM_ARGS() != 0)) { \
1313 			zend_wrong_parameters_none_error(); \
1314 			return; \
1315 		} \
1316 	} while (0)
1317 
1318 #define ZEND_PARSE_PARAMETERS_END_EX(failure) \
1319 		} while (0); \
1320 		if (UNEXPECTED(_error_code != ZPP_ERROR_OK)) { \
1321 			if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
1322 				zend_wrong_parameter_error(_error_code, _i, _error, _expected_type, _arg); \
1323 			} \
1324 			failure; \
1325 		} \
1326 	} while (0)
1327 
1328 #define ZEND_PARSE_PARAMETERS_END() \
1329 	ZEND_PARSE_PARAMETERS_END_EX(return)
1330 
1331 #define Z_PARAM_PROLOGUE(deref, separate) \
1332 	++_i; \
1333 	ZEND_ASSERT(_i <= _min_num_args || _optional==1); \
1334 	ZEND_ASSERT(_i >  _min_num_args || _optional==0); \
1335 	if (_optional) { \
1336 		if (UNEXPECTED(_i >_num_args)) break; \
1337 	} \
1338 	_real_arg++; \
1339 	_arg = _real_arg; \
1340 	if (deref) { \
1341 		if (EXPECTED(Z_ISREF_P(_arg))) { \
1342 			_arg = Z_REFVAL_P(_arg); \
1343 		} \
1344 	} \
1345 	if (separate) { \
1346 		SEPARATE_ZVAL_NOREF(_arg); \
1347 	}
1348 
1349 /* old "|" */
1350 #define Z_PARAM_OPTIONAL \
1351 	_optional = 1;
1352 
1353 /* old "a" */
1354 #define Z_PARAM_ARRAY_EX2(dest, check_null, deref, separate) \
1355 		Z_PARAM_PROLOGUE(deref, separate); \
1356 		if (UNEXPECTED(!zend_parse_arg_array(_arg, &dest, check_null, 0))) { \
1357 			_expected_type = check_null ? Z_EXPECTED_ARRAY_OR_NULL : Z_EXPECTED_ARRAY; \
1358 			_error_code = ZPP_ERROR_WRONG_ARG; \
1359 			break; \
1360 		}
1361 
1362 #define Z_PARAM_ARRAY_EX(dest, check_null, separate) \
1363 	Z_PARAM_ARRAY_EX2(dest, check_null, separate, separate)
1364 
1365 #define Z_PARAM_ARRAY(dest) \
1366 	Z_PARAM_ARRAY_EX(dest, 0, 0)
1367 
1368 #define Z_PARAM_ARRAY_OR_NULL(dest) \
1369 	Z_PARAM_ARRAY_EX(dest, 1, 0)
1370 
1371 /* old "A" */
1372 #define Z_PARAM_ARRAY_OR_OBJECT_EX2(dest, check_null, deref, separate) \
1373 		Z_PARAM_PROLOGUE(deref, separate); \
1374 		if (UNEXPECTED(!zend_parse_arg_array(_arg, &dest, check_null, 1))) { \
1375 			_expected_type = check_null ? Z_EXPECTED_ARRAY_OR_NULL : Z_EXPECTED_ARRAY; \
1376 			_error_code = ZPP_ERROR_WRONG_ARG; \
1377 			break; \
1378 		}
1379 
1380 #define Z_PARAM_ARRAY_OR_OBJECT_EX(dest, check_null, separate) \
1381 	Z_PARAM_ARRAY_OR_OBJECT_EX2(dest, check_null, separate, separate)
1382 
1383 #define Z_PARAM_ARRAY_OR_OBJECT(dest) \
1384 	Z_PARAM_ARRAY_OR_OBJECT_EX(dest, 0, 0)
1385 
1386 #define Z_PARAM_ITERABLE_EX(dest, check_null) \
1387 	Z_PARAM_PROLOGUE(0, 0); \
1388 	if (UNEXPECTED(!zend_parse_arg_iterable(_arg, &dest, check_null))) { \
1389 		_expected_type = check_null ? Z_EXPECTED_ITERABLE_OR_NULL : Z_EXPECTED_ITERABLE; \
1390 		_error_code = ZPP_ERROR_WRONG_ARG; \
1391 		break; \
1392 	}
1393 
1394 #define Z_PARAM_ITERABLE(dest) \
1395 	Z_PARAM_ITERABLE_EX(dest, 0)
1396 
1397 #define Z_PARAM_ITERABLE_OR_NULL(dest) \
1398 	Z_PARAM_ITERABLE_EX(dest, 1)
1399 
1400 /* old "b" */
1401 #define Z_PARAM_BOOL_EX2(dest, is_null, check_null, deref, separate) \
1402 		Z_PARAM_PROLOGUE(deref, separate); \
1403 		if (UNEXPECTED(!zend_parse_arg_bool(_arg, &dest, &is_null, check_null))) { \
1404 			_expected_type = check_null ? Z_EXPECTED_BOOL_OR_NULL : Z_EXPECTED_BOOL; \
1405 			_error_code = ZPP_ERROR_WRONG_ARG; \
1406 			break; \
1407 		}
1408 
1409 #define Z_PARAM_BOOL_EX(dest, is_null, check_null, separate) \
1410 	Z_PARAM_BOOL_EX2(dest, is_null, check_null, separate, separate)
1411 
1412 #define Z_PARAM_BOOL(dest) \
1413 	Z_PARAM_BOOL_EX(dest, _dummy, 0, 0)
1414 
1415 #define Z_PARAM_BOOL_OR_NULL(dest, is_null) \
1416 	Z_PARAM_BOOL_EX(dest, is_null, 1, 0)
1417 
1418 /* old "C" */
1419 #define Z_PARAM_CLASS_EX2(dest, check_null, deref, separate) \
1420 		Z_PARAM_PROLOGUE(deref, separate); \
1421 		if (UNEXPECTED(!zend_parse_arg_class(_arg, &dest, _i, check_null))) { \
1422 			_error_code = ZPP_ERROR_FAILURE; \
1423 			break; \
1424 		}
1425 
1426 #define Z_PARAM_CLASS_EX(dest, check_null, separate) \
1427 	Z_PARAM_CLASS_EX2(dest, check_null, separate, separate)
1428 
1429 #define Z_PARAM_CLASS(dest) \
1430 	Z_PARAM_CLASS_EX(dest, 0, 0)
1431 
1432 #define Z_PARAM_CLASS_OR_NULL(dest) \
1433 	Z_PARAM_CLASS_EX(dest, 1, 0)
1434 
1435 #define Z_PARAM_OBJ_OR_CLASS_NAME_EX(dest, allow_null) \
1436 	Z_PARAM_PROLOGUE(0, 0); \
1437 	if (UNEXPECTED(!zend_parse_arg_obj_or_class_name(_arg, &dest, allow_null))) { \
1438 		_expected_type = allow_null ? Z_EXPECTED_OBJECT_OR_CLASS_NAME_OR_NULL : Z_EXPECTED_OBJECT_OR_CLASS_NAME; \
1439 		_error_code = ZPP_ERROR_WRONG_ARG; \
1440 		break; \
1441 	}
1442 
1443 #define Z_PARAM_OBJ_OR_CLASS_NAME(dest) \
1444 	Z_PARAM_OBJ_OR_CLASS_NAME_EX(dest, 0);
1445 
1446 #define Z_PARAM_OBJ_OR_CLASS_NAME_OR_NULL(dest) \
1447 	Z_PARAM_OBJ_OR_CLASS_NAME_EX(dest, 1);
1448 
1449 #define Z_PARAM_OBJ_OR_STR_EX(destination_object, destination_string, allow_null) \
1450 	Z_PARAM_PROLOGUE(0, 0); \
1451 	if (UNEXPECTED(!zend_parse_arg_obj_or_str(_arg, &destination_object, NULL, &destination_string, allow_null))) { \
1452 		_expected_type = allow_null ? Z_EXPECTED_OBJECT_OR_STRING_OR_NULL : Z_EXPECTED_OBJECT_OR_STRING; \
1453 		_error_code = ZPP_ERROR_WRONG_ARG; \
1454 		break; \
1455 	}
1456 
1457 #define Z_PARAM_OBJ_OR_STR(destination_object, destination_string) \
1458 	Z_PARAM_OBJ_OR_STR_EX(destination_object, destination_string, 0);
1459 
1460 #define Z_PARAM_OBJ_OR_STR_OR_NULL(destination_object, destination_string) \
1461 	Z_PARAM_OBJ_OR_STR_EX(destination_object, destination_string, 1);
1462 
1463 #define Z_PARAM_OBJ_OF_CLASS_OR_STR_EX(destination_object, base_ce, destination_string, allow_null) \
1464 	Z_PARAM_PROLOGUE(0, 0); \
1465 	if (UNEXPECTED(!zend_parse_arg_obj_or_str(_arg, &destination_object, base_ce, &destination_string, allow_null))) { \
1466 		if (base_ce) { \
1467 			_error = ZSTR_VAL((base_ce)->name); \
1468 			_error_code = allow_null ? ZPP_ERROR_WRONG_CLASS_OR_STRING_OR_NULL : ZPP_ERROR_WRONG_CLASS_OR_STRING; \
1469 			break; \
1470 		} else { \
1471 			_expected_type = allow_null ? Z_EXPECTED_OBJECT_OR_STRING_OR_NULL : Z_EXPECTED_OBJECT_OR_STRING; \
1472 			_error_code = ZPP_ERROR_WRONG_ARG; \
1473 			break; \
1474 		} \
1475 	}
1476 
1477 #define Z_PARAM_OBJ_OF_CLASS_OR_STR(destination_object, base_ce, destination_string) \
1478 	Z_PARAM_OBJ_OF_CLASS_OR_STR_EX(destination_object, base_ce, destination_string, 0);
1479 
1480 #define Z_PARAM_OBJ_OF_CLASS_OR_STR_OR_NULL(destination_object, base_ce, destination_string) \
1481 	Z_PARAM_OBJ_OF_CLASS_OR_STR_EX(destination_object, base_ce, destination_string, 1);
1482 
1483 /* old "d" */
1484 #define Z_PARAM_DOUBLE_EX2(dest, is_null, check_null, deref, separate) \
1485 		Z_PARAM_PROLOGUE(deref, separate); \
1486 		if (UNEXPECTED(!zend_parse_arg_double(_arg, &dest, &is_null, check_null))) { \
1487 			_expected_type = check_null ? Z_EXPECTED_DOUBLE_OR_NULL : Z_EXPECTED_DOUBLE; \
1488 			_error_code = ZPP_ERROR_WRONG_ARG; \
1489 			break; \
1490 		}
1491 
1492 #define Z_PARAM_DOUBLE_EX(dest, is_null, check_null, separate) \
1493 	Z_PARAM_DOUBLE_EX2(dest, is_null, check_null, separate, separate)
1494 
1495 #define Z_PARAM_DOUBLE(dest) \
1496 	Z_PARAM_DOUBLE_EX(dest, _dummy, 0, 0)
1497 
1498 #define Z_PARAM_DOUBLE_OR_NULL(dest, is_null) \
1499 	Z_PARAM_DOUBLE_EX(dest, is_null, 1, 0)
1500 
1501 /* old "f" */
1502 #define Z_PARAM_FUNC_EX2(dest_fci, dest_fcc, check_null, deref, separate) \
1503 		Z_PARAM_PROLOGUE(deref, separate); \
1504 		if (UNEXPECTED(!zend_parse_arg_func(_arg, &dest_fci, &dest_fcc, check_null, &_error))) { \
1505 			if (!_error) { \
1506 				_expected_type = check_null ? Z_EXPECTED_FUNC_OR_NULL : Z_EXPECTED_FUNC; \
1507 				_error_code = ZPP_ERROR_WRONG_ARG; \
1508 			} else { \
1509 				_error_code = ZPP_ERROR_WRONG_CALLBACK; \
1510 			} \
1511 			break; \
1512 		} \
1513 
1514 #define Z_PARAM_FUNC_EX(dest_fci, dest_fcc, check_null, separate) \
1515 	Z_PARAM_FUNC_EX2(dest_fci, dest_fcc, check_null, separate, separate)
1516 
1517 #define Z_PARAM_FUNC(dest_fci, dest_fcc) \
1518 	Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 0, 0)
1519 
1520 #define Z_PARAM_FUNC_OR_NULL(dest_fci, dest_fcc) \
1521 	Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 1, 0)
1522 
1523 /* old "h" */
1524 #define Z_PARAM_ARRAY_HT_EX2(dest, check_null, deref, separate) \
1525 		Z_PARAM_PROLOGUE(deref, separate); \
1526 		if (UNEXPECTED(!zend_parse_arg_array_ht(_arg, &dest, check_null, 0, separate))) { \
1527 			_expected_type = check_null ? Z_EXPECTED_ARRAY_OR_NULL : Z_EXPECTED_ARRAY; \
1528 			_error_code = ZPP_ERROR_WRONG_ARG; \
1529 			break; \
1530 		}
1531 
1532 #define Z_PARAM_ARRAY_HT_EX(dest, check_null, separate) \
1533 	Z_PARAM_ARRAY_HT_EX2(dest, check_null, separate, separate)
1534 
1535 #define Z_PARAM_ARRAY_HT(dest) \
1536 	Z_PARAM_ARRAY_HT_EX(dest, 0, 0)
1537 
1538 #define Z_PARAM_ARRAY_HT_OR_NULL(dest) \
1539 	Z_PARAM_ARRAY_HT_EX(dest, 1, 0)
1540 
1541 #define Z_PARAM_ARRAY_HT_OR_LONG_EX(dest_ht, dest_long, is_null, allow_null) \
1542 	Z_PARAM_PROLOGUE(0, 0); \
1543 	if (UNEXPECTED(!zend_parse_arg_array_ht_or_long(_arg, &dest_ht, &dest_long, &is_null, allow_null))) { \
1544 		_expected_type = allow_null ? Z_EXPECTED_ARRAY_OR_LONG_OR_NULL : Z_EXPECTED_ARRAY_OR_LONG; \
1545 		_error_code = ZPP_ERROR_WRONG_ARG; \
1546 		break; \
1547 	}
1548 
1549 #define Z_PARAM_ARRAY_HT_OR_LONG(dest_ht, dest_long) \
1550 	Z_PARAM_ARRAY_HT_OR_LONG_EX(dest_ht, dest_long, _dummy, 0)
1551 
1552 #define Z_PARAM_ARRAY_HT_OR_LONG_OR_NULL(dest_ht, dest_long, is_null) \
1553 	Z_PARAM_ARRAY_HT_OR_LONG_EX(dest_ht, dest_long, is_null, 1)
1554 
1555 /* old "H" */
1556 #define Z_PARAM_ARRAY_OR_OBJECT_HT_EX2(dest, check_null, deref, separate) \
1557 		Z_PARAM_PROLOGUE(deref, separate); \
1558 		if (UNEXPECTED(!zend_parse_arg_array_ht(_arg, &dest, check_null, 1, separate))) { \
1559 			_expected_type = check_null ? Z_EXPECTED_ARRAY_OR_NULL : Z_EXPECTED_ARRAY; \
1560 			_error_code = ZPP_ERROR_WRONG_ARG; \
1561 			break; \
1562 		}
1563 
1564 #define Z_PARAM_ARRAY_OR_OBJECT_HT_EX(dest, check_null, separate) \
1565 	Z_PARAM_ARRAY_OR_OBJECT_HT_EX2(dest, check_null, separate, separate)
1566 
1567 #define Z_PARAM_ARRAY_OR_OBJECT_HT(dest) \
1568 	Z_PARAM_ARRAY_OR_OBJECT_HT_EX(dest, 0, 0)
1569 
1570 /* old "l" */
1571 #define Z_PARAM_LONG_EX2(dest, is_null, check_null, deref, separate) \
1572 		Z_PARAM_PROLOGUE(deref, separate); \
1573 		if (UNEXPECTED(!zend_parse_arg_long(_arg, &dest, &is_null, check_null))) { \
1574 			_expected_type = check_null ? Z_EXPECTED_LONG_OR_NULL : Z_EXPECTED_LONG; \
1575 			_error_code = ZPP_ERROR_WRONG_ARG; \
1576 			break; \
1577 		}
1578 
1579 #define Z_PARAM_LONG_EX(dest, is_null, check_null, separate) \
1580 	Z_PARAM_LONG_EX2(dest, is_null, check_null, separate, separate)
1581 
1582 #define Z_PARAM_LONG(dest) \
1583 	Z_PARAM_LONG_EX(dest, _dummy, 0, 0)
1584 
1585 #define Z_PARAM_LONG_OR_NULL(dest, is_null) \
1586 	Z_PARAM_LONG_EX(dest, is_null, 1, 0)
1587 
1588 /* old "n" */
1589 #define Z_PARAM_NUMBER_EX(dest, check_null) \
1590 	Z_PARAM_PROLOGUE(0, 0); \
1591 	if (UNEXPECTED(!zend_parse_arg_number(_arg, &dest, check_null))) { \
1592 		_expected_type = check_null ? Z_EXPECTED_NUMBER_OR_NULL : Z_EXPECTED_NUMBER; \
1593 		_error_code = ZPP_ERROR_WRONG_ARG; \
1594 		break; \
1595 	}
1596 
1597 #define Z_PARAM_NUMBER_OR_NULL(dest) \
1598 	Z_PARAM_NUMBER_EX(dest, 1)
1599 
1600 #define Z_PARAM_NUMBER(dest) \
1601 	Z_PARAM_NUMBER_EX(dest, 0)
1602 
1603 /* old "o" */
1604 #define Z_PARAM_OBJECT_EX2(dest, check_null, deref, separate) \
1605 		Z_PARAM_PROLOGUE(deref, separate); \
1606 		if (UNEXPECTED(!zend_parse_arg_object(_arg, &dest, NULL, check_null))) { \
1607 			_expected_type = check_null ? Z_EXPECTED_OBJECT_OR_NULL : Z_EXPECTED_OBJECT; \
1608 			_error_code = ZPP_ERROR_WRONG_ARG; \
1609 			break; \
1610 		}
1611 
1612 #define Z_PARAM_OBJECT_EX(dest, check_null, separate) \
1613 	Z_PARAM_OBJECT_EX2(dest, check_null, separate, separate)
1614 
1615 #define Z_PARAM_OBJECT(dest) \
1616 	Z_PARAM_OBJECT_EX(dest, 0, 0)
1617 
1618 #define Z_PARAM_OBJECT_OR_NULL(dest) \
1619 	Z_PARAM_OBJECT_EX(dest, 1, 0)
1620 
1621 /* The same as Z_PARAM_OBJECT_EX2 except that dest is a zend_object rather than a zval */
1622 #define Z_PARAM_OBJ_EX2(dest, check_null, deref, separate) \
1623 		Z_PARAM_PROLOGUE(deref, separate); \
1624 		if (UNEXPECTED(!zend_parse_arg_obj(_arg, &dest, NULL, check_null))) { \
1625 			_expected_type = check_null ? Z_EXPECTED_OBJECT_OR_NULL : Z_EXPECTED_OBJECT; \
1626 			_error_code = ZPP_ERROR_WRONG_ARG; \
1627 			break; \
1628 		}
1629 
1630 #define Z_PARAM_OBJ_EX(dest, check_null, separate) \
1631 	Z_PARAM_OBJ_EX2(dest, check_null, separate, separate)
1632 
1633 #define Z_PARAM_OBJ(dest) \
1634 	Z_PARAM_OBJ_EX(dest, 0, 0)
1635 
1636 #define Z_PARAM_OBJ_OR_NULL(dest) \
1637 	Z_PARAM_OBJ_EX(dest, 1, 0)
1638 
1639 /* old "O" */
1640 #define Z_PARAM_OBJECT_OF_CLASS_EX2(dest, _ce, check_null, deref, separate) \
1641 		Z_PARAM_PROLOGUE(deref, separate); \
1642 		if (UNEXPECTED(!zend_parse_arg_object(_arg, &dest, _ce, check_null))) { \
1643 			if (_ce) { \
1644 				_error = ZSTR_VAL((_ce)->name); \
1645 				_error_code = check_null ? ZPP_ERROR_WRONG_CLASS_OR_NULL : ZPP_ERROR_WRONG_CLASS; \
1646 				break; \
1647 			} else { \
1648 				_expected_type = check_null ? Z_EXPECTED_OBJECT_OR_NULL : Z_EXPECTED_OBJECT; \
1649 				_error_code = ZPP_ERROR_WRONG_ARG; \
1650 				break; \
1651 			} \
1652 		}
1653 
1654 #define Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, check_null, separate) \
1655 	Z_PARAM_OBJECT_OF_CLASS_EX2(dest, _ce, check_null, separate, separate)
1656 
1657 #define Z_PARAM_OBJECT_OF_CLASS(dest, _ce) \
1658 	Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, 0, 0)
1659 
1660 #define Z_PARAM_OBJECT_OF_CLASS_OR_NULL(dest, _ce) \
1661 	Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, 1, 0)
1662 
1663 /* The same as Z_PARAM_OBJECT_OF_CLASS_EX2 except that dest is a zend_object rather than a zval */
1664 #define Z_PARAM_OBJ_OF_CLASS_EX2(dest, _ce, check_null, deref, separate) \
1665 		Z_PARAM_PROLOGUE(deref, separate); \
1666 		if (UNEXPECTED(!zend_parse_arg_obj(_arg, &dest, _ce, check_null))) { \
1667 			if (_ce) { \
1668 				_error = ZSTR_VAL((_ce)->name); \
1669 				_error_code = check_null ? ZPP_ERROR_WRONG_CLASS_OR_NULL : ZPP_ERROR_WRONG_CLASS; \
1670 				break; \
1671 			} else { \
1672 				_expected_type = check_null ? Z_EXPECTED_OBJECT_OR_NULL : Z_EXPECTED_OBJECT; \
1673 				_error_code = ZPP_ERROR_WRONG_ARG; \
1674 				break; \
1675 			} \
1676 		}
1677 
1678 #define Z_PARAM_OBJ_OF_CLASS_EX(dest, _ce, check_null, separate) \
1679 	Z_PARAM_OBJ_OF_CLASS_EX2(dest, _ce, check_null, separate, separate)
1680 
1681 #define Z_PARAM_OBJ_OF_CLASS(dest, _ce) \
1682 	Z_PARAM_OBJ_OF_CLASS_EX(dest, _ce, 0, 0)
1683 
1684 #define Z_PARAM_OBJ_OF_CLASS_OR_NULL(dest, _ce) \
1685 	Z_PARAM_OBJ_OF_CLASS_EX(dest, _ce, 1, 0)
1686 
1687 #define Z_PARAM_OBJ_OF_CLASS_OR_LONG_EX(dest_obj, _ce, dest_long, is_null, allow_null) \
1688 		Z_PARAM_PROLOGUE(0, 0); \
1689 		if (UNEXPECTED(!zend_parse_arg_obj_or_long(_arg, &dest_obj, _ce, &dest_long, &is_null, allow_null))) { \
1690 			_error = ZSTR_VAL((_ce)->name); \
1691 			_error_code = allow_null ? ZPP_ERROR_WRONG_CLASS_OR_LONG_OR_NULL : ZPP_ERROR_WRONG_CLASS_OR_LONG; \
1692 			break; \
1693 		}
1694 
1695 #define Z_PARAM_OBJ_OF_CLASS_OR_LONG(dest_obj, _ce, dest_long) \
1696 	Z_PARAM_OBJ_OF_CLASS_OR_LONG_EX(dest_obj, _ce, dest_long, _dummy, 0)
1697 
1698 #define Z_PARAM_OBJ_OF_CLASS_OR_LONG_OR_NULL(dest_obj, _ce, dest_long, is_null) \
1699 	Z_PARAM_OBJ_OF_CLASS_OR_LONG_EX(dest_obj, _ce, dest_long, is_null, 1)
1700 
1701 /* old "p" */
1702 #define Z_PARAM_PATH_EX2(dest, dest_len, check_null, deref, separate) \
1703 		Z_PARAM_PROLOGUE(deref, separate); \
1704 		if (UNEXPECTED(!zend_parse_arg_path(_arg, &dest, &dest_len, check_null))) { \
1705 			_expected_type = check_null ? Z_EXPECTED_PATH_OR_NULL : Z_EXPECTED_PATH; \
1706 			_error_code = ZPP_ERROR_WRONG_ARG; \
1707 			break; \
1708 		}
1709 
1710 #define Z_PARAM_PATH_EX(dest, dest_len, check_null, separate) \
1711 	Z_PARAM_PATH_EX2(dest, dest_len, check_null, separate, separate)
1712 
1713 #define Z_PARAM_PATH(dest, dest_len) \
1714 	Z_PARAM_PATH_EX(dest, dest_len, 0, 0)
1715 
1716 #define Z_PARAM_PATH_OR_NULL(dest, dest_len) \
1717 	Z_PARAM_PATH_EX(dest, dest_len, 1, 0)
1718 
1719 /* old "P" */
1720 #define Z_PARAM_PATH_STR_EX2(dest, check_null, deref, separate) \
1721 		Z_PARAM_PROLOGUE(deref, separate); \
1722 		if (UNEXPECTED(!zend_parse_arg_path_str(_arg, &dest, check_null))) { \
1723 			_expected_type = check_null ? Z_EXPECTED_PATH_OR_NULL : Z_EXPECTED_PATH; \
1724 			_error_code = ZPP_ERROR_WRONG_ARG; \
1725 			break; \
1726 		}
1727 
1728 #define Z_PARAM_PATH_STR_EX(dest, check_null, separate) \
1729 	Z_PARAM_PATH_STR_EX2(dest, check_null, separate, separate)
1730 
1731 #define Z_PARAM_PATH_STR(dest) \
1732 	Z_PARAM_PATH_STR_EX(dest, 0, 0)
1733 
1734 #define Z_PARAM_PATH_STR_OR_NULL(dest) \
1735 	Z_PARAM_PATH_STR_EX(dest, 1, 0)
1736 
1737 /* old "r" */
1738 #define Z_PARAM_RESOURCE_EX2(dest, check_null, deref, separate) \
1739 		Z_PARAM_PROLOGUE(deref, separate); \
1740 		if (UNEXPECTED(!zend_parse_arg_resource(_arg, &dest, check_null))) { \
1741 			_expected_type = check_null ? Z_EXPECTED_RESOURCE_OR_NULL : Z_EXPECTED_RESOURCE; \
1742 			_error_code = ZPP_ERROR_WRONG_ARG; \
1743 			break; \
1744 		}
1745 
1746 #define Z_PARAM_RESOURCE_EX(dest, check_null, separate) \
1747 	Z_PARAM_RESOURCE_EX2(dest, check_null, separate, separate)
1748 
1749 #define Z_PARAM_RESOURCE(dest) \
1750 	Z_PARAM_RESOURCE_EX(dest, 0, 0)
1751 
1752 #define Z_PARAM_RESOURCE_OR_NULL(dest) \
1753 	Z_PARAM_RESOURCE_EX(dest, 1, 0)
1754 
1755 /* old "s" */
1756 #define Z_PARAM_STRING_EX2(dest, dest_len, check_null, deref, separate) \
1757 		Z_PARAM_PROLOGUE(deref, separate); \
1758 		if (UNEXPECTED(!zend_parse_arg_string(_arg, &dest, &dest_len, check_null))) { \
1759 			_expected_type = check_null ? Z_EXPECTED_STRING_OR_NULL : Z_EXPECTED_STRING; \
1760 			_error_code = ZPP_ERROR_WRONG_ARG; \
1761 			break; \
1762 		}
1763 
1764 #define Z_PARAM_STRING_EX(dest, dest_len, check_null, separate) \
1765 	Z_PARAM_STRING_EX2(dest, dest_len, check_null, separate, separate)
1766 
1767 #define Z_PARAM_STRING(dest, dest_len) \
1768 	Z_PARAM_STRING_EX(dest, dest_len, 0, 0)
1769 
1770 #define Z_PARAM_STRING_OR_NULL(dest, dest_len) \
1771 	Z_PARAM_STRING_EX(dest, dest_len, 1, 0)
1772 
1773 /* old "S" */
1774 #define Z_PARAM_STR_EX2(dest, check_null, deref, separate) \
1775 		Z_PARAM_PROLOGUE(deref, separate); \
1776 		if (UNEXPECTED(!zend_parse_arg_str(_arg, &dest, check_null))) { \
1777 			_expected_type = check_null ? Z_EXPECTED_STRING_OR_NULL : Z_EXPECTED_STRING; \
1778 			_error_code = ZPP_ERROR_WRONG_ARG; \
1779 			break; \
1780 		}
1781 
1782 #define Z_PARAM_STR_EX(dest, check_null, separate) \
1783 	Z_PARAM_STR_EX2(dest, check_null, separate, separate)
1784 
1785 #define Z_PARAM_STR(dest) \
1786 	Z_PARAM_STR_EX(dest, 0, 0)
1787 
1788 #define Z_PARAM_STR_OR_NULL(dest) \
1789 	Z_PARAM_STR_EX(dest, 1, 0)
1790 
1791 /* old "z" */
1792 #define Z_PARAM_ZVAL_EX2(dest, check_null, deref, separate) \
1793 		Z_PARAM_PROLOGUE(deref, separate); \
1794 		zend_parse_arg_zval_deref(_arg, &dest, check_null);
1795 
1796 #define Z_PARAM_ZVAL_EX(dest, check_null, separate) \
1797 	Z_PARAM_ZVAL_EX2(dest, check_null, separate, separate)
1798 
1799 #define Z_PARAM_ZVAL(dest) \
1800 	Z_PARAM_ZVAL_EX(dest, 0, 0)
1801 
1802 #define Z_PARAM_ZVAL_OR_NULL(dest) \
1803 	Z_PARAM_ZVAL_EX(dest, 1, 0)
1804 
1805 /* old "+" and "*" */
1806 #define Z_PARAM_VARIADIC_EX(spec, dest, dest_num, post_varargs) do { \
1807 		uint32_t _num_varargs = _num_args - _i - (post_varargs); \
1808 		if (EXPECTED(_num_varargs > 0)) { \
1809 			dest = _real_arg + 1; \
1810 			dest_num = _num_varargs; \
1811 			_i += _num_varargs; \
1812 			_real_arg += _num_varargs; \
1813 		} else { \
1814 			dest = NULL; \
1815 			dest_num = 0; \
1816 		} \
1817 		if (UNEXPECTED(ZEND_CALL_INFO(execute_data) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { \
1818 			_error_code = ZPP_ERROR_UNEXPECTED_EXTRA_NAMED; \
1819 			break; \
1820 		} \
1821 	} while (0);
1822 
1823 #define Z_PARAM_VARIADIC(spec, dest, dest_num) \
1824 	Z_PARAM_VARIADIC_EX(spec, dest, dest_num, 0)
1825 
1826 #define Z_PARAM_VARIADIC_WITH_NAMED(dest, dest_num, dest_named) do { \
1827 		int _num_varargs = _num_args - _i; \
1828 		if (EXPECTED(_num_varargs > 0)) { \
1829 			dest = _real_arg + 1; \
1830 			dest_num = _num_varargs; \
1831 		} else { \
1832 			dest = NULL; \
1833 			dest_num = 0; \
1834 		} \
1835 		if (ZEND_CALL_INFO(execute_data) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { \
1836 			dest_named = execute_data->extra_named_params; \
1837 		} else { \
1838 			dest_named = NULL; \
1839 		} \
1840 	} while (0);
1841 
1842 #define Z_PARAM_ARRAY_HT_OR_STR_EX(dest_ht, dest_str, allow_null) \
1843 	Z_PARAM_PROLOGUE(0, 0); \
1844 	if (UNEXPECTED(!zend_parse_arg_array_ht_or_str(_arg, &dest_ht, &dest_str, allow_null))) { \
1845 		_expected_type = allow_null ? Z_EXPECTED_ARRAY_OR_STRING_OR_NULL : Z_EXPECTED_ARRAY_OR_STRING; \
1846 		_error_code = ZPP_ERROR_WRONG_ARG; \
1847 		break; \
1848 	}
1849 
1850 #define Z_PARAM_ARRAY_HT_OR_STR(dest_ht, dest_str) \
1851 	Z_PARAM_ARRAY_HT_OR_STR_EX(dest_ht, dest_str, 0);
1852 
1853 #define Z_PARAM_ARRAY_HT_OR_STR_OR_NULL(dest_ht, dest_str) \
1854 	Z_PARAM_ARRAY_HT_OR_STR_EX(dest_ht, dest_str, 1);
1855 
1856 #define Z_PARAM_STR_OR_LONG_EX(dest_str, dest_long, is_null, allow_null) \
1857 	Z_PARAM_PROLOGUE(0, 0); \
1858 	if (UNEXPECTED(!zend_parse_arg_str_or_long(_arg, &dest_str, &dest_long, &is_null, allow_null))) { \
1859 		_expected_type = allow_null ? Z_EXPECTED_STRING_OR_LONG_OR_NULL : Z_EXPECTED_STRING_OR_LONG; \
1860 		_error_code = ZPP_ERROR_WRONG_ARG; \
1861 		break; \
1862 	}
1863 
1864 #define Z_PARAM_STR_OR_LONG(dest_str, dest_long) \
1865 	Z_PARAM_STR_OR_LONG_EX(dest_str, dest_long, _dummy, 0);
1866 
1867 #define Z_PARAM_STR_OR_LONG_OR_NULL(dest_str, dest_long, is_null) \
1868 	Z_PARAM_STR_OR_LONG_EX(dest_str, dest_long, is_null, 1);
1869 
1870 /* End of new parameter parsing API */
1871 
1872 /* Inlined implementations shared by new and old parameter parsing APIs */
1873 
1874 ZEND_API bool ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pce, uint32_t num, bool check_null);
1875 ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_slow(zval *arg, zend_bool *dest);
1876 ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_weak(zval *arg, zend_bool *dest);
1877 ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_slow(zval *arg, zend_long *dest);
1878 ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_weak(zval *arg, zend_long *dest);
1879 ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_slow(zval *arg, double *dest);
1880 ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_weak(zval *arg, double *dest);
1881 ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest);
1882 ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest);
1883 ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest);
1884 ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_or_long_slow(zval *arg, zend_string **dest_str, zend_long *dest_long);
1885 
zend_parse_arg_bool(zval * arg,zend_bool * dest,zend_bool * is_null,bool check_null)1886 static zend_always_inline bool zend_parse_arg_bool(zval *arg, zend_bool *dest, zend_bool *is_null, bool check_null)
1887 {
1888 	if (check_null) {
1889 		*is_null = 0;
1890 	}
1891 	if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
1892 		*dest = 1;
1893 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_FALSE)) {
1894 		*dest = 0;
1895 	} else if (check_null && Z_TYPE_P(arg) == IS_NULL) {
1896 		*is_null = 1;
1897 		*dest = 0;
1898 	} else {
1899 		return zend_parse_arg_bool_slow(arg, dest);
1900 	}
1901 	return 1;
1902 }
1903 
zend_parse_arg_long(zval * arg,zend_long * dest,zend_bool * is_null,bool check_null)1904 static zend_always_inline bool zend_parse_arg_long(zval *arg, zend_long *dest, zend_bool *is_null, bool check_null)
1905 {
1906 	if (check_null) {
1907 		*is_null = 0;
1908 	}
1909 	if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
1910 		*dest = Z_LVAL_P(arg);
1911 	} else if (check_null && Z_TYPE_P(arg) == IS_NULL) {
1912 		*is_null = 1;
1913 		*dest = 0;
1914 	} else {
1915 		return zend_parse_arg_long_slow(arg, dest);
1916 	}
1917 	return 1;
1918 }
1919 
zend_parse_arg_double(zval * arg,double * dest,zend_bool * is_null,bool check_null)1920 static zend_always_inline bool zend_parse_arg_double(zval *arg, double *dest, zend_bool *is_null, bool check_null)
1921 {
1922 	if (check_null) {
1923 		*is_null = 0;
1924 	}
1925 	if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
1926 		*dest = Z_DVAL_P(arg);
1927 	} else if (check_null && Z_TYPE_P(arg) == IS_NULL) {
1928 		*is_null = 1;
1929 		*dest = 0.0;
1930 	} else {
1931 		return zend_parse_arg_double_slow(arg, dest);
1932 	}
1933 	return 1;
1934 }
1935 
zend_parse_arg_number(zval * arg,zval ** dest,bool check_null)1936 static zend_always_inline bool zend_parse_arg_number(zval *arg, zval **dest, bool check_null)
1937 {
1938 	if (EXPECTED(Z_TYPE_P(arg) == IS_LONG || Z_TYPE_P(arg) == IS_DOUBLE)) {
1939 		*dest = arg;
1940 	} else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
1941 		*dest = NULL;
1942 	} else {
1943 		return zend_parse_arg_number_slow(arg, dest);
1944 	}
1945 	return 1;
1946 }
1947 
zend_parse_arg_str(zval * arg,zend_string ** dest,bool check_null)1948 static zend_always_inline bool zend_parse_arg_str(zval *arg, zend_string **dest, bool check_null)
1949 {
1950 	if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
1951 		*dest = Z_STR_P(arg);
1952 	} else if (check_null && Z_TYPE_P(arg) == IS_NULL) {
1953 		*dest = NULL;
1954 	} else {
1955 		return zend_parse_arg_str_slow(arg, dest);
1956 	}
1957 	return 1;
1958 }
1959 
zend_parse_arg_string(zval * arg,char ** dest,size_t * dest_len,bool check_null)1960 static zend_always_inline bool zend_parse_arg_string(zval *arg, char **dest, size_t *dest_len, bool check_null)
1961 {
1962 	zend_string *str;
1963 
1964 	if (!zend_parse_arg_str(arg, &str, check_null)) {
1965 		return 0;
1966 	}
1967 	if (check_null && UNEXPECTED(!str)) {
1968 		*dest = NULL;
1969 		*dest_len = 0;
1970 	} else {
1971 		*dest = ZSTR_VAL(str);
1972 		*dest_len = ZSTR_LEN(str);
1973 	}
1974 	return 1;
1975 }
1976 
zend_parse_arg_path_str(zval * arg,zend_string ** dest,bool check_null)1977 static zend_always_inline bool zend_parse_arg_path_str(zval *arg, zend_string **dest, bool check_null)
1978 {
1979 	if (!zend_parse_arg_str(arg, dest, check_null) ||
1980 	    (*dest && UNEXPECTED(CHECK_NULL_PATH(ZSTR_VAL(*dest), ZSTR_LEN(*dest))))) {
1981 		return 0;
1982 	}
1983 	return 1;
1984 }
1985 
zend_parse_arg_path(zval * arg,char ** dest,size_t * dest_len,bool check_null)1986 static zend_always_inline bool zend_parse_arg_path(zval *arg, char **dest, size_t *dest_len, bool check_null)
1987 {
1988 	zend_string *str;
1989 
1990 	if (!zend_parse_arg_path_str(arg, &str, check_null)) {
1991 		return 0;
1992 	}
1993 	if (check_null && UNEXPECTED(!str)) {
1994 		*dest = NULL;
1995 		*dest_len = 0;
1996 	} else {
1997 		*dest = ZSTR_VAL(str);
1998 		*dest_len = ZSTR_LEN(str);
1999 	}
2000 	return 1;
2001 }
2002 
zend_parse_arg_iterable(zval * arg,zval ** dest,bool check_null)2003 static zend_always_inline bool zend_parse_arg_iterable(zval *arg, zval **dest, bool check_null)
2004 {
2005 	if (EXPECTED(zend_is_iterable(arg))) {
2006 		*dest = arg;
2007 		return 1;
2008 	}
2009 
2010 	if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
2011 		*dest = NULL;
2012 		return 1;
2013 	}
2014 
2015 	return 0;
2016 }
2017 
zend_parse_arg_array(zval * arg,zval ** dest,bool check_null,bool or_object)2018 static zend_always_inline bool zend_parse_arg_array(zval *arg, zval **dest, bool check_null, bool or_object)
2019 {
2020 	if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY) ||
2021 		(or_object && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT))) {
2022 		*dest = arg;
2023 	} else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
2024 		*dest = NULL;
2025 	} else {
2026 		return 0;
2027 	}
2028 	return 1;
2029 }
2030 
zend_parse_arg_array_ht(zval * arg,HashTable ** dest,bool check_null,bool or_object,bool separate)2031 static zend_always_inline bool zend_parse_arg_array_ht(zval *arg, HashTable **dest, bool check_null, bool or_object, bool separate)
2032 {
2033 	if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY)) {
2034 		*dest = Z_ARRVAL_P(arg);
2035 	} else if (or_object && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
2036 		zend_object *zobj = Z_OBJ_P(arg);
2037 		if (separate
2038 		 && zobj->properties
2039 		 && UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
2040 			if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
2041 				GC_DELREF(zobj->properties);
2042 			}
2043 			zobj->properties = zend_array_dup(zobj->properties);
2044 		}
2045 		*dest = zobj->handlers->get_properties(zobj);
2046 	} else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
2047 		*dest = NULL;
2048 	} else {
2049 		return 0;
2050 	}
2051 	return 1;
2052 }
2053 
zend_parse_arg_array_ht_or_long(zval * arg,HashTable ** dest_ht,zend_long * dest_long,zend_bool * is_null,bool allow_null)2054 static zend_always_inline bool zend_parse_arg_array_ht_or_long(
2055 	zval *arg, HashTable **dest_ht, zend_long *dest_long, zend_bool *is_null, bool allow_null
2056 ) {
2057 	if (allow_null) {
2058 		*is_null = 0;
2059 	}
2060 
2061 	if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY)) {
2062 		*dest_ht = Z_ARRVAL_P(arg);
2063 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
2064 		*dest_ht = NULL;
2065 		*dest_long = Z_LVAL_P(arg);
2066 	} else if (allow_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
2067 		*dest_ht = NULL;
2068 		*is_null = 1;
2069 	} else {
2070 		*dest_ht = NULL;
2071 		return zend_parse_arg_long_slow(arg, dest_long);
2072 	}
2073 
2074 	return 1;
2075 }
2076 
zend_parse_arg_object(zval * arg,zval ** dest,zend_class_entry * ce,bool check_null)2077 static zend_always_inline bool zend_parse_arg_object(zval *arg, zval **dest, zend_class_entry *ce, bool check_null)
2078 {
2079 	if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT) &&
2080 	    (!ce || EXPECTED(instanceof_function(Z_OBJCE_P(arg), ce) != 0))) {
2081 		*dest = arg;
2082 	} else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
2083 		*dest = NULL;
2084 	} else {
2085 		return 0;
2086 	}
2087 	return 1;
2088 }
2089 
zend_parse_arg_obj(zval * arg,zend_object ** dest,zend_class_entry * ce,bool check_null)2090 static zend_always_inline bool zend_parse_arg_obj(zval *arg, zend_object **dest, zend_class_entry *ce, bool check_null)
2091 {
2092 	if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT) &&
2093 	    (!ce || EXPECTED(instanceof_function(Z_OBJCE_P(arg), ce) != 0))) {
2094 		*dest = Z_OBJ_P(arg);
2095 	} else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
2096 		*dest = NULL;
2097 	} else {
2098 		return 0;
2099 	}
2100 	return 1;
2101 }
2102 
zend_parse_arg_obj_or_long(zval * arg,zend_object ** dest_obj,zend_class_entry * ce,zend_long * dest_long,zend_bool * is_null,bool allow_null)2103 static zend_always_inline bool zend_parse_arg_obj_or_long(
2104 	zval *arg, zend_object **dest_obj, zend_class_entry *ce, zend_long *dest_long, zend_bool *is_null, bool allow_null
2105 ) {
2106 	if (allow_null) {
2107 		*is_null = 0;
2108 	}
2109 
2110 	if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT) && EXPECTED(instanceof_function(Z_OBJCE_P(arg), ce) != 0)) {
2111 		*dest_obj = Z_OBJ_P(arg);
2112 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
2113 		*dest_obj = NULL;
2114 		*dest_long = Z_LVAL_P(arg);
2115 	} else if (allow_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
2116 		*dest_obj = NULL;
2117 		*is_null = 1;
2118 	} else {
2119 		*dest_obj = NULL;
2120 		return zend_parse_arg_long_slow(arg, dest_long);
2121 	}
2122 
2123 	return 1;
2124 }
2125 
zend_parse_arg_resource(zval * arg,zval ** dest,bool check_null)2126 static zend_always_inline bool zend_parse_arg_resource(zval *arg, zval **dest, bool check_null)
2127 {
2128 	if (EXPECTED(Z_TYPE_P(arg) == IS_RESOURCE)) {
2129 		*dest = arg;
2130 	} else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
2131 		*dest = NULL;
2132 	} else {
2133 		return 0;
2134 	}
2135 	return 1;
2136 }
2137 
zend_parse_arg_func(zval * arg,zend_fcall_info * dest_fci,zend_fcall_info_cache * dest_fcc,bool check_null,char ** error)2138 static zend_always_inline bool zend_parse_arg_func(zval *arg, zend_fcall_info *dest_fci, zend_fcall_info_cache *dest_fcc, bool check_null, char **error)
2139 {
2140 	if (check_null && UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
2141 		dest_fci->size = 0;
2142 		dest_fcc->function_handler = NULL;
2143 		*error = NULL;
2144 	} else if (UNEXPECTED(zend_fcall_info_init(arg, 0, dest_fci, dest_fcc, NULL, error) != SUCCESS)) {
2145 		return 0;
2146 	}
2147 	/* Release call trampolines: The function may not get called, in which case
2148 	 * the trampoline will leak. Force it to be refetched during
2149 	 * zend_call_function instead. */
2150 	zend_release_fcall_info_cache(dest_fcc);
2151 	return 1;
2152 }
2153 
zend_parse_arg_zval(zval * arg,zval ** dest,bool check_null)2154 static zend_always_inline void zend_parse_arg_zval(zval *arg, zval **dest, bool check_null)
2155 {
2156 	*dest = (check_null &&
2157 	    (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) ||
2158 	     (UNEXPECTED(Z_ISREF_P(arg)) &&
2159 	      UNEXPECTED(Z_TYPE_P(Z_REFVAL_P(arg)) == IS_NULL)))) ? NULL : arg;
2160 }
2161 
zend_parse_arg_zval_deref(zval * arg,zval ** dest,bool check_null)2162 static zend_always_inline void zend_parse_arg_zval_deref(zval *arg, zval **dest, bool check_null)
2163 {
2164 	*dest = (check_null && UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) ? NULL : arg;
2165 }
2166 
zend_parse_arg_array_ht_or_str(zval * arg,HashTable ** dest_ht,zend_string ** dest_str,bool allow_null)2167 static zend_always_inline bool zend_parse_arg_array_ht_or_str(
2168 		zval *arg, HashTable **dest_ht, zend_string **dest_str, bool allow_null)
2169 {
2170 	if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
2171 		*dest_ht = NULL;
2172 		*dest_str = Z_STR_P(arg);
2173 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY)) {
2174 		*dest_ht = Z_ARRVAL_P(arg);
2175 		*dest_str = NULL;
2176 	} else if (allow_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
2177 		*dest_ht = NULL;
2178 		*dest_str = NULL;
2179 	} else {
2180 		*dest_ht = NULL;
2181 		return zend_parse_arg_str_slow(arg, dest_str);
2182 	}
2183 	return 1;
2184 }
2185 
zend_parse_arg_str_or_long(zval * arg,zend_string ** dest_str,zend_long * dest_long,zend_bool * is_null,bool allow_null)2186 static zend_always_inline bool zend_parse_arg_str_or_long(zval *arg, zend_string **dest_str, zend_long *dest_long,
2187 	zend_bool *is_null, bool allow_null)
2188 {
2189 	if (allow_null) {
2190 		*is_null = 0;
2191 	}
2192 	if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
2193 		*dest_str = Z_STR_P(arg);
2194 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
2195 		*dest_str = NULL;
2196 		*dest_long = Z_LVAL_P(arg);
2197 	} else if (allow_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
2198 		*dest_str = NULL;
2199 		*is_null = 1;
2200 	} else {
2201 		return zend_parse_arg_str_or_long_slow(arg, dest_str, dest_long);
2202 	}
2203 	return 1;
2204 }
2205 
zend_parse_arg_obj_or_class_name(zval * arg,zend_class_entry ** destination,bool allow_null)2206 static zend_always_inline bool zend_parse_arg_obj_or_class_name(
2207 	zval *arg, zend_class_entry **destination, bool allow_null
2208 ) {
2209 	if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
2210 		*destination = zend_lookup_class(Z_STR_P(arg));
2211 
2212 		return *destination != NULL;
2213 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
2214 		*destination = Z_OBJ_P(arg)->ce;
2215 	} else if (allow_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
2216 		*destination = NULL;
2217 	} else {
2218 		return 0;
2219 	}
2220 
2221 	return 1;
2222 }
2223 
zend_parse_arg_obj_or_str(zval * arg,zend_object ** destination_object,zend_class_entry * base_ce,zend_string ** destination_string,bool allow_null)2224 static zend_always_inline bool zend_parse_arg_obj_or_str(
2225 	zval *arg, zend_object **destination_object, zend_class_entry *base_ce, zend_string **destination_string, bool allow_null
2226 ) {
2227 	if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
2228 		if (!base_ce || EXPECTED(instanceof_function(Z_OBJCE_P(arg), base_ce))) {
2229 			*destination_object = Z_OBJ_P(arg);
2230 			*destination_string = NULL;
2231 			return 1;
2232 		}
2233 	}
2234 
2235 	*destination_object = NULL;
2236 	return zend_parse_arg_str(arg, destination_string, allow_null);
2237 }
2238 
2239 END_EXTERN_C()
2240 
2241 #endif /* ZEND_API_H */
2242