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