xref: /PHP-7.1/Zend/zend_builtin_functions.c (revision 7f6387b5)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1998-2018 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@zend.com>                                |
16    |          Zeev Suraski <zeev@zend.com>                                |
17    +----------------------------------------------------------------------+
18 */
19 
20 /* $Id$ */
21 
22 #include "zend.h"
23 #include "zend_API.h"
24 #include "zend_builtin_functions.h"
25 #include "zend_constants.h"
26 #include "zend_ini.h"
27 #include "zend_exceptions.h"
28 #include "zend_extensions.h"
29 #include "zend_closures.h"
30 #include "zend_generators.h"
31 
32 #undef ZEND_TEST_EXCEPTIONS
33 
34 #if ZEND_DEBUG
35 static zend_class_entry *zend_test_interface;
36 static zend_class_entry *zend_test_class;
37 static zend_class_entry *zend_test_trait;
38 static zend_object_handlers zend_test_class_handlers;
39 #endif
40 
41 static ZEND_FUNCTION(zend_version);
42 static ZEND_FUNCTION(func_num_args);
43 static ZEND_FUNCTION(func_get_arg);
44 static ZEND_FUNCTION(func_get_args);
45 static ZEND_FUNCTION(strlen);
46 static ZEND_FUNCTION(strcmp);
47 static ZEND_FUNCTION(strncmp);
48 static ZEND_FUNCTION(strcasecmp);
49 static ZEND_FUNCTION(strncasecmp);
50 static ZEND_FUNCTION(each);
51 static ZEND_FUNCTION(error_reporting);
52 static ZEND_FUNCTION(define);
53 static ZEND_FUNCTION(defined);
54 static ZEND_FUNCTION(get_class);
55 static ZEND_FUNCTION(get_called_class);
56 static ZEND_FUNCTION(get_parent_class);
57 static ZEND_FUNCTION(method_exists);
58 static ZEND_FUNCTION(property_exists);
59 static ZEND_FUNCTION(class_exists);
60 static ZEND_FUNCTION(interface_exists);
61 static ZEND_FUNCTION(trait_exists);
62 static ZEND_FUNCTION(function_exists);
63 static ZEND_FUNCTION(class_alias);
64 #if ZEND_DEBUG
65 static ZEND_FUNCTION(leak);
66 static ZEND_FUNCTION(leak_variable);
67 #ifdef ZEND_TEST_EXCEPTIONS
68 static ZEND_FUNCTION(crash);
69 #endif
70 #endif
71 static ZEND_FUNCTION(get_included_files);
72 static ZEND_FUNCTION(is_subclass_of);
73 static ZEND_FUNCTION(is_a);
74 static ZEND_FUNCTION(get_class_vars);
75 static ZEND_FUNCTION(get_object_vars);
76 static ZEND_FUNCTION(get_class_methods);
77 static ZEND_FUNCTION(trigger_error);
78 static ZEND_FUNCTION(set_error_handler);
79 static ZEND_FUNCTION(restore_error_handler);
80 static ZEND_FUNCTION(set_exception_handler);
81 static ZEND_FUNCTION(restore_exception_handler);
82 static ZEND_FUNCTION(get_declared_classes);
83 static ZEND_FUNCTION(get_declared_traits);
84 static ZEND_FUNCTION(get_declared_interfaces);
85 static ZEND_FUNCTION(get_defined_functions);
86 static ZEND_FUNCTION(get_defined_vars);
87 static ZEND_FUNCTION(create_function);
88 static ZEND_FUNCTION(get_resource_type);
89 static ZEND_FUNCTION(get_resources);
90 static ZEND_FUNCTION(get_loaded_extensions);
91 static ZEND_FUNCTION(extension_loaded);
92 static ZEND_FUNCTION(get_extension_funcs);
93 static ZEND_FUNCTION(get_defined_constants);
94 static ZEND_FUNCTION(debug_backtrace);
95 static ZEND_FUNCTION(debug_print_backtrace);
96 #if ZEND_DEBUG
97 static ZEND_FUNCTION(zend_test_func);
98 static ZEND_FUNCTION(zend_test_func2);
99 #ifdef ZTS
100 static ZEND_FUNCTION(zend_thread_id);
101 #endif
102 #endif
103 static ZEND_FUNCTION(gc_mem_caches);
104 static ZEND_FUNCTION(gc_collect_cycles);
105 static ZEND_FUNCTION(gc_enabled);
106 static ZEND_FUNCTION(gc_enable);
107 static ZEND_FUNCTION(gc_disable);
108 
109 /* {{{ arginfo */
110 ZEND_BEGIN_ARG_INFO(arginfo_zend__void, 0)
ZEND_END_ARG_INFO()111 ZEND_END_ARG_INFO()
112 
113 ZEND_BEGIN_ARG_INFO_EX(arginfo_func_get_arg, 0, 0, 1)
114 	ZEND_ARG_INFO(0, arg_num)
115 ZEND_END_ARG_INFO()
116 
117 ZEND_BEGIN_ARG_INFO_EX(arginfo_strlen, 0, 0, 1)
118 	ZEND_ARG_INFO(0, str)
119 ZEND_END_ARG_INFO()
120 
121 ZEND_BEGIN_ARG_INFO_EX(arginfo_strcmp, 0, 0, 2)
122 	ZEND_ARG_INFO(0, str1)
123 	ZEND_ARG_INFO(0, str2)
124 ZEND_END_ARG_INFO()
125 
126 ZEND_BEGIN_ARG_INFO_EX(arginfo_strncmp, 0, 0, 3)
127 	ZEND_ARG_INFO(0, str1)
128 	ZEND_ARG_INFO(0, str2)
129 	ZEND_ARG_INFO(0, len)
130 ZEND_END_ARG_INFO()
131 
132 ZEND_BEGIN_ARG_INFO_EX(arginfo_each, 0, 0, 1)
133 	ZEND_ARG_INFO(1, arr)
134 ZEND_END_ARG_INFO()
135 
136 ZEND_BEGIN_ARG_INFO_EX(arginfo_error_reporting, 0, 0, 0)
137 	ZEND_ARG_INFO(0, new_error_level)
138 ZEND_END_ARG_INFO()
139 
140 ZEND_BEGIN_ARG_INFO_EX(arginfo_define, 0, 0, 2)
141 	ZEND_ARG_INFO(0, constant_name)
142 	ZEND_ARG_INFO(0, value)
143 	ZEND_ARG_INFO(0, case_insensitive)
144 ZEND_END_ARG_INFO()
145 
146 ZEND_BEGIN_ARG_INFO_EX(arginfo_defined, 0, 0, 1)
147 	ZEND_ARG_INFO(0, constant_name)
148 ZEND_END_ARG_INFO()
149 
150 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class, 0, 0, 0)
151 	ZEND_ARG_INFO(0, object)
152 ZEND_END_ARG_INFO()
153 
154 ZEND_BEGIN_ARG_INFO_EX(arginfo_is_subclass_of, 0, 0, 2)
155 	ZEND_ARG_INFO(0, object)
156 	ZEND_ARG_INFO(0, class_name)
157 	ZEND_ARG_INFO(0, allow_string)
158 ZEND_END_ARG_INFO()
159 
160 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_vars, 0, 0, 1)
161 	ZEND_ARG_INFO(0, class_name)
162 ZEND_END_ARG_INFO()
163 
164 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_object_vars, 0, 0, 1)
165 	ZEND_ARG_INFO(0, obj)
166 ZEND_END_ARG_INFO()
167 
168 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_methods, 0, 0, 1)
169 	ZEND_ARG_INFO(0, class)
170 ZEND_END_ARG_INFO()
171 
172 ZEND_BEGIN_ARG_INFO_EX(arginfo_method_exists, 0, 0, 2)
173 	ZEND_ARG_INFO(0, object)
174 	ZEND_ARG_INFO(0, method)
175 ZEND_END_ARG_INFO()
176 
177 ZEND_BEGIN_ARG_INFO_EX(arginfo_property_exists, 0, 0, 2)
178 	ZEND_ARG_INFO(0, object_or_class)
179 	ZEND_ARG_INFO(0, property_name)
180 ZEND_END_ARG_INFO()
181 
182 ZEND_BEGIN_ARG_INFO_EX(arginfo_class_exists, 0, 0, 1)
183 	ZEND_ARG_INFO(0, classname)
184 	ZEND_ARG_INFO(0, autoload)
185 ZEND_END_ARG_INFO()
186 
187 ZEND_BEGIN_ARG_INFO_EX(arginfo_trait_exists, 0, 0, 1)
188 	ZEND_ARG_INFO(0, traitname)
189 	ZEND_ARG_INFO(0, autoload)
190 ZEND_END_ARG_INFO()
191 
192 ZEND_BEGIN_ARG_INFO_EX(arginfo_function_exists, 0, 0, 1)
193 	ZEND_ARG_INFO(0, function_name)
194 ZEND_END_ARG_INFO()
195 
196 ZEND_BEGIN_ARG_INFO_EX(arginfo_class_alias, 0, 0, 2)
197 	ZEND_ARG_INFO(0, user_class_name)
198 	ZEND_ARG_INFO(0, alias_name)
199 	ZEND_ARG_INFO(0, autoload)
200 ZEND_END_ARG_INFO()
201 
202 #if ZEND_DEBUG
203 ZEND_BEGIN_ARG_INFO_EX(arginfo_leak_variable, 0, 0, 1)
204 	ZEND_ARG_INFO(0, variable)
205 	ZEND_ARG_INFO(0, leak_data)
206 ZEND_END_ARG_INFO()
207 #endif
208 
209 ZEND_BEGIN_ARG_INFO_EX(arginfo_trigger_error, 0, 0, 1)
210 	ZEND_ARG_INFO(0, message)
211 	ZEND_ARG_INFO(0, error_type)
212 ZEND_END_ARG_INFO()
213 
214 ZEND_BEGIN_ARG_INFO_EX(arginfo_set_error_handler, 0, 0, 1)
215 	ZEND_ARG_INFO(0, error_handler)
216 	ZEND_ARG_INFO(0, error_types)
217 ZEND_END_ARG_INFO()
218 
219 ZEND_BEGIN_ARG_INFO_EX(arginfo_set_exception_handler, 0, 0, 1)
220 	ZEND_ARG_INFO(0, exception_handler)
221 ZEND_END_ARG_INFO()
222 
223 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_functions, 0, 0, 0)
224 	ZEND_ARG_INFO(0, exclude_disabled)
225 ZEND_END_ARG_INFO()
226 
227 ZEND_BEGIN_ARG_INFO_EX(arginfo_create_function, 0, 0, 2)
228 	ZEND_ARG_INFO(0, args)
229 	ZEND_ARG_INFO(0, code)
230 ZEND_END_ARG_INFO()
231 
232 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resource_type, 0, 0, 1)
233 	ZEND_ARG_INFO(0, res)
234 ZEND_END_ARG_INFO()
235 
236 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resources, 0, 0, 0)
237 	ZEND_ARG_INFO(0, type)
238 ZEND_END_ARG_INFO()
239 
240 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_loaded_extensions, 0, 0, 0)
241 	ZEND_ARG_INFO(0, zend_extensions)
242 ZEND_END_ARG_INFO()
243 
244 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_constants, 0, 0, 0)
245 	ZEND_ARG_INFO(0, categorize)
246 ZEND_END_ARG_INFO()
247 
248 ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_backtrace, 0, 0, 0)
249 	ZEND_ARG_INFO(0, options)
250 	ZEND_ARG_INFO(0, limit)
251 ZEND_END_ARG_INFO()
252 
253 ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_print_backtrace, 0, 0, 0)
254 	ZEND_ARG_INFO(0, options)
255 	ZEND_ARG_INFO(0, limit)
256 ZEND_END_ARG_INFO()
257 
258 ZEND_BEGIN_ARG_INFO_EX(arginfo_extension_loaded, 0, 0, 1)
259 	ZEND_ARG_INFO(0, extension_name)
260 ZEND_END_ARG_INFO()
261 
262 #if ZEND_DEBUG
263 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(arginfo_zend_test_func, IS_ARRAY, NULL, 0)
264 ZEND_END_ARG_INFO()
265 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(arginfo_zend_test_func2, IS_ARRAY, NULL, 1)
266 ZEND_END_ARG_INFO()
267 #endif
268 
269 /* }}} */
270 
271 #if ZEND_DEBUG
272 static zend_object *zend_test_class_new(zend_class_entry *class_type) /* {{{ */ {
273 	zend_object *obj = zend_objects_new(class_type);
274 	obj->handlers = &zend_test_class_handlers;
275 	return obj;
276 }
277 /* }}} */
278 
zend_test_class_method_get(zend_object ** object,zend_string * name,const zval * key)279 static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key) /* {{{ */ {
280 	zend_internal_function *fptr = emalloc(sizeof(zend_internal_function));
281 	fptr->type = ZEND_OVERLOADED_FUNCTION_TEMPORARY;
282 	fptr->num_args = 1;
283 	fptr->arg_info = NULL;
284 	fptr->scope = (*object)->ce;
285 	fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
286 	fptr->function_name = zend_string_copy(name);
287 	fptr->handler = ZEND_FN(zend_test_func);
288 	zend_set_function_arg_flags((zend_function*)fptr);
289 
290 	return (zend_function*)fptr;
291 }
292 /* }}} */
293 
zend_test_class_static_method_get(zend_class_entry * ce,zend_string * name)294 static zend_function *zend_test_class_static_method_get(zend_class_entry *ce, zend_string *name) /* {{{ */ {
295 	zend_internal_function *fptr = emalloc(sizeof(zend_internal_function));
296 	fptr->type = ZEND_OVERLOADED_FUNCTION;
297 	fptr->num_args = 1;
298 	fptr->arg_info = NULL;
299 	fptr->scope = ce;
300 	fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_STATIC;
301 	fptr->function_name = name;
302 	fptr->handler = ZEND_FN(zend_test_func);
303 	zend_set_function_arg_flags((zend_function*)fptr);
304 
305 	return (zend_function*)fptr;
306 }
307 /* }}} */
308 
zend_test_class_call_method(zend_string * method,zend_object * object,INTERNAL_FUNCTION_PARAMETERS)309 static int zend_test_class_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ {
310 	RETVAL_STR(zend_string_copy(method));
311 	return 0;
312 }
313 /* }}} */
314 
ZEND_METHOD(_ZendTestTrait,testMethod)315 static ZEND_METHOD(_ZendTestTrait, testMethod) /* {{{ */ {
316 	RETURN_TRUE;
317 }
318 /* }}} */
319 
320 static zend_function_entry zend_test_trait_methods[] = {
321     ZEND_ME(_ZendTestTrait, testMethod, arginfo_zend__void, ZEND_ACC_PUBLIC)
322     ZEND_FE_END
323 };
324 #endif
325 
326 static const zend_function_entry builtin_functions[] = { /* {{{ */
327 	ZEND_FE(zend_version,		arginfo_zend__void)
328 	ZEND_FE(func_num_args,		arginfo_zend__void)
329 	ZEND_FE(func_get_arg,		arginfo_func_get_arg)
330 	ZEND_FE(func_get_args,		arginfo_zend__void)
331 	ZEND_FE(strlen,			arginfo_strlen)
332 	ZEND_FE(strcmp,			arginfo_strcmp)
333 	ZEND_FE(strncmp,		arginfo_strncmp)
334 	ZEND_FE(strcasecmp,		arginfo_strcmp)
335 	ZEND_FE(strncasecmp,		arginfo_strncmp)
336 	ZEND_FE(each,			arginfo_each)
337 	ZEND_FE(error_reporting,	arginfo_error_reporting)
338 	ZEND_FE(define,			arginfo_define)
339 	ZEND_FE(defined,		arginfo_defined)
340 	ZEND_FE(get_class,		arginfo_get_class)
341 	ZEND_FE(get_called_class,	arginfo_zend__void)
342 	ZEND_FE(get_parent_class,	arginfo_get_class)
343 	ZEND_FE(method_exists,		arginfo_method_exists)
344 	ZEND_FE(property_exists,	arginfo_property_exists)
345 	ZEND_FE(class_exists,		arginfo_class_exists)
346 	ZEND_FE(interface_exists,	arginfo_class_exists)
347 	ZEND_FE(trait_exists,		arginfo_trait_exists)
348 	ZEND_FE(function_exists,	arginfo_function_exists)
349 	ZEND_FE(class_alias,		arginfo_class_alias)
350 #if ZEND_DEBUG
351 	ZEND_FE(leak,				NULL)
352 	ZEND_FE(leak_variable,		arginfo_leak_variable)
353 #ifdef ZEND_TEST_EXCEPTIONS
354 	ZEND_FE(crash,				NULL)
355 #endif
356 #endif
357 	ZEND_FE(get_included_files,	arginfo_zend__void)
358 	ZEND_FALIAS(get_required_files,	get_included_files,		arginfo_zend__void)
359 	ZEND_FE(is_subclass_of,		arginfo_is_subclass_of)
360 	ZEND_FE(is_a,			arginfo_is_subclass_of)
361 	ZEND_FE(get_class_vars,		arginfo_get_class_vars)
362 	ZEND_FE(get_object_vars,	arginfo_get_object_vars)
363 	ZEND_FE(get_class_methods,	arginfo_get_class_methods)
364 	ZEND_FE(trigger_error,		arginfo_trigger_error)
365 	ZEND_FALIAS(user_error,		trigger_error,		arginfo_trigger_error)
366 	ZEND_FE(set_error_handler,		arginfo_set_error_handler)
367 	ZEND_FE(restore_error_handler,		arginfo_zend__void)
368 	ZEND_FE(set_exception_handler,		arginfo_set_exception_handler)
369 	ZEND_FE(restore_exception_handler,	arginfo_zend__void)
370 	ZEND_FE(get_declared_classes, 		arginfo_zend__void)
371 	ZEND_FE(get_declared_traits, 		arginfo_zend__void)
372 	ZEND_FE(get_declared_interfaces, 	arginfo_zend__void)
373 	ZEND_FE(get_defined_functions, 		arginfo_get_defined_functions)
374 	ZEND_FE(get_defined_vars,		arginfo_zend__void)
375 	ZEND_FE(create_function,		arginfo_create_function)
376 	ZEND_FE(get_resource_type,		arginfo_get_resource_type)
377 	ZEND_FE(get_resources,			arginfo_get_resources)
378 	ZEND_FE(get_loaded_extensions,		arginfo_get_loaded_extensions)
379 	ZEND_FE(extension_loaded,		arginfo_extension_loaded)
380 	ZEND_FE(get_extension_funcs,		arginfo_extension_loaded)
381 	ZEND_FE(get_defined_constants,		arginfo_get_defined_constants)
382 	ZEND_FE(debug_backtrace, 		arginfo_debug_backtrace)
383 	ZEND_FE(debug_print_backtrace, 		arginfo_debug_print_backtrace)
384 #if ZEND_DEBUG
385 	ZEND_FE(zend_test_func,		arginfo_zend_test_func)
386 	ZEND_FE(zend_test_func2,	arginfo_zend_test_func2)
387 #ifdef ZTS
388 	ZEND_FE(zend_thread_id,		NULL)
389 #endif
390 #endif
391 	ZEND_FE(gc_mem_caches,      arginfo_zend__void)
392 	ZEND_FE(gc_collect_cycles, 	arginfo_zend__void)
393 	ZEND_FE(gc_enabled, 		arginfo_zend__void)
394 	ZEND_FE(gc_enable, 		arginfo_zend__void)
395 	ZEND_FE(gc_disable, 		arginfo_zend__void)
396 	ZEND_FE_END
397 };
398 /* }}} */
399 
ZEND_MINIT_FUNCTION(core)400 ZEND_MINIT_FUNCTION(core) { /* {{{ */
401 	zend_class_entry class_entry;
402 
403 	INIT_CLASS_ENTRY(class_entry, "stdClass", NULL);
404 	zend_standard_class_def = zend_register_internal_class(&class_entry);
405 
406 	zend_register_default_classes();
407 
408 #if ZEND_DEBUG
409 	INIT_CLASS_ENTRY(class_entry, "_ZendTestInterface", NULL);
410 	zend_test_interface = zend_register_internal_interface(&class_entry);
411 	zend_declare_class_constant_long(zend_test_interface, ZEND_STRL("DUMMY"), 0);
412 	INIT_CLASS_ENTRY(class_entry, "_ZendTestClass", NULL);
413 	zend_test_class = zend_register_internal_class_ex(&class_entry, NULL);
414 	zend_class_implements(zend_test_class, 1, zend_test_interface);
415 	zend_test_class->create_object = zend_test_class_new;
416 	zend_test_class->get_static_method = zend_test_class_static_method_get;
417 
418 	memcpy(&zend_test_class_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
419 	zend_test_class_handlers.get_method = zend_test_class_method_get;
420 	zend_test_class_handlers.call_method = zend_test_class_call_method;
421 
422 	INIT_CLASS_ENTRY(class_entry, "_ZendTestTrait", zend_test_trait_methods);
423 	zend_test_trait = zend_register_internal_class(&class_entry);
424 	zend_test_trait->ce_flags |= ZEND_ACC_TRAIT;
425 	zend_declare_property_null(zend_test_trait, "testProp", sizeof("testProp")-1, ZEND_ACC_PUBLIC);
426 #endif
427 
428 	return SUCCESS;
429 }
430 /* }}} */
431 
432 zend_module_entry zend_builtin_module = { /* {{{ */
433     STANDARD_MODULE_HEADER,
434 	"Core",
435 	builtin_functions,
436 	ZEND_MINIT(core),
437 	NULL,
438 	NULL,
439 	NULL,
440 	NULL,
441 	ZEND_VERSION,
442 	STANDARD_MODULE_PROPERTIES
443 };
444 /* }}} */
445 
zend_startup_builtin_functions(void)446 int zend_startup_builtin_functions(void) /* {{{ */
447 {
448 	zend_builtin_module.module_number = 0;
449 	zend_builtin_module.type = MODULE_PERSISTENT;
450 	return (EG(current_module) = zend_register_module_ex(&zend_builtin_module)) == NULL ? FAILURE : SUCCESS;
451 }
452 /* }}} */
453 
454 /* {{{ proto string zend_version(void)
455    Get the version of the Zend Engine */
ZEND_FUNCTION(zend_version)456 ZEND_FUNCTION(zend_version)
457 {
458 	RETURN_STRINGL(ZEND_VERSION, sizeof(ZEND_VERSION)-1);
459 }
460 /* }}} */
461 
462 /* {{{ proto int gc_mem_caches(void)
463    Reclaims memory used by MM caches.
464    Returns number of freed bytes */
ZEND_FUNCTION(gc_mem_caches)465 ZEND_FUNCTION(gc_mem_caches)
466 {
467 	RETURN_LONG(zend_mm_gc(zend_mm_get_heap()));
468 }
469 /* }}} */
470 
471 /* {{{ proto int gc_collect_cycles(void)
472    Forces collection of any existing garbage cycles.
473    Returns number of freed zvals */
ZEND_FUNCTION(gc_collect_cycles)474 ZEND_FUNCTION(gc_collect_cycles)
475 {
476 	RETURN_LONG(gc_collect_cycles());
477 }
478 /* }}} */
479 
480 /* {{{ proto void gc_enabled(void)
481    Returns status of the circular reference collector */
ZEND_FUNCTION(gc_enabled)482 ZEND_FUNCTION(gc_enabled)
483 {
484 	RETURN_BOOL(GC_G(gc_enabled));
485 }
486 /* }}} */
487 
488 /* {{{ proto void gc_enable(void)
489    Activates the circular reference collector */
ZEND_FUNCTION(gc_enable)490 ZEND_FUNCTION(gc_enable)
491 {
492 	zend_string *key = zend_string_init("zend.enable_gc", sizeof("zend.enable_gc")-1, 0);
493 	zend_alter_ini_entry_chars(key, "1", sizeof("1")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
494 	zend_string_release(key);
495 }
496 /* }}} */
497 
498 /* {{{ proto void gc_disable(void)
499    Deactivates the circular reference collector */
ZEND_FUNCTION(gc_disable)500 ZEND_FUNCTION(gc_disable)
501 {
502 	zend_string *key = zend_string_init("zend.enable_gc", sizeof("zend.enable_gc")-1, 0);
503 	zend_alter_ini_entry_chars(key, "0", sizeof("0")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
504 	zend_string_release(key);
505 }
506 /* }}} */
507 
508 /* {{{ proto int func_num_args(void)
509    Get the number of arguments that were passed to the function */
ZEND_FUNCTION(func_num_args)510 ZEND_FUNCTION(func_num_args)
511 {
512 	zend_execute_data *ex = EX(prev_execute_data);
513 
514 	if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) {
515 		zend_error(E_WARNING, "func_num_args():  Called from the global scope - no function context");
516 		RETURN_LONG(-1);
517 	}
518 
519 	if (zend_forbid_dynamic_call("func_num_args()") == FAILURE) {
520 		RETURN_LONG(-1);
521 	}
522 
523 	RETURN_LONG(ZEND_CALL_NUM_ARGS(ex));
524 }
525 /* }}} */
526 
527 /* {{{ proto mixed func_get_arg(int arg_num)
528    Get the $arg_num'th argument that was passed to the function */
ZEND_FUNCTION(func_get_arg)529 ZEND_FUNCTION(func_get_arg)
530 {
531 	uint32_t arg_count, first_extra_arg;
532 	zval *arg;
533 	zend_long requested_offset;
534 	zend_execute_data *ex;
535 
536 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &requested_offset) == FAILURE) {
537 		return;
538 	}
539 
540 	if (requested_offset < 0) {
541 		zend_error(E_WARNING, "func_get_arg():  The argument number should be >= 0");
542 		RETURN_FALSE;
543 	}
544 
545 	ex = EX(prev_execute_data);
546 	if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) {
547 		zend_error(E_WARNING, "func_get_arg():  Called from the global scope - no function context");
548 		RETURN_FALSE;
549 	}
550 
551 	if (zend_forbid_dynamic_call("func_get_arg()") == FAILURE) {
552 		RETURN_FALSE;
553 	}
554 
555 	arg_count = ZEND_CALL_NUM_ARGS(ex);
556 
557 	if ((zend_ulong)requested_offset >= arg_count) {
558 		zend_error(E_WARNING, "func_get_arg():  Argument " ZEND_LONG_FMT " not passed to function", requested_offset);
559 		RETURN_FALSE;
560 	}
561 
562 	first_extra_arg = ex->func->op_array.num_args;
563 	if ((zend_ulong)requested_offset >= first_extra_arg && (ZEND_CALL_NUM_ARGS(ex) > first_extra_arg)) {
564 		arg = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T) + (requested_offset - first_extra_arg);
565 	} else {
566 		arg = ZEND_CALL_ARG(ex, requested_offset + 1);
567 	}
568 	if (EXPECTED(!Z_ISUNDEF_P(arg))) {
569 		ZVAL_DEREF(arg);
570 		ZVAL_COPY(return_value, arg);
571 	}
572 }
573 /* }}} */
574 
575 /* {{{ proto array func_get_args()
576    Get an array of the arguments that were passed to the function */
ZEND_FUNCTION(func_get_args)577 ZEND_FUNCTION(func_get_args)
578 {
579 	zval *p, *q;
580 	uint32_t arg_count, first_extra_arg;
581 	uint32_t i;
582 	zend_execute_data *ex = EX(prev_execute_data);
583 
584 	if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) {
585 		zend_error(E_WARNING, "func_get_args():  Called from the global scope - no function context");
586 		RETURN_FALSE;
587 	}
588 
589 	if (zend_forbid_dynamic_call("func_get_args()") == FAILURE) {
590 		RETURN_FALSE;
591 	}
592 
593 	arg_count = ZEND_CALL_NUM_ARGS(ex);
594 
595 	array_init_size(return_value, arg_count);
596 	if (arg_count) {
597 		first_extra_arg = ex->func->op_array.num_args;
598 		zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
599 		ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
600 			i = 0;
601 			p = ZEND_CALL_ARG(ex, 1);
602 			if (arg_count > first_extra_arg) {
603 				while (i < first_extra_arg) {
604 					q = p;
605 					if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
606 						ZVAL_DEREF(q);
607 						if (Z_OPT_REFCOUNTED_P(q)) {
608 							Z_ADDREF_P(q);
609 						}
610 					} else {
611 						q = &EG(uninitialized_zval);
612 					}
613 					ZEND_HASH_FILL_ADD(q);
614 					p++;
615 					i++;
616 				}
617 				p = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T);
618 			}
619 			while (i < arg_count) {
620 				q = p;
621 				if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
622 					ZVAL_DEREF(q);
623 					if (Z_OPT_REFCOUNTED_P(q)) {
624 						Z_ADDREF_P(q);
625 					}
626 				} else {
627 					q = &EG(uninitialized_zval);
628 				}
629 				ZEND_HASH_FILL_ADD(q);
630 				p++;
631 				i++;
632 			}
633 		} ZEND_HASH_FILL_END();
634 		Z_ARRVAL_P(return_value)->nNumOfElements = arg_count;
635 	}
636 }
637 /* }}} */
638 
639 /* {{{ proto int strlen(string str)
640    Get string length
641    Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
ZEND_FUNCTION(strlen)642 ZEND_FUNCTION(strlen)
643 {
644 	zend_string *s;
645 
646 	ZEND_PARSE_PARAMETERS_START(1, 1)
647 		Z_PARAM_STR(s)
648 	ZEND_PARSE_PARAMETERS_END();
649 
650 	RETVAL_LONG(ZSTR_LEN(s));
651 }
652 /* }}} */
653 
654 /* {{{ proto int strcmp(string str1, string str2)
655    Binary safe string comparison */
ZEND_FUNCTION(strcmp)656 ZEND_FUNCTION(strcmp)
657 {
658 	zend_string *s1, *s2;
659 
660 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &s1, &s2) == FAILURE) {
661 		return;
662 	}
663 
664 	RETURN_LONG(zend_binary_strcmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)));
665 }
666 /* }}} */
667 
668 /* {{{ proto int strncmp(string str1, string str2, int len)
669    Binary safe string comparison */
ZEND_FUNCTION(strncmp)670 ZEND_FUNCTION(strncmp)
671 {
672 	zend_string *s1, *s2;
673 	zend_long len;
674 
675 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSl", &s1, &s2, &len) == FAILURE) {
676 		return;
677 	}
678 
679 	if (len < 0) {
680 		zend_error(E_WARNING, "Length must be greater than or equal to 0");
681 		RETURN_FALSE;
682 	}
683 
684 	RETURN_LONG(zend_binary_strncmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), len));
685 }
686 /* }}} */
687 
688 /* {{{ proto int strcasecmp(string str1, string str2)
689    Binary safe case-insensitive string comparison */
ZEND_FUNCTION(strcasecmp)690 ZEND_FUNCTION(strcasecmp)
691 {
692 	zend_string *s1, *s2;
693 
694 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &s1, &s2) == FAILURE) {
695 		return;
696 	}
697 
698 	RETURN_LONG(zend_binary_strcasecmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)));
699 }
700 /* }}} */
701 
702 /* {{{ proto int strncasecmp(string str1, string str2, int len)
703    Binary safe string comparison */
ZEND_FUNCTION(strncasecmp)704 ZEND_FUNCTION(strncasecmp)
705 {
706 	zend_string *s1, *s2;
707 	zend_long len;
708 
709 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSl", &s1, &s2, &len) == FAILURE) {
710 		return;
711 	}
712 
713 	if (len < 0) {
714 		zend_error(E_WARNING, "Length must be greater than or equal to 0");
715 		RETURN_FALSE;
716 	}
717 
718 	RETURN_LONG(zend_binary_strncasecmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), len));
719 }
720 /* }}} */
721 
722 /* {{{ proto mixed each(array &arr)
723    Return the currently pointed key..value pair in the passed array, and advance the pointer to the next element, or false if there is no element at this place */
ZEND_FUNCTION(each)724 ZEND_FUNCTION(each)
725 {
726 	zval *array, *entry, tmp;
727 	zend_ulong num_key;
728 	HashTable *target_hash;
729 	zend_string *key;
730 
731 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "z/", &array) == FAILURE) {
732 		return;
733 	}
734 
735 	target_hash = HASH_OF(array);
736 	if (!target_hash) {
737 		zend_error(E_WARNING,"Variable passed to each() is not an array or object");
738 		return;
739 	}
740 	while (1) {
741 		entry = zend_hash_get_current_data(target_hash);
742 		if (!entry) {
743 			RETURN_FALSE;
744 		} else if (Z_TYPE_P(entry) == IS_INDIRECT) {
745 			entry = Z_INDIRECT_P(entry);
746 			if (Z_TYPE_P(entry) == IS_UNDEF) {
747 				zend_hash_move_forward(target_hash);
748 				continue;
749 			}
750 		}
751 		break;
752 	}
753 	array_init_size(return_value, 4);
754 	zend_hash_real_init(Z_ARRVAL_P(return_value), 0);
755 
756 	/* add value elements */
757 	if (Z_ISREF_P(entry)) {
758 		ZVAL_DUP(&tmp, Z_REFVAL_P(entry));
759 		entry = &tmp;
760 		if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
761 	} else {
762 		if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
763 		if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
764 	}
765 	zend_hash_index_add_new(Z_ARRVAL_P(return_value), 1, entry);
766 	zend_hash_add_new(Z_ARRVAL_P(return_value), CG(known_strings)[ZEND_STR_VALUE], entry);
767 
768 	/* add the key elements */
769 	if (zend_hash_get_current_key(target_hash, &key, &num_key) == HASH_KEY_IS_STRING) {
770 		ZVAL_STR_COPY(&tmp, key);
771 		if (Z_REFCOUNTED(tmp)) Z_ADDREF(tmp);
772 	} else {
773 		ZVAL_LONG(&tmp, num_key);
774 	}
775 	zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp);
776 	zend_hash_add_new(Z_ARRVAL_P(return_value), CG(known_strings)[ZEND_STR_KEY], &tmp);
777 	zend_hash_move_forward(target_hash);
778 }
779 /* }}} */
780 
781 /* {{{ proto int error_reporting([int new_error_level])
782    Return the current error_reporting level, and if an argument was passed - change to the new level */
ZEND_FUNCTION(error_reporting)783 ZEND_FUNCTION(error_reporting)
784 {
785 	zval *err = NULL;
786 	int old_error_reporting;
787 
788 	ZEND_PARSE_PARAMETERS_START(0, 1)
789 		Z_PARAM_OPTIONAL
790 		Z_PARAM_ZVAL(err)
791 	ZEND_PARSE_PARAMETERS_END();
792 
793 	old_error_reporting = EG(error_reporting);
794 	if (ZEND_NUM_ARGS() != 0) {
795 		zend_string *new_val = zval_get_string(err);
796 		do {
797 			zend_ini_entry *p = EG(error_reporting_ini_entry);
798 
799 			if (!p) {
800 				p = zend_hash_find_ptr(EG(ini_directives), CG(known_strings)[ZEND_STR_ERROR_REPORTING]);
801 				if (p) {
802 					EG(error_reporting_ini_entry) = p;
803 				} else {
804 					break;
805 				}
806 			}
807 			if (!p->modified) {
808 				if (!EG(modified_ini_directives)) {
809 					ALLOC_HASHTABLE(EG(modified_ini_directives));
810 					zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
811 				}
812 				if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), CG(known_strings)[ZEND_STR_ERROR_REPORTING], p) != NULL)) {
813 					p->orig_value = p->value;
814 					p->orig_modifiable = p->modifiable;
815 					p->modified = 1;
816 				}
817 			} else if (p->orig_value != p->value) {
818 				zend_string_release(p->value);
819 			}
820 
821 			p->value = new_val;
822 			if (Z_TYPE_P(err) == IS_LONG) {
823 				EG(error_reporting) = Z_LVAL_P(err);
824 			} else {
825 				EG(error_reporting) = atoi(ZSTR_VAL(p->value));
826 			}
827 		} while (0);
828 	}
829 
830 	RETVAL_LONG(old_error_reporting);
831 }
832 /* }}} */
833 
validate_constant_array(HashTable * ht)834 static int validate_constant_array(HashTable *ht) /* {{{ */
835 {
836 	int ret = 1;
837 	zval *val;
838 
839 	ht->u.v.nApplyCount++;
840 	ZEND_HASH_FOREACH_VAL_IND(ht, val) {
841 		ZVAL_DEREF(val);
842 		if (Z_REFCOUNTED_P(val)) {
843 			if (Z_TYPE_P(val) == IS_ARRAY) {
844 				if (!Z_IMMUTABLE_P(val)) {
845 					if (Z_ARRVAL_P(val)->u.v.nApplyCount > 0) {
846 						zend_error(E_WARNING, "Constants cannot be recursive arrays");
847 						ret = 0;
848 						break;
849 					} else if (!validate_constant_array(Z_ARRVAL_P(val))) {
850 						ret = 0;
851 						break;
852 					}
853 				}
854 			} else if (Z_TYPE_P(val) != IS_STRING && Z_TYPE_P(val) != IS_RESOURCE) {
855 				zend_error(E_WARNING, "Constants may only evaluate to scalar values or arrays");
856 				ret = 0;
857 				break;
858 			}
859 		}
860 	} ZEND_HASH_FOREACH_END();
861 	ht->u.v.nApplyCount--;
862 	return ret;
863 }
864 /* }}} */
865 
copy_constant_array(zval * dst,zval * src)866 static void copy_constant_array(zval *dst, zval *src) /* {{{ */
867 {
868 	zend_string *key;
869 	zend_ulong idx;
870 	zval *new_val, *val;
871 
872 	array_init_size(dst, zend_hash_num_elements(Z_ARRVAL_P(src)));
873 	ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(src), idx, key, val) {
874 		/* constant arrays can't contain references */
875 		ZVAL_DEREF(val);
876 		if (key) {
877 			new_val = zend_hash_add_new(Z_ARRVAL_P(dst), key, val);
878 		} else {
879 			new_val = zend_hash_index_add_new(Z_ARRVAL_P(dst), idx, val);
880 		}
881 		if (Z_TYPE_P(val) == IS_ARRAY) {
882 			if (!Z_IMMUTABLE_P(val)) {
883 				copy_constant_array(new_val, val);
884 			}
885 		} else if (Z_REFCOUNTED_P(val)) {
886 			Z_ADDREF_P(val);
887 		}
888 	} ZEND_HASH_FOREACH_END();
889 }
890 /* }}} */
891 
892 /* {{{ proto bool define(string constant_name, mixed value[, boolean case_insensitive])
893    Define a new constant */
ZEND_FUNCTION(define)894 ZEND_FUNCTION(define)
895 {
896 	zend_string *name;
897 	zval *val, val_free;
898 	zend_bool non_cs = 0;
899 	int case_sensitive = CONST_CS;
900 	zend_constant c;
901 
902 	ZEND_PARSE_PARAMETERS_START(2, 3)
903 		Z_PARAM_STR(name)
904 		Z_PARAM_ZVAL(val)
905 		Z_PARAM_OPTIONAL
906 		Z_PARAM_BOOL(non_cs)
907 	ZEND_PARSE_PARAMETERS_END();
908 
909 	if (non_cs) {
910 		case_sensitive = 0;
911 	}
912 
913 	/* class constant, check if there is name and make sure class is valid & exists */
914 	if (zend_memnstr(ZSTR_VAL(name), "::", sizeof("::") - 1, ZSTR_VAL(name) + ZSTR_LEN(name))) {
915 		zend_error(E_WARNING, "Class constants cannot be defined or redefined");
916 		RETURN_FALSE;
917 	}
918 
919 	ZVAL_UNDEF(&val_free);
920 
921 repeat:
922 	switch (Z_TYPE_P(val)) {
923 		case IS_LONG:
924 		case IS_DOUBLE:
925 		case IS_STRING:
926 		case IS_FALSE:
927 		case IS_TRUE:
928 		case IS_NULL:
929 		case IS_RESOURCE:
930 			break;
931 		case IS_ARRAY:
932 			if (!Z_IMMUTABLE_P(val)) {
933 				if (!validate_constant_array(Z_ARRVAL_P(val))) {
934 					RETURN_FALSE;
935 				} else {
936 					copy_constant_array(&c.value, val);
937 					goto register_constant;
938 				}
939 			}
940 			break;
941 		case IS_OBJECT:
942 			if (Z_TYPE(val_free) == IS_UNDEF) {
943 				if (Z_OBJ_HT_P(val)->get) {
944 					zval rv;
945 					val = Z_OBJ_HT_P(val)->get(val, &rv);
946 					ZVAL_COPY_VALUE(&val_free, val);
947 					goto repeat;
948 				} else if (Z_OBJ_HT_P(val)->cast_object) {
949 					if (Z_OBJ_HT_P(val)->cast_object(val, &val_free, IS_STRING) == SUCCESS) {
950 						val = &val_free;
951 						break;
952 					}
953 				}
954 			}
955 			/* no break */
956 		default:
957 			zend_error(E_WARNING, "Constants may only evaluate to scalar values or arrays");
958 			zval_ptr_dtor(&val_free);
959 			RETURN_FALSE;
960 	}
961 
962 	ZVAL_DUP(&c.value, val);
963 	zval_ptr_dtor(&val_free);
964 register_constant:
965 	c.flags = case_sensitive; /* non persistent */
966 	c.name = zend_string_copy(name);
967 	c.module_number = PHP_USER_CONSTANT;
968 	if (zend_register_constant(&c) == SUCCESS) {
969 		RETURN_TRUE;
970 	} else {
971 		RETURN_FALSE;
972 	}
973 }
974 /* }}} */
975 
976 /* {{{ proto bool defined(string constant_name)
977    Check whether a constant exists
978    Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
ZEND_FUNCTION(defined)979 ZEND_FUNCTION(defined)
980 {
981 	zend_string *name;
982 
983 	ZEND_PARSE_PARAMETERS_START(1, 1)
984 		Z_PARAM_STR(name)
985 	ZEND_PARSE_PARAMETERS_END();
986 
987 	if (zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT)) {
988 		RETURN_TRUE;
989 	} else {
990 		RETURN_FALSE;
991 	}
992 }
993 /* }}} */
994 
995 /* {{{ proto string get_class([object object])
996    Retrieves the class name */
ZEND_FUNCTION(get_class)997 ZEND_FUNCTION(get_class)
998 {
999 	zval *obj = NULL;
1000 
1001 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o!", &obj) == FAILURE) {
1002 		RETURN_FALSE;
1003 	}
1004 
1005 	if (!obj) {
1006 		zend_class_entry *scope = zend_get_executed_scope();
1007 
1008 		if (scope) {
1009 			RETURN_STR_COPY(scope->name);
1010 		} else {
1011 			zend_error(E_WARNING, "get_class() called without object from outside a class");
1012 			RETURN_FALSE;
1013 		}
1014 	}
1015 
1016 	RETURN_STR_COPY(Z_OBJCE_P(obj)->name);
1017 }
1018 /* }}} */
1019 
1020 /* {{{ proto string get_called_class()
1021    Retrieves the "Late Static Binding" class name */
ZEND_FUNCTION(get_called_class)1022 ZEND_FUNCTION(get_called_class)
1023 {
1024 	zend_class_entry *called_scope;
1025 
1026 	if (zend_parse_parameters_none() == FAILURE) {
1027 		return;
1028 	}
1029 
1030 	called_scope = zend_get_called_scope(execute_data);
1031 	if (called_scope) {
1032 		RETURN_STR_COPY(called_scope->name);
1033 	} else {
1034 		zend_class_entry *scope = zend_get_executed_scope();
1035 		if (!scope)  {
1036 			zend_error(E_WARNING, "get_called_class() called from outside a class");
1037 		}
1038 	}
1039 	RETURN_FALSE;
1040 }
1041 /* }}} */
1042 
1043 /* {{{ proto mixed get_parent_class([mixed object])
1044    Retrieves the parent class name for object or class or current scope or false if not in a scope. */
ZEND_FUNCTION(get_parent_class)1045 ZEND_FUNCTION(get_parent_class)
1046 {
1047 	zval *arg;
1048 	zend_class_entry *ce = NULL;
1049 
1050 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|z", &arg) == FAILURE) {
1051 		return;
1052 	}
1053 
1054 	if (!ZEND_NUM_ARGS()) {
1055 		ce = zend_get_executed_scope();
1056 		if (ce && ce->parent) {
1057 			RETURN_STR_COPY(ce->parent->name);
1058 		} else {
1059 			RETURN_FALSE;
1060 		}
1061 	}
1062 
1063 	if (Z_TYPE_P(arg) == IS_OBJECT) {
1064 		ce = Z_OBJ_P(arg)->ce;
1065 	} else if (Z_TYPE_P(arg) == IS_STRING) {
1066 	    ce = zend_lookup_class(Z_STR_P(arg));
1067 	}
1068 
1069 	if (ce && ce->parent) {
1070 		RETURN_STR_COPY(ce->parent->name);
1071 	} else {
1072 		RETURN_FALSE;
1073 	}
1074 }
1075 /* }}} */
1076 
is_a_impl(INTERNAL_FUNCTION_PARAMETERS,zend_bool only_subclass)1077 static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass) /* {{{ */
1078 {
1079 	zval *obj;
1080 	zend_string *class_name;
1081 	zend_class_entry *instance_ce;
1082 	zend_class_entry *ce;
1083 	zend_bool allow_string = only_subclass;
1084 	zend_bool retval;
1085 
1086 	ZEND_PARSE_PARAMETERS_START(2, 3)
1087 		Z_PARAM_ZVAL(obj)
1088 		Z_PARAM_STR(class_name)
1089 		Z_PARAM_OPTIONAL
1090 		Z_PARAM_BOOL(allow_string)
1091 	ZEND_PARSE_PARAMETERS_END();
1092 	/*
1093 	 * allow_string - is_a default is no, is_subclass_of is yes.
1094 	 *   if it's allowed, then the autoloader will be called if the class does not exist.
1095 	 *   default behaviour is different, as 'is_a' used to be used to test mixed return values
1096 	 *   and there is no easy way to deprecate this.
1097 	 */
1098 
1099 	if (allow_string && Z_TYPE_P(obj) == IS_STRING) {
1100 		instance_ce = zend_lookup_class(Z_STR_P(obj));
1101 		if (!instance_ce) {
1102 			RETURN_FALSE;
1103 		}
1104 	} else if (Z_TYPE_P(obj) == IS_OBJECT) {
1105 		instance_ce = Z_OBJCE_P(obj);
1106 	} else {
1107 		RETURN_FALSE;
1108 	}
1109 
1110 	if (!only_subclass && EXPECTED(zend_string_equals(instance_ce->name, class_name))) {
1111 		retval = 1;
1112 	} else {
1113 		ce = zend_lookup_class_ex(class_name, NULL, 0);
1114 		if (!ce) {
1115 			retval = 0;
1116 		} else {
1117 			if (only_subclass && instance_ce == ce) {
1118 				retval = 0;
1119 			} else {
1120 				retval = instanceof_function(instance_ce, ce);
1121 			}
1122 		}
1123 	}
1124 
1125 	RETURN_BOOL(retval);
1126 }
1127 /* }}} */
1128 
1129 /* {{{ proto bool is_subclass_of(mixed object_or_string, string class_name [, bool allow_string])
1130    Returns true if the object has this class as one of its parents */
ZEND_FUNCTION(is_subclass_of)1131 ZEND_FUNCTION(is_subclass_of)
1132 {
1133 	is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1134 }
1135 /* }}} */
1136 
1137 /* {{{ proto bool is_a(mixed object_or_string, string class_name [, bool allow_string])
1138    Returns true if the first argument is an object and is this class or has this class as one of its parents, */
ZEND_FUNCTION(is_a)1139 ZEND_FUNCTION(is_a)
1140 {
1141 	is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1142 }
1143 /* }}} */
1144 
1145 /* {{{ add_class_vars */
add_class_vars(zend_class_entry * scope,zend_class_entry * ce,int statics,zval * return_value)1146 static void add_class_vars(zend_class_entry *scope, zend_class_entry *ce, int statics, zval *return_value)
1147 {
1148 	zend_property_info *prop_info;
1149 	zval *prop, prop_copy;
1150 	zend_string *key;
1151 
1152 	ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
1153 		if (((prop_info->flags & ZEND_ACC_SHADOW) &&
1154 		     prop_info->ce != scope) ||
1155 		    ((prop_info->flags & ZEND_ACC_PROTECTED) &&
1156 		     !zend_check_protected(prop_info->ce, scope)) ||
1157 		    ((prop_info->flags & ZEND_ACC_PRIVATE) &&
1158 		      ce != scope &&
1159 			  prop_info->ce != scope)) {
1160 			continue;
1161 		}
1162 		prop = NULL;
1163 		if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
1164 			prop = &ce->default_static_members_table[prop_info->offset];
1165 		} else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
1166 			prop = &ce->default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
1167 		}
1168 		if (!prop || Z_TYPE_P(prop) == IS_UNDEF) {
1169 			continue;
1170 		}
1171 
1172 		/* copy: enforce read only access */
1173 		ZVAL_DEREF(prop);
1174 		if (UNEXPECTED(Z_COPYABLE_P(prop))) {
1175 			ZVAL_DUP(&prop_copy, prop);
1176 			prop = &prop_copy;
1177 		} else {
1178 			Z_TRY_ADDREF_P(prop);
1179 		}
1180 
1181 		/* this is necessary to make it able to work with default array
1182 		 * properties, returned to user */
1183 		if (Z_OPT_CONSTANT_P(prop)) {
1184 			if (UNEXPECTED(zval_update_constant_ex(prop, NULL) != SUCCESS)) {
1185 				return;
1186 			}
1187 		}
1188 
1189 		zend_hash_add_new(Z_ARRVAL_P(return_value), key, prop);
1190 	} ZEND_HASH_FOREACH_END();
1191 }
1192 /* }}} */
1193 
1194 /* {{{ proto array get_class_vars(string class_name)
1195    Returns an array of default properties of the class. */
ZEND_FUNCTION(get_class_vars)1196 ZEND_FUNCTION(get_class_vars)
1197 {
1198 	zend_string *class_name;
1199 	zend_class_entry *ce, *scope;
1200 
1201 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &class_name) == FAILURE) {
1202 		return;
1203 	}
1204 
1205 	ce = zend_lookup_class(class_name);
1206 	if (!ce) {
1207 		RETURN_FALSE;
1208 	} else {
1209 		array_init(return_value);
1210 		if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
1211 			if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
1212 				return;
1213 			}
1214 		}
1215 		scope = zend_get_executed_scope();
1216 		add_class_vars(scope, ce, 0, return_value);
1217 		add_class_vars(scope, ce, 1, return_value);
1218 	}
1219 }
1220 /* }}} */
1221 
1222 /* {{{ proto array get_object_vars(object obj)
1223    Returns an array of object properties */
ZEND_FUNCTION(get_object_vars)1224 ZEND_FUNCTION(get_object_vars)
1225 {
1226 	zval *obj;
1227 	zval *value;
1228 	HashTable *properties;
1229 	zend_string *key;
1230 	zend_object *zobj;
1231 	zend_ulong index;
1232 	zend_bool fast_copy = 0;
1233 
1234 	ZEND_PARSE_PARAMETERS_START(1, 1)
1235 		Z_PARAM_OBJECT(obj)
1236 	ZEND_PARSE_PARAMETERS_END();
1237 
1238 	if (Z_OBJ_HT_P(obj)->get_properties == NULL) {
1239 		RETURN_FALSE;
1240 	}
1241 
1242 	properties = Z_OBJ_HT_P(obj)->get_properties(obj);
1243 
1244 	if (properties == NULL) {
1245 		RETURN_FALSE;
1246 	}
1247 
1248 	zobj = Z_OBJ_P(obj);
1249 
1250 	if (!zobj->ce->default_properties_count && properties == zobj->properties && !ZEND_HASH_GET_APPLY_COUNT(properties)) {
1251 		fast_copy = 1;
1252 		/* Check if the object has a numeric property, See Bug 73998 */
1253 		ZEND_HASH_FOREACH_STR_KEY(properties, key) {
1254 			if (key && ZEND_HANDLE_NUMERIC(key, index)) {
1255 				fast_copy = 0;
1256 				break;
1257 			}
1258 		} ZEND_HASH_FOREACH_END();
1259 	}
1260 
1261 	if (fast_copy) {
1262 		if (EXPECTED(zobj->handlers == &std_object_handlers)) {
1263 			if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) {
1264 				GC_REFCOUNT(properties)++;
1265 			}
1266 			RETURN_ARR(properties);
1267 		}
1268 		RETURN_ARR(zend_array_dup(properties));
1269 	} else {
1270 		array_init_size(return_value, zend_hash_num_elements(properties));
1271 
1272 		ZEND_HASH_FOREACH_STR_KEY_VAL_IND(properties, key, value) {
1273 			if (key) {
1274 				if (zend_check_property_access(zobj, key) == SUCCESS) {
1275 					if (Z_ISREF_P(value) && Z_REFCOUNT_P(value) == 1) {
1276 						value = Z_REFVAL_P(value);
1277 					}
1278 					if (Z_REFCOUNTED_P(value)) {
1279 						Z_ADDREF_P(value);
1280 					}
1281 					if (ZSTR_VAL(key)[0] == 0) {
1282 						const char *prop_name, *class_name;
1283 						size_t prop_len;
1284 						zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_len);
1285 						zend_hash_str_add_new(Z_ARRVAL_P(return_value), prop_name, prop_len, value);
1286 					} else {
1287 						zend_symtable_add_new(Z_ARRVAL_P(return_value), key, value);
1288 					}
1289 				}
1290 			}
1291 		} ZEND_HASH_FOREACH_END();
1292 	}
1293 }
1294 /* }}} */
1295 
same_name(zend_string * key,zend_string * name)1296 static int same_name(zend_string *key, zend_string *name) /* {{{ */
1297 {
1298 	zend_string *lcname;
1299 	int ret;
1300 
1301 	if (key == name) {
1302 		return 1;
1303 	}
1304 	if (ZSTR_LEN(key) != ZSTR_LEN(name)) {
1305 		return 0;
1306 	}
1307 	lcname = zend_string_tolower(name);
1308 	ret = memcmp(ZSTR_VAL(lcname), ZSTR_VAL(key), ZSTR_LEN(key)) == 0;
1309 	zend_string_release(lcname);
1310 	return ret;
1311 }
1312 /* }}} */
1313 
1314 /* {{{ proto array get_class_methods(mixed class)
1315    Returns an array of method names for class or class instance. */
ZEND_FUNCTION(get_class_methods)1316 ZEND_FUNCTION(get_class_methods)
1317 {
1318 	zval *klass;
1319 	zval method_name;
1320 	zend_class_entry *ce = NULL;
1321 	zend_class_entry *scope;
1322 	zend_function *mptr;
1323 	zend_string *key;
1324 
1325 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &klass) == FAILURE) {
1326 		return;
1327 	}
1328 
1329 	if (Z_TYPE_P(klass) == IS_OBJECT) {
1330 		ce = Z_OBJCE_P(klass);
1331 	} else if (Z_TYPE_P(klass) == IS_STRING) {
1332 	    ce = zend_lookup_class(Z_STR_P(klass));
1333 	}
1334 
1335 	if (!ce) {
1336 		RETURN_NULL();
1337 	}
1338 
1339 	array_init(return_value);
1340 	scope = zend_get_executed_scope();
1341 
1342 	ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, key, mptr) {
1343 
1344 		if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC)
1345 		 || (scope &&
1346 		     (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) &&
1347 		       zend_check_protected(mptr->common.scope, scope))
1348 		   || ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) &&
1349 		       scope == mptr->common.scope)))) {
1350 			size_t len = ZSTR_LEN(mptr->common.function_name);
1351 
1352 			/* Do not display old-style inherited constructors */
1353 			if (!key) {
1354 				ZVAL_STR_COPY(&method_name, mptr->common.function_name);
1355 				zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
1356 			} else if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0 ||
1357 			    mptr->common.scope == ce ||
1358 			    zend_binary_strcasecmp(ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(mptr->common.function_name), len) == 0) {
1359 
1360 				if (mptr->type == ZEND_USER_FUNCTION &&
1361 				    (!mptr->op_array.refcount || *mptr->op_array.refcount > 1) &&
1362 			    	 !same_name(key, mptr->common.function_name)) {
1363 					ZVAL_STR_COPY(&method_name, zend_find_alias_name(mptr->common.scope, key));
1364 					zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
1365 				} else {
1366 					ZVAL_STR_COPY(&method_name, mptr->common.function_name);
1367 					zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
1368 				}
1369 			}
1370 		}
1371 	} ZEND_HASH_FOREACH_END();
1372 }
1373 /* }}} */
1374 
1375 /* {{{ proto bool method_exists(object object, string method)
1376    Checks if the class method exists */
ZEND_FUNCTION(method_exists)1377 ZEND_FUNCTION(method_exists)
1378 {
1379 	zval *klass;
1380 	zend_string *method_name;
1381 	zend_string *lcname;
1382 	zend_class_entry * ce;
1383 
1384 	ZEND_PARSE_PARAMETERS_START(2, 2)
1385 		Z_PARAM_ZVAL(klass)
1386 		Z_PARAM_STR(method_name)
1387 	ZEND_PARSE_PARAMETERS_END();
1388 
1389 	if (Z_TYPE_P(klass) == IS_OBJECT) {
1390 		ce = Z_OBJCE_P(klass);
1391 	} else if (Z_TYPE_P(klass) == IS_STRING) {
1392 		if ((ce = zend_lookup_class(Z_STR_P(klass))) == NULL) {
1393 			RETURN_FALSE;
1394 		}
1395 	} else {
1396 		RETURN_FALSE;
1397 	}
1398 
1399 	lcname = zend_string_tolower(method_name);
1400 	if (zend_hash_exists(&ce->function_table, lcname)) {
1401 		zend_string_release(lcname);
1402 		RETURN_TRUE;
1403 	} else if (Z_TYPE_P(klass) == IS_OBJECT && Z_OBJ_HT_P(klass)->get_method != NULL) {
1404 		zend_object *obj = Z_OBJ_P(klass);
1405 		zend_function *func = Z_OBJ_HT_P(klass)->get_method(&obj, method_name, NULL);
1406 		if (func != NULL) {
1407 			if (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
1408 				/* Returns true to the fake Closure's __invoke */
1409 				RETVAL_BOOL(func->common.scope == zend_ce_closure
1410 					&& zend_string_equals_literal(method_name, ZEND_INVOKE_FUNC_NAME));
1411 
1412 				zend_string_release(lcname);
1413 				zend_string_release(func->common.function_name);
1414 				zend_free_trampoline(func);
1415 				return;
1416 			}
1417 			zend_string_release(lcname);
1418 			RETURN_TRUE;
1419 		}
1420 	}
1421 	zend_string_release(lcname);
1422 	RETURN_FALSE;
1423 }
1424 /* }}} */
1425 
1426 /* {{{ proto bool property_exists(mixed object_or_class, string property_name)
1427    Checks if the object or class has a property */
ZEND_FUNCTION(property_exists)1428 ZEND_FUNCTION(property_exists)
1429 {
1430 	zval *object;
1431 	zend_string *property;
1432 	zend_class_entry *ce;
1433 	zend_property_info *property_info;
1434 	zval property_z;
1435 
1436 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &object, &property) == FAILURE) {
1437 		return;
1438 	}
1439 
1440 	if (property == NULL) {
1441 		RETURN_FALSE;
1442 	}
1443 
1444 	if (Z_TYPE_P(object) == IS_STRING) {
1445 		ce = zend_lookup_class(Z_STR_P(object));
1446 		if (!ce) {
1447 			RETURN_FALSE;
1448 		}
1449 	} else if (Z_TYPE_P(object) == IS_OBJECT) {
1450 		ce = Z_OBJCE_P(object);
1451 	} else {
1452 		zend_error(E_WARNING, "First parameter must either be an object or the name of an existing class");
1453 		RETURN_NULL();
1454 	}
1455 
1456 	if ((property_info = zend_hash_find_ptr(&ce->properties_info, property)) != NULL
1457 		&& (property_info->flags & ZEND_ACC_SHADOW) == 0) {
1458 		RETURN_TRUE;
1459 	}
1460 
1461 	ZVAL_STR(&property_z, property);
1462 
1463 	if (Z_TYPE_P(object) ==  IS_OBJECT &&
1464 		Z_OBJ_HANDLER_P(object, has_property) &&
1465 		Z_OBJ_HANDLER_P(object, has_property)(object, &property_z, 2, NULL)) {
1466 		RETURN_TRUE;
1467 	}
1468 	RETURN_FALSE;
1469 }
1470 /* }}} */
1471 
1472 /* {{{ proto bool class_exists(string classname [, bool autoload])
1473    Checks if the class exists */
ZEND_FUNCTION(class_exists)1474 ZEND_FUNCTION(class_exists)
1475 {
1476 	zend_string *class_name;
1477 	zend_string *lc_name;
1478 	zend_class_entry *ce;
1479 	zend_bool autoload = 1;
1480 
1481 	ZEND_PARSE_PARAMETERS_START(1, 2)
1482 		Z_PARAM_STR(class_name)
1483 		Z_PARAM_OPTIONAL
1484 		Z_PARAM_BOOL(autoload)
1485 	ZEND_PARSE_PARAMETERS_END();
1486 
1487 	if (!autoload) {
1488 		if (ZSTR_VAL(class_name)[0] == '\\') {
1489 			/* Ignore leading "\" */
1490 			lc_name = zend_string_alloc(ZSTR_LEN(class_name) - 1, 0);
1491 			zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(class_name) + 1, ZSTR_LEN(class_name) - 1);
1492 		} else {
1493 			lc_name = zend_string_tolower(class_name);
1494 		}
1495 
1496 		ce = zend_hash_find_ptr(EG(class_table), lc_name);
1497 		zend_string_release(lc_name);
1498 	} else {
1499 		ce = zend_lookup_class(class_name);
1500 	}
1501 
1502  	if (ce) {
1503  		RETURN_BOOL((ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT)) == 0);
1504 	} else {
1505 		RETURN_FALSE;
1506 	}
1507 }
1508 /* }}} */
1509 
1510 /* {{{ proto bool interface_exists(string classname [, bool autoload])
1511    Checks if the class exists */
ZEND_FUNCTION(interface_exists)1512 ZEND_FUNCTION(interface_exists)
1513 {
1514 	zend_string *iface_name, *lc_name;
1515 	zend_class_entry *ce;
1516 	zend_bool autoload = 1;
1517 
1518 	ZEND_PARSE_PARAMETERS_START(1, 2)
1519 		Z_PARAM_STR(iface_name)
1520 		Z_PARAM_OPTIONAL
1521 		Z_PARAM_BOOL(autoload)
1522 	ZEND_PARSE_PARAMETERS_END();
1523 
1524 	if (!autoload) {
1525 		if (ZSTR_VAL(iface_name)[0] == '\\') {
1526 			/* Ignore leading "\" */
1527 			lc_name = zend_string_alloc(ZSTR_LEN(iface_name) - 1, 0);
1528 			zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(iface_name) + 1, ZSTR_LEN(iface_name) - 1);
1529 		} else {
1530 			lc_name = zend_string_tolower(iface_name);
1531 		}
1532 		ce = zend_hash_find_ptr(EG(class_table), lc_name);
1533 		zend_string_release(lc_name);
1534 		RETURN_BOOL(ce && ce->ce_flags & ZEND_ACC_INTERFACE);
1535 	}
1536 
1537 	ce = zend_lookup_class(iface_name);
1538 	if (ce) {
1539  		RETURN_BOOL((ce->ce_flags & ZEND_ACC_INTERFACE) > 0);
1540 	} else {
1541 		RETURN_FALSE;
1542 	}
1543 }
1544 /* }}} */
1545 
1546 /* {{{ proto bool trait_exists(string traitname [, bool autoload])
1547  Checks if the trait exists */
ZEND_FUNCTION(trait_exists)1548 ZEND_FUNCTION(trait_exists)
1549 {
1550 	zend_string *trait_name, *lc_name;
1551 	zend_class_entry *ce;
1552 	zend_bool autoload = 1;
1553 
1554 	ZEND_PARSE_PARAMETERS_START(1, 2)
1555 		Z_PARAM_STR(trait_name)
1556 		Z_PARAM_OPTIONAL
1557 		Z_PARAM_BOOL(autoload)
1558 	ZEND_PARSE_PARAMETERS_END();
1559 
1560 	if (!autoload) {
1561 		if (ZSTR_VAL(trait_name)[0] == '\\') {
1562 			/* Ignore leading "\" */
1563 			lc_name = zend_string_alloc(ZSTR_LEN(trait_name) - 1, 0);
1564 			zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(trait_name) + 1, ZSTR_LEN(trait_name) - 1);
1565 		} else {
1566 			lc_name = zend_string_tolower(trait_name);
1567 		}
1568 
1569 		ce = zend_hash_find_ptr(EG(class_table), lc_name);
1570 		zend_string_release(lc_name);
1571 	} else {
1572 		ce = zend_lookup_class(trait_name);
1573 	}
1574 
1575 	if (ce) {
1576  		RETURN_BOOL((ce->ce_flags & ZEND_ACC_TRAIT) != 0);
1577 	} else {
1578 		RETURN_FALSE;
1579 	}
1580 }
1581 /* }}} */
1582 
1583 /* {{{ proto bool function_exists(string function_name)
1584    Checks if the function exists */
ZEND_FUNCTION(function_exists)1585 ZEND_FUNCTION(function_exists)
1586 {
1587 	zend_string *name;
1588 	zend_function *func;
1589 	zend_string *lcname;
1590 
1591 	ZEND_PARSE_PARAMETERS_START(1, 1)
1592 		Z_PARAM_STR(name)
1593 	ZEND_PARSE_PARAMETERS_END();
1594 
1595 	if (ZSTR_VAL(name)[0] == '\\') {
1596 		/* Ignore leading "\" */
1597 		lcname = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
1598 		zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
1599 	} else {
1600 		lcname = zend_string_tolower(name);
1601 	}
1602 
1603 	func = zend_hash_find_ptr(EG(function_table), lcname);
1604 	zend_string_release(lcname);
1605 
1606 	/*
1607 	 * A bit of a hack, but not a bad one: we see if the handler of the function
1608 	 * is actually one that displays "function is disabled" message.
1609 	 */
1610 	RETURN_BOOL(func && (func->type != ZEND_INTERNAL_FUNCTION ||
1611 		func->internal_function.handler != zif_display_disabled_function));
1612 }
1613 /* }}} */
1614 
1615 /* {{{ proto bool class_alias(string user_class_name , string alias_name [, bool autoload])
1616    Creates an alias for user defined class */
ZEND_FUNCTION(class_alias)1617 ZEND_FUNCTION(class_alias)
1618 {
1619 	zend_string *class_name;
1620 	char *alias_name;
1621 	zend_class_entry *ce;
1622 	size_t alias_name_len;
1623 	zend_bool autoload = 1;
1624 
1625 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ss|b", &class_name, &alias_name, &alias_name_len, &autoload) == FAILURE) {
1626 		return;
1627 	}
1628 
1629 	ce = zend_lookup_class_ex(class_name, NULL, autoload);
1630 
1631 	if (ce) {
1632 		if (ce->type == ZEND_USER_CLASS) {
1633 			if (zend_register_class_alias_ex(alias_name, alias_name_len, ce) == SUCCESS) {
1634 				RETURN_TRUE;
1635 			} else {
1636 				zend_error(E_WARNING, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), alias_name);
1637 				RETURN_FALSE;
1638 			}
1639 		} else {
1640 			zend_error(E_WARNING, "First argument of class_alias() must be a name of user defined class");
1641 			RETURN_FALSE;
1642 		}
1643 	} else {
1644 		zend_error(E_WARNING, "Class '%s' not found", ZSTR_VAL(class_name));
1645 		RETURN_FALSE;
1646 	}
1647 }
1648 /* }}} */
1649 
1650 #if ZEND_DEBUG
1651 /* {{{ proto void leak([int num_bytes])
1652    Cause an intentional memory leak, for testing/debugging purposes */
ZEND_FUNCTION(leak)1653 ZEND_FUNCTION(leak)
1654 {
1655 	zend_long leakbytes = 3;
1656 
1657 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &leakbytes) == FAILURE) {
1658 		return;
1659 	}
1660 
1661 	emalloc(leakbytes);
1662 }
1663 /* }}} */
1664 
1665 /* {{{ proto void leak_variable(mixed variable [, bool leak_data])
1666    Leak a variable that is a resource or an object */
ZEND_FUNCTION(leak_variable)1667 ZEND_FUNCTION(leak_variable)
1668 {
1669 	zval *zv;
1670 	zend_bool leak_data = 0;
1671 
1672 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &zv, &leak_data) == FAILURE) {
1673 		return;
1674 	}
1675 
1676 	if (!leak_data) {
1677 		Z_ADDREF_P(zv);
1678 	} else if (Z_TYPE_P(zv) == IS_RESOURCE) {
1679 		Z_ADDREF_P(zv);
1680 	} else if (Z_TYPE_P(zv) == IS_OBJECT) {
1681 		Z_ADDREF_P(zv);
1682 	} else {
1683 		zend_error(E_WARNING, "Leaking non-zval data is only applicable to resources and objects");
1684 	}
1685 }
1686 /* }}} */
1687 
1688 
1689 #ifdef ZEND_TEST_EXCEPTIONS
1690 /* {{{ proto void crash(void)
1691    Crash the script */
ZEND_FUNCTION(crash)1692 ZEND_FUNCTION(crash)
1693 {
1694 	char *nowhere = NULL;
1695 
1696 	if (zend_parse_parameters_none() == FAILURE) {
1697 		return;
1698 	}
1699 
1700 	memcpy(nowhere, "something", sizeof("something"));
1701 }
1702 /* }}} */
1703 #endif
1704 
1705 #endif /* ZEND_DEBUG */
1706 
1707 /* {{{ proto array get_included_files(void)
1708    Returns an array with the file names that were include_once()'d */
ZEND_FUNCTION(get_included_files)1709 ZEND_FUNCTION(get_included_files)
1710 {
1711 	zend_string *entry;
1712 
1713 	if (zend_parse_parameters_none() == FAILURE) {
1714 		return;
1715 	}
1716 
1717 	array_init(return_value);
1718 	ZEND_HASH_FOREACH_STR_KEY(&EG(included_files), entry) {
1719 		if (entry) {
1720 			add_next_index_str(return_value, zend_string_copy(entry));
1721 		}
1722 	} ZEND_HASH_FOREACH_END();
1723 }
1724 /* }}} */
1725 
1726 /* {{{ proto void trigger_error(string message [, int error_type])
1727    Generates a user-level error/warning/notice message */
ZEND_FUNCTION(trigger_error)1728 ZEND_FUNCTION(trigger_error)
1729 {
1730 	zend_long error_type = E_USER_NOTICE;
1731 	char *message;
1732 	size_t message_len;
1733 
1734 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &message, &message_len, &error_type) == FAILURE) {
1735 		return;
1736 	}
1737 
1738 	switch (error_type) {
1739 		case E_USER_ERROR:
1740 		case E_USER_WARNING:
1741 		case E_USER_NOTICE:
1742 		case E_USER_DEPRECATED:
1743 			break;
1744 		default:
1745 			zend_error(E_WARNING, "Invalid error type specified");
1746 			RETURN_FALSE;
1747 			break;
1748 	}
1749 
1750 	zend_error((int)error_type, "%s", message);
1751 	RETURN_TRUE;
1752 }
1753 /* }}} */
1754 
1755 /* {{{ proto string set_error_handler(callable error_handler [, int error_types])
1756    Sets a user-defined error handler function.  Returns the previously defined error handler, or false on error */
ZEND_FUNCTION(set_error_handler)1757 ZEND_FUNCTION(set_error_handler)
1758 {
1759 	zval *error_handler;
1760 	zend_string *error_handler_name = NULL;
1761 	zend_long error_type = E_ALL;
1762 
1763 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &error_handler, &error_type) == FAILURE) {
1764 		return;
1765 	}
1766 
1767 	if (Z_TYPE_P(error_handler) != IS_NULL) { /* NULL == unset */
1768 		if (!zend_is_callable(error_handler, 0, &error_handler_name)) {
1769 			zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
1770 					   get_active_function_name(), error_handler_name?ZSTR_VAL(error_handler_name):"unknown");
1771 			zend_string_release(error_handler_name);
1772 			return;
1773 		}
1774 		zend_string_release(error_handler_name);
1775 	}
1776 
1777 	if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
1778 		ZVAL_COPY(return_value, &EG(user_error_handler));
1779 
1780 		zend_stack_push(&EG(user_error_handlers_error_reporting), &EG(user_error_handler_error_reporting));
1781 		zend_stack_push(&EG(user_error_handlers), &EG(user_error_handler));
1782 	}
1783 
1784 	if (Z_TYPE_P(error_handler) == IS_NULL) { /* unset user-defined handler */
1785 		ZVAL_UNDEF(&EG(user_error_handler));
1786 		return;
1787 	}
1788 
1789 	ZVAL_COPY(&EG(user_error_handler), error_handler);
1790 	EG(user_error_handler_error_reporting) = (int)error_type;
1791 }
1792 /* }}} */
1793 
1794 /* {{{ proto void restore_error_handler(void)
1795    Restores the previously defined error handler function */
ZEND_FUNCTION(restore_error_handler)1796 ZEND_FUNCTION(restore_error_handler)
1797 {
1798 	if (zend_parse_parameters_none() == FAILURE) {
1799 		return;
1800 	}
1801 
1802 	if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
1803 		zval zeh;
1804 
1805 		ZVAL_COPY_VALUE(&zeh, &EG(user_error_handler));
1806 		ZVAL_UNDEF(&EG(user_error_handler));
1807 		zval_ptr_dtor(&zeh);
1808 	}
1809 
1810 	if (zend_stack_is_empty(&EG(user_error_handlers))) {
1811 		ZVAL_UNDEF(&EG(user_error_handler));
1812 	} else {
1813 		zval *tmp;
1814 		EG(user_error_handler_error_reporting) = zend_stack_int_top(&EG(user_error_handlers_error_reporting));
1815 		zend_stack_del_top(&EG(user_error_handlers_error_reporting));
1816 		tmp = zend_stack_top(&EG(user_error_handlers));
1817 		ZVAL_COPY_VALUE(&EG(user_error_handler), tmp);
1818 		zend_stack_del_top(&EG(user_error_handlers));
1819 	}
1820 	RETURN_TRUE;
1821 }
1822 /* }}} */
1823 
1824 /* {{{ proto mixed set_exception_handler(callable exception_handler)
1825    Sets a user-defined exception handler function. Returns the previously defined exception handler, or false on error */
ZEND_FUNCTION(set_exception_handler)1826 ZEND_FUNCTION(set_exception_handler)
1827 {
1828 	zval *exception_handler;
1829 	zend_string *exception_handler_name = NULL;
1830 
1831 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &exception_handler) == FAILURE) {
1832 		return;
1833 	}
1834 
1835 	if (Z_TYPE_P(exception_handler) != IS_NULL) { /* NULL == unset */
1836 		if (!zend_is_callable(exception_handler, 0, &exception_handler_name)) {
1837 			zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
1838 					   get_active_function_name(), exception_handler_name?ZSTR_VAL(exception_handler_name):"unknown");
1839 			zend_string_release(exception_handler_name);
1840 			return;
1841 		}
1842 		zend_string_release(exception_handler_name);
1843 	}
1844 
1845 	if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
1846 		ZVAL_COPY(return_value, &EG(user_exception_handler));
1847 
1848 		zend_stack_push(&EG(user_exception_handlers), &EG(user_exception_handler));
1849 	}
1850 
1851 	if (Z_TYPE_P(exception_handler) == IS_NULL) { /* unset user-defined handler */
1852 		ZVAL_UNDEF(&EG(user_exception_handler));
1853 		return;
1854 	}
1855 
1856 	ZVAL_COPY(&EG(user_exception_handler), exception_handler);
1857 }
1858 /* }}} */
1859 
1860 /* {{{ proto void restore_exception_handler(void)
1861    Restores the previously defined exception handler function */
ZEND_FUNCTION(restore_exception_handler)1862 ZEND_FUNCTION(restore_exception_handler)
1863 {
1864 	if (zend_parse_parameters_none() == FAILURE) {
1865 		return;
1866 	}
1867 
1868 	if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
1869 		zval_ptr_dtor(&EG(user_exception_handler));
1870 	}
1871 	if (zend_stack_is_empty(&EG(user_exception_handlers))) {
1872 		ZVAL_UNDEF(&EG(user_exception_handler));
1873 	} else {
1874 		zval *tmp = zend_stack_top(&EG(user_exception_handlers));
1875 		ZVAL_COPY_VALUE(&EG(user_exception_handler), tmp);
1876 		zend_stack_del_top(&EG(user_exception_handlers));
1877 	}
1878 	RETURN_TRUE;
1879 }
1880 /* }}} */
1881 
copy_class_or_interface_name(zval * el,int num_args,va_list args,zend_hash_key * hash_key)1882 static int copy_class_or_interface_name(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
1883 {
1884 	zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el);
1885 	zval *array = va_arg(args, zval *);
1886 	uint32_t mask = va_arg(args, uint32_t);
1887 	uint32_t comply = va_arg(args, uint32_t);
1888 	uint32_t comply_mask = (comply)? mask:0;
1889 
1890 	if ((hash_key->key && ZSTR_VAL(hash_key->key)[0] != 0)
1891 		&& (comply_mask == (ce->ce_flags & mask))) {
1892 		if (ce->refcount > 1 &&
1893 		    !same_name(hash_key->key, ce->name)) {
1894 			add_next_index_str(array, zend_string_copy(hash_key->key));
1895 		} else {
1896 			add_next_index_str(array, zend_string_copy(ce->name));
1897 		}
1898 	}
1899 	return ZEND_HASH_APPLY_KEEP;
1900 }
1901 /* }}} */
1902 
1903 /* {{{ proto array get_declared_traits()
1904    Returns an array of all declared traits. */
ZEND_FUNCTION(get_declared_traits)1905 ZEND_FUNCTION(get_declared_traits)
1906 {
1907 	uint32_t mask = ZEND_ACC_TRAIT;
1908 	uint32_t comply = 1;
1909 
1910 	if (zend_parse_parameters_none() == FAILURE) {
1911 		return;
1912 	}
1913 
1914 	array_init(return_value);
1915 	zend_hash_apply_with_arguments(EG(class_table), copy_class_or_interface_name, 3, return_value, mask, comply);
1916 }
1917 /* }}} */
1918 
1919 /* {{{ proto array get_declared_classes()
1920    Returns an array of all declared classes. */
ZEND_FUNCTION(get_declared_classes)1921 ZEND_FUNCTION(get_declared_classes)
1922 {
1923 	uint32_t mask = ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT;
1924 	uint32_t comply = 0;
1925 
1926 	if (zend_parse_parameters_none() == FAILURE) {
1927 		return;
1928 	}
1929 
1930 	array_init(return_value);
1931 	zend_hash_apply_with_arguments(EG(class_table), copy_class_or_interface_name, 3, return_value, mask, comply);
1932 }
1933 /* }}} */
1934 
1935 /* {{{ proto array get_declared_interfaces()
1936    Returns an array of all declared interfaces. */
ZEND_FUNCTION(get_declared_interfaces)1937 ZEND_FUNCTION(get_declared_interfaces)
1938 {
1939 	uint32_t mask = ZEND_ACC_INTERFACE;
1940 	uint32_t comply = 1;
1941 
1942 	if (zend_parse_parameters_none() == FAILURE) {
1943 		return;
1944 	}
1945 
1946 	array_init(return_value);
1947 	zend_hash_apply_with_arguments(EG(class_table), copy_class_or_interface_name, 3, return_value, mask, comply);
1948 }
1949 /* }}} */
1950 
copy_function_name(zval * zv,int num_args,va_list args,zend_hash_key * hash_key)1951 static int copy_function_name(zval *zv, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
1952 {
1953 	zend_function *func = Z_PTR_P(zv);
1954 	zval *internal_ar = va_arg(args, zval *),
1955 	     *user_ar     = va_arg(args, zval *);
1956 	zend_bool *exclude_disabled = va_arg(args, zend_bool *);
1957 
1958 	if (hash_key->key == NULL || ZSTR_VAL(hash_key->key)[0] == 0) {
1959 		return 0;
1960 	}
1961 
1962 	if (func->type == ZEND_INTERNAL_FUNCTION) {
1963 		char *disable_functions = INI_STR("disable_functions");
1964 
1965 		if ((*exclude_disabled == 1) && (disable_functions != NULL)) {
1966 			if (strstr(disable_functions, func->common.function_name->val) == NULL) {
1967 				add_next_index_str(internal_ar, zend_string_copy(hash_key->key));
1968 			}
1969 		} else {
1970 			add_next_index_str(internal_ar, zend_string_copy(hash_key->key));
1971 		}
1972 	} else if (func->type == ZEND_USER_FUNCTION) {
1973 		add_next_index_str(user_ar, zend_string_copy(hash_key->key));
1974 	}
1975 
1976 	return 0;
1977 }
1978 /* }}} */
1979 
1980 /* {{{ proto array get_defined_functions(void)
1981    Returns an array of all defined functions */
ZEND_FUNCTION(get_defined_functions)1982 ZEND_FUNCTION(get_defined_functions)
1983 {
1984 	zval internal, user;
1985 	zend_bool exclude_disabled = 0;
1986 
1987 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &exclude_disabled) == FAILURE) {
1988 		return;
1989 	}
1990 
1991 	array_init(&internal);
1992 	array_init(&user);
1993 	array_init(return_value);
1994 
1995 	zend_hash_apply_with_arguments(EG(function_table), copy_function_name, 3, &internal, &user, &exclude_disabled);
1996 
1997 	zend_hash_str_add_new(Z_ARRVAL_P(return_value), "internal", sizeof("internal")-1, &internal);
1998 	zend_hash_str_add_new(Z_ARRVAL_P(return_value), "user", sizeof("user")-1, &user);
1999 }
2000 /* }}} */
2001 
2002 /* {{{ proto array get_defined_vars(void)
2003    Returns an associative array of names and values of all currently defined variable names (variables in the current scope) */
ZEND_FUNCTION(get_defined_vars)2004 ZEND_FUNCTION(get_defined_vars)
2005 {
2006 	zend_array *symbol_table;
2007 	if (zend_forbid_dynamic_call("get_defined_vars()") == FAILURE) {
2008 		return;
2009 	}
2010 
2011 	symbol_table = zend_rebuild_symbol_table();
2012 	if (UNEXPECTED(symbol_table == NULL)) {
2013 		return;
2014 	}
2015 
2016 	RETURN_ARR(zend_array_dup(symbol_table));
2017 }
2018 /* }}} */
2019 
2020 #define LAMBDA_TEMP_FUNCNAME	"__lambda_func"
2021 /* {{{ proto string create_function(string args, string code)
2022    Creates an anonymous function, and returns its name (funny, eh?) */
ZEND_FUNCTION(create_function)2023 ZEND_FUNCTION(create_function)
2024 {
2025     zend_string *function_name;
2026 	char *eval_code, *function_args, *function_code;
2027 	size_t eval_code_length, function_args_len, function_code_len;
2028 	int retval;
2029 	char *eval_name;
2030 
2031 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &function_args, &function_args_len, &function_code, &function_code_len) == FAILURE) {
2032 		return;
2033 	}
2034 
2035 	eval_code = (char *) emalloc(sizeof("function " LAMBDA_TEMP_FUNCNAME)
2036 			+function_args_len
2037 			+2	/* for the args parentheses */
2038 			+2	/* for the curly braces */
2039 			+function_code_len);
2040 
2041 	eval_code_length = sizeof("function " LAMBDA_TEMP_FUNCNAME "(") - 1;
2042 	memcpy(eval_code, "function " LAMBDA_TEMP_FUNCNAME "(", eval_code_length);
2043 
2044 	memcpy(eval_code + eval_code_length, function_args, function_args_len);
2045 	eval_code_length += function_args_len;
2046 
2047 	eval_code[eval_code_length++] = ')';
2048 	eval_code[eval_code_length++] = '{';
2049 
2050 	memcpy(eval_code + eval_code_length, function_code, function_code_len);
2051 	eval_code_length += function_code_len;
2052 
2053 	eval_code[eval_code_length++] = '}';
2054 	eval_code[eval_code_length] = '\0';
2055 
2056 	eval_name = zend_make_compiled_string_description("runtime-created function");
2057 	retval = zend_eval_stringl(eval_code, eval_code_length, NULL, eval_name);
2058 	efree(eval_code);
2059 	efree(eval_name);
2060 
2061 	if (retval==SUCCESS) {
2062 		zend_op_array *func;
2063 		HashTable *static_variables;
2064 
2065 		func = zend_hash_str_find_ptr(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1);
2066 		if (!func) {
2067 			zend_error_noreturn(E_CORE_ERROR, "Unexpected inconsistency in create_function()");
2068 			RETURN_FALSE;
2069 		}
2070 		if (func->refcount) {
2071 			(*func->refcount)++;
2072 		}
2073 		static_variables = func->static_variables;
2074 		func->static_variables = NULL;
2075 		zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1);
2076 		func->static_variables = static_variables;
2077 
2078 		function_name = zend_string_alloc(sizeof("0lambda_")+MAX_LENGTH_OF_LONG, 0);
2079 		ZSTR_VAL(function_name)[0] = '\0';
2080 
2081 		do {
2082 			ZSTR_LEN(function_name) = snprintf(ZSTR_VAL(function_name) + 1, sizeof("lambda_")+MAX_LENGTH_OF_LONG, "lambda_%d", ++EG(lambda_count)) + 1;
2083 		} while (zend_hash_add_ptr(EG(function_table), function_name, func) == NULL);
2084 		RETURN_NEW_STR(function_name);
2085 	} else {
2086 		zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1);
2087 		RETURN_FALSE;
2088 	}
2089 }
2090 /* }}} */
2091 
2092 #if ZEND_DEBUG
ZEND_FUNCTION(zend_test_func)2093 ZEND_FUNCTION(zend_test_func)
2094 {
2095 	zval *arg1, *arg2;
2096 
2097 	zend_parse_parameters(ZEND_NUM_ARGS(), "|zz", &arg1, &arg2);
2098 }
2099 
ZEND_FUNCTION(zend_test_func2)2100 ZEND_FUNCTION(zend_test_func2)
2101 {
2102 	zval *arg1, *arg2;
2103 
2104 	zend_parse_parameters(ZEND_NUM_ARGS(), "|zz", &arg1, &arg2);
2105 }
2106 
2107 #ifdef ZTS
ZEND_FUNCTION(zend_thread_id)2108 ZEND_FUNCTION(zend_thread_id)
2109 {
2110 	RETURN_LONG((zend_long)tsrm_thread_id());
2111 }
2112 #endif
2113 #endif
2114 
2115 /* {{{ proto string get_resource_type(resource res)
2116    Get the resource type name for a given resource */
ZEND_FUNCTION(get_resource_type)2117 ZEND_FUNCTION(get_resource_type)
2118 {
2119 	const char *resource_type;
2120 	zval *z_resource_type;
2121 
2122 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_resource_type) == FAILURE) {
2123 		return;
2124 	}
2125 
2126 	resource_type = zend_rsrc_list_get_rsrc_type(Z_RES_P(z_resource_type));
2127 	if (resource_type) {
2128 		RETURN_STRING(resource_type);
2129 	} else {
2130 		RETURN_STRING("Unknown");
2131 	}
2132 }
2133 /* }}} */
2134 
2135 /* {{{ proto array get_resources([string resouce_type])
2136    Get an array with all active resources */
ZEND_FUNCTION(get_resources)2137 ZEND_FUNCTION(get_resources)
2138 {
2139 	zend_string *type = NULL;
2140 	zend_string *key;
2141 	zend_ulong index;
2142 	zval *val;
2143 
2144 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S", &type) == FAILURE) {
2145 		return;
2146 	}
2147 
2148 	if (!type) {
2149 		array_init(return_value);
2150 		ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
2151 			if (!key) {
2152 				Z_ADDREF_P(val);
2153 				zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
2154 			}
2155 		} ZEND_HASH_FOREACH_END();
2156 	} else if (zend_string_equals_literal(type, "Unknown")) {
2157 		array_init(return_value);
2158 		ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
2159 			if (!key && Z_RES_TYPE_P(val) <= 0) {
2160 				Z_ADDREF_P(val);
2161 				zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
2162 			}
2163 		} ZEND_HASH_FOREACH_END();
2164 	} else {
2165 		int id = zend_fetch_list_dtor_id(ZSTR_VAL(type));
2166 
2167 		if (id <= 0) {
2168 			zend_error(E_WARNING, "get_resources():  Unknown resource type '%s'", ZSTR_VAL(type));
2169 			RETURN_FALSE;
2170 		}
2171 
2172 		array_init(return_value);
2173 		ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
2174 			if (!key && Z_RES_TYPE_P(val) == id) {
2175 				Z_ADDREF_P(val);
2176 				zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
2177 			}
2178 		} ZEND_HASH_FOREACH_END();
2179 	}
2180 }
2181 /* }}} */
2182 
add_extension_info(zval * item,void * arg)2183 static int add_extension_info(zval *item, void *arg) /* {{{ */
2184 {
2185 	zval *name_array = (zval *)arg;
2186 	zend_module_entry *module = (zend_module_entry*)Z_PTR_P(item);
2187 	add_next_index_string(name_array, module->name);
2188 	return 0;
2189 }
2190 /* }}} */
2191 
add_zendext_info(zend_extension * ext,void * arg)2192 static int add_zendext_info(zend_extension *ext, void *arg) /* {{{ */
2193 {
2194 	zval *name_array = (zval *)arg;
2195 	add_next_index_string(name_array, ext->name);
2196 	return 0;
2197 }
2198 /* }}} */
2199 
add_constant_info(zval * item,void * arg)2200 static int add_constant_info(zval *item, void *arg) /* {{{ */
2201 {
2202 	zval *name_array = (zval *)arg;
2203 	zend_constant *constant = (zend_constant*)Z_PTR_P(item);
2204 	zval const_val;
2205 
2206 	if (!constant->name) {
2207 		/* skip special constants */
2208 		return 0;
2209 	}
2210 
2211 	ZVAL_DUP(&const_val, &constant->value);
2212 	zend_hash_add_new(Z_ARRVAL_P(name_array), constant->name, &const_val);
2213 	return 0;
2214 }
2215 /* }}} */
2216 
2217 /* {{{ proto array get_loaded_extensions([bool zend_extensions])
2218    Return an array containing names of loaded extensions */
ZEND_FUNCTION(get_loaded_extensions)2219 ZEND_FUNCTION(get_loaded_extensions)
2220 {
2221 	zend_bool zendext = 0;
2222 
2223 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &zendext) == FAILURE) {
2224 		return;
2225 	}
2226 
2227 	array_init(return_value);
2228 
2229 	if (zendext) {
2230 		zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t)add_zendext_info, return_value);
2231 	} else {
2232 		zend_hash_apply_with_argument(&module_registry, add_extension_info, return_value);
2233 	}
2234 }
2235 /* }}} */
2236 
2237 /* {{{ proto array get_defined_constants([bool categorize])
2238    Return an array containing the names and values of all defined constants */
ZEND_FUNCTION(get_defined_constants)2239 ZEND_FUNCTION(get_defined_constants)
2240 {
2241 	zend_bool categorize = 0;
2242 
2243 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &categorize) == FAILURE) {
2244 		return;
2245 	}
2246 
2247 	array_init(return_value);
2248 
2249 	if (categorize) {
2250 		zend_constant *val;
2251 		int module_number;
2252 		zval *modules, const_val;
2253 		char **module_names;
2254 		zend_module_entry *module;
2255 		int i = 1;
2256 
2257 		modules = ecalloc(zend_hash_num_elements(&module_registry) + 2, sizeof(zval));
2258 		module_names = emalloc((zend_hash_num_elements(&module_registry) + 2) * sizeof(char *));
2259 
2260 		module_names[0] = "internal";
2261 		ZEND_HASH_FOREACH_PTR(&module_registry, module) {
2262 			module_names[module->module_number] = (char *)module->name;
2263 			i++;
2264 		} ZEND_HASH_FOREACH_END();
2265 		module_names[i] = "user";
2266 
2267 		ZEND_HASH_FOREACH_PTR(EG(zend_constants), val) {
2268 			if (!val->name) {
2269 				/* skip special constants */
2270 				continue;
2271 			}
2272 
2273 			if (val->module_number == PHP_USER_CONSTANT) {
2274 				module_number = i;
2275 			} else if (val->module_number > i || val->module_number < 0) {
2276 				/* should not happen */
2277 				continue;
2278 			} else {
2279 				module_number = val->module_number;
2280 			}
2281 
2282 			if (Z_TYPE(modules[module_number]) == IS_UNDEF) {
2283 				array_init(&modules[module_number]);
2284 				add_assoc_zval(return_value, module_names[module_number], &modules[module_number]);
2285 			}
2286 
2287 			ZVAL_DUP(&const_val, &val->value);
2288 			zend_hash_add_new(Z_ARRVAL(modules[module_number]), val->name, &const_val);
2289 		} ZEND_HASH_FOREACH_END();
2290 
2291 		efree(module_names);
2292 		efree(modules);
2293 	} else {
2294 		zend_hash_apply_with_argument(EG(zend_constants), add_constant_info, return_value);
2295 	}
2296 }
2297 /* }}} */
2298 
debug_backtrace_get_args(zend_execute_data * call,zval * arg_array)2299 static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) /* {{{ */
2300 {
2301 	uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
2302 
2303 	array_init_size(arg_array, num_args);
2304 	if (num_args) {
2305 		uint32_t i = 0;
2306 		zval *p = ZEND_CALL_ARG(call, 1);
2307 
2308 		zend_hash_real_init(Z_ARRVAL_P(arg_array), 1);
2309 		ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(arg_array)) {
2310 			if (call->func->type == ZEND_USER_FUNCTION) {
2311 				uint32_t first_extra_arg = MIN(num_args, call->func->op_array.num_args);
2312 
2313 				if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_SYMBOL_TABLE)) {
2314 					/* In case of attached symbol_table, values on stack may be invalid
2315 					 * and we have to access them through symbol_table
2316 					 * See: https://bugs.php.net/bug.php?id=73156
2317 					 */
2318 					zend_string *arg_name;
2319 					zval *arg;
2320 
2321 					while (i < first_extra_arg) {
2322 						arg_name = call->func->op_array.vars[i];
2323 						arg = zend_hash_find_ind(call->symbol_table, arg_name);
2324 						if (arg) {
2325 							if (Z_OPT_REFCOUNTED_P(arg)) {
2326 								Z_ADDREF_P(arg);
2327 							}
2328 							ZEND_HASH_FILL_ADD(arg);
2329 						} else {
2330 							ZEND_HASH_FILL_ADD(&EG(uninitialized_zval));
2331 						}
2332 						i++;
2333 					}
2334 				} else {
2335 					while (i < first_extra_arg) {
2336 						if (EXPECTED(Z_TYPE_INFO_P(p) != IS_UNDEF)) {
2337 							if (Z_OPT_REFCOUNTED_P(p)) {
2338 								Z_ADDREF_P(p);
2339 							}
2340 							ZEND_HASH_FILL_ADD(p);
2341 						} else {
2342 							ZEND_HASH_FILL_ADD(&EG(uninitialized_zval));
2343 						}
2344 						p++;
2345 						i++;
2346 					}
2347 				}
2348 				p = ZEND_CALL_VAR_NUM(call, call->func->op_array.last_var + call->func->op_array.T);
2349 			}
2350 
2351 			while (i < num_args) {
2352 				if (EXPECTED(Z_TYPE_INFO_P(p) != IS_UNDEF)) {
2353 					if (Z_OPT_REFCOUNTED_P(p)) {
2354 						Z_ADDREF_P(p);
2355 					}
2356 					ZEND_HASH_FILL_ADD(p);
2357 				} else {
2358 					ZEND_HASH_FILL_ADD(&EG(uninitialized_zval));
2359 				}
2360 				p++;
2361 				i++;
2362 			}
2363 		} ZEND_HASH_FILL_END();
2364 		Z_ARRVAL_P(arg_array)->nNumOfElements = num_args;
2365 	}
2366 }
2367 /* }}} */
2368 
debug_print_backtrace_args(zval * arg_array)2369 void debug_print_backtrace_args(zval *arg_array) /* {{{ */
2370 {
2371 	zval *tmp;
2372 	int i = 0;
2373 
2374 	ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arg_array), tmp) {
2375 		if (i++) {
2376 			ZEND_PUTS(", ");
2377 		}
2378 		zend_print_flat_zval_r(tmp);
2379 	} ZEND_HASH_FOREACH_END();
2380 }
2381 /* }}} */
2382 
2383 /* {{{ proto void debug_print_backtrace([int options[, int limit]]) */
ZEND_FUNCTION(debug_print_backtrace)2384 ZEND_FUNCTION(debug_print_backtrace)
2385 {
2386 	zend_execute_data *call, *ptr, *skip;
2387 	zend_object *object;
2388 	int lineno, frameno = 0;
2389 	zend_function *func;
2390 	const char *function_name;
2391 	const char *filename;
2392 	zend_string *class_name = NULL;
2393 	char *call_type;
2394 	const char *include_filename = NULL;
2395 	zval arg_array;
2396 	int indent = 0;
2397 	zend_long options = 0;
2398 	zend_long limit = 0;
2399 
2400 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) {
2401 		return;
2402 	}
2403 
2404 	ZVAL_UNDEF(&arg_array);
2405 	ptr = EX(prev_execute_data);
2406 
2407 	/* skip debug_backtrace() */
2408 	call = ptr;
2409 	ptr = ptr->prev_execute_data;
2410 
2411 	while (ptr && (limit == 0 || frameno < limit)) {
2412 		frameno++;
2413 		class_name = NULL;
2414 		call_type = NULL;
2415 		ZVAL_UNDEF(&arg_array);
2416 
2417 		ptr = zend_generator_check_placeholder_frame(ptr);
2418 
2419 		skip = ptr;
2420 		/* skip internal handler */
2421 		if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
2422 		    skip->prev_execute_data &&
2423 		    skip->prev_execute_data->func &&
2424 		    ZEND_USER_CODE(skip->prev_execute_data->func->common.type) &&
2425 		    skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
2426 		    skip->prev_execute_data->opline->opcode != ZEND_DO_ICALL &&
2427 		    skip->prev_execute_data->opline->opcode != ZEND_DO_UCALL &&
2428 		    skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
2429 		    skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
2430 			skip = skip->prev_execute_data;
2431 		}
2432 
2433 		if (skip->func && ZEND_USER_CODE(skip->func->common.type)) {
2434 			filename = ZSTR_VAL(skip->func->op_array.filename);
2435 			if (skip->opline->opcode == ZEND_HANDLE_EXCEPTION) {
2436 				if (EG(opline_before_exception)) {
2437 					lineno = EG(opline_before_exception)->lineno;
2438 				} else {
2439 					lineno = skip->func->op_array.line_end;
2440 				}
2441 			} else {
2442 				lineno = skip->opline->lineno;
2443 			}
2444 		} else {
2445 			filename = NULL;
2446 			lineno = 0;
2447 		}
2448 
2449 		/* $this may be passed into regular internal functions */
2450 		object = (Z_TYPE(call->This) == IS_OBJECT) ? Z_OBJ(call->This) : NULL;
2451 
2452 		if (call->func) {
2453 			zend_string *zend_function_name;
2454 
2455 			func = call->func;
2456             if (func->common.scope && func->common.scope->trait_aliases) {
2457                 zend_function_name = zend_resolve_method_name(object ? object->ce : func->common.scope, func);
2458             } else {
2459                 zend_function_name = func->common.function_name;
2460             }
2461             if (zend_function_name != NULL) {
2462                 function_name = ZSTR_VAL(zend_function_name);
2463             } else {
2464                 function_name = NULL;
2465             }
2466 		} else {
2467 			func = NULL;
2468 			function_name = NULL;
2469 		}
2470 
2471 		if (function_name) {
2472 			if (object) {
2473 				if (func->common.scope) {
2474 					class_name = func->common.scope->name;
2475 				} else if (object->handlers->get_class_name == std_object_handlers.get_class_name) {
2476 					class_name = object->ce->name;
2477 				} else {
2478 					class_name = object->handlers->get_class_name(object);
2479 				}
2480 
2481 				call_type = "->";
2482 			} else if (func->common.scope) {
2483 				class_name = func->common.scope->name;
2484 				call_type = "::";
2485 			} else {
2486 				class_name = NULL;
2487 				call_type = NULL;
2488 			}
2489 			if (func->type != ZEND_EVAL_CODE) {
2490 				if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
2491 					debug_backtrace_get_args(call, &arg_array);
2492 				}
2493 			}
2494 		} else {
2495 			/* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
2496 			zend_bool build_filename_arg = 1;
2497 
2498 			if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
2499 				/* can happen when calling eval from a custom sapi */
2500 				function_name = "unknown";
2501 				build_filename_arg = 0;
2502 			} else
2503 			switch (ptr->opline->extended_value) {
2504 				case ZEND_EVAL:
2505 					function_name = "eval";
2506 					build_filename_arg = 0;
2507 					break;
2508 				case ZEND_INCLUDE:
2509 					function_name = "include";
2510 					break;
2511 				case ZEND_REQUIRE:
2512 					function_name = "require";
2513 					break;
2514 				case ZEND_INCLUDE_ONCE:
2515 					function_name = "include_once";
2516 					break;
2517 				case ZEND_REQUIRE_ONCE:
2518 					function_name = "require_once";
2519 					break;
2520 				default:
2521 					/* this can actually happen if you use debug_backtrace() in your error_handler and
2522 					 * you're in the top-scope */
2523 					function_name = "unknown";
2524 					build_filename_arg = 0;
2525 					break;
2526 			}
2527 
2528 			if (build_filename_arg && include_filename) {
2529 				array_init(&arg_array);
2530 				add_next_index_string(&arg_array, (char*)include_filename);
2531 			}
2532 			call_type = NULL;
2533 		}
2534 		zend_printf("#%-2d ", indent);
2535 		if (class_name) {
2536 			ZEND_PUTS(ZSTR_VAL(class_name));
2537 			ZEND_PUTS(call_type);
2538 			if (object
2539 			  && !func->common.scope
2540 			  && object->handlers->get_class_name != std_object_handlers.get_class_name) {
2541 				zend_string_release(class_name);
2542 			}
2543 		}
2544 		zend_printf("%s(", function_name);
2545 		if (Z_TYPE(arg_array) != IS_UNDEF) {
2546 			debug_print_backtrace_args(&arg_array);
2547 			zval_ptr_dtor(&arg_array);
2548 		}
2549 		if (filename) {
2550 			zend_printf(") called at [%s:%d]\n", filename, lineno);
2551 		} else {
2552 			zend_execute_data *prev_call = skip;
2553 			zend_execute_data *prev = skip->prev_execute_data;
2554 
2555 			while (prev) {
2556 				if (prev_call &&
2557 				    prev_call->func &&
2558 					!ZEND_USER_CODE(prev_call->func->common.type)) {
2559 					prev = NULL;
2560 					break;
2561 				}
2562 				if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
2563 					zend_printf(") called at [%s:%d]\n", ZSTR_VAL(prev->func->op_array.filename), prev->opline->lineno);
2564 					break;
2565 				}
2566 				prev_call = prev;
2567 				prev = prev->prev_execute_data;
2568 			}
2569 			if (!prev) {
2570 				ZEND_PUTS(")\n");
2571 			}
2572 		}
2573 		include_filename = filename;
2574 		call = skip;
2575 		ptr = skip->prev_execute_data;
2576 		++indent;
2577 	}
2578 }
2579 
2580 /* }}} */
2581 
zend_fetch_debug_backtrace(zval * return_value,int skip_last,int options,int limit)2582 ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit) /* {{{ */
2583 {
2584 	zend_execute_data *ptr, *skip, *call = NULL;
2585 	zend_object *object;
2586 	int lineno, frameno = 0;
2587 	zend_function *func;
2588 	zend_string *function_name;
2589 	zend_string *filename;
2590 	zend_string *include_filename = NULL;
2591 	zval stack_frame, tmp;
2592 
2593 	array_init(return_value);
2594 
2595 	if (!(ptr = EG(current_execute_data))) {
2596 		return;
2597 	}
2598 
2599 	if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type)) {
2600 		call = ptr;
2601 		ptr = ptr->prev_execute_data;
2602 	}
2603 
2604 	if (ptr) {
2605 		if (skip_last) {
2606 			/* skip debug_backtrace() */
2607 			call = ptr;
2608 			ptr = ptr->prev_execute_data;
2609 		} else {
2610 			/* skip "new Exception()" */
2611 			if (ptr->func && ZEND_USER_CODE(ptr->func->common.type) && (ptr->opline->opcode == ZEND_NEW)) {
2612 				call = ptr;
2613 				ptr = ptr->prev_execute_data;
2614 			}
2615 		}
2616 		if (!call) {
2617 			call = ptr;
2618 			ptr = ptr->prev_execute_data;
2619 		}
2620 	}
2621 
2622 	while (ptr && (limit == 0 || frameno < limit)) {
2623 		frameno++;
2624 		array_init(&stack_frame);
2625 
2626 		ptr = zend_generator_check_placeholder_frame(ptr);
2627 
2628 		skip = ptr;
2629 		/* skip internal handler */
2630 		if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
2631 		    skip->prev_execute_data &&
2632 		    skip->prev_execute_data->func &&
2633 		    ZEND_USER_CODE(skip->prev_execute_data->func->common.type) &&
2634 		    skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
2635 		    skip->prev_execute_data->opline->opcode != ZEND_DO_ICALL &&
2636 		    skip->prev_execute_data->opline->opcode != ZEND_DO_UCALL &&
2637 		    skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
2638 		    skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
2639 			skip = skip->prev_execute_data;
2640 		}
2641 
2642 		if (skip->func && ZEND_USER_CODE(skip->func->common.type)) {
2643 			filename = skip->func->op_array.filename;
2644 			if (skip->opline->opcode == ZEND_HANDLE_EXCEPTION) {
2645 				if (EG(opline_before_exception)) {
2646 					lineno = EG(opline_before_exception)->lineno;
2647 				} else {
2648 					lineno = skip->func->op_array.line_end;
2649 				}
2650 			} else {
2651 				lineno = skip->opline->lineno;
2652 			}
2653 			ZVAL_STR_COPY(&tmp, filename);
2654 			zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_FILE], &tmp);
2655 			ZVAL_LONG(&tmp, lineno);
2656 			zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_LINE], &tmp);
2657 
2658 			/* try to fetch args only if an FCALL was just made - elsewise we're in the middle of a function
2659 			 * and debug_baktrace() might have been called by the error_handler. in this case we don't
2660 			 * want to pop anything of the argument-stack */
2661 		} else {
2662 			zend_execute_data *prev_call = skip;
2663 			zend_execute_data *prev = skip->prev_execute_data;
2664 
2665 			while (prev) {
2666 				if (prev_call &&
2667 				    prev_call->func &&
2668 					!ZEND_USER_CODE(prev_call->func->common.type) &&
2669 					!(prev_call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
2670 					break;
2671 				}
2672 				if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
2673 					ZVAL_STR_COPY(&tmp, prev->func->op_array.filename);
2674 					zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_FILE], &tmp);
2675 					ZVAL_LONG(&tmp, prev->opline->lineno);
2676 					zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_LINE], &tmp);
2677 					break;
2678 				}
2679 				prev_call = prev;
2680 				prev = prev->prev_execute_data;
2681 			}
2682 			filename = NULL;
2683 		}
2684 
2685 		/* $this may be passed into regular internal functions */
2686 		object = (call && (Z_TYPE(call->This) == IS_OBJECT)) ? Z_OBJ(call->This) : NULL;
2687 
2688 		if (call && call->func) {
2689 			func = call->func;
2690 			function_name = (func->common.scope &&
2691 			                 func->common.scope->trait_aliases) ?
2692 				zend_resolve_method_name(
2693 					(object ? object->ce : func->common.scope), func) :
2694 				func->common.function_name;
2695 		} else {
2696 			func = NULL;
2697 			function_name = NULL;
2698 		}
2699 
2700 		if (function_name) {
2701 			ZVAL_STR_COPY(&tmp, function_name);
2702 			zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_FUNCTION], &tmp);
2703 
2704 			if (object) {
2705 				if (func->common.scope) {
2706 					ZVAL_STR_COPY(&tmp, func->common.scope->name);
2707 				} else if (object->handlers->get_class_name == std_object_handlers.get_class_name) {
2708 					ZVAL_STR_COPY(&tmp, object->ce->name);
2709 				} else {
2710 					ZVAL_STR(&tmp, object->handlers->get_class_name(object));
2711 				}
2712 				zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_CLASS], &tmp);
2713 				if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) {
2714 					ZVAL_OBJ(&tmp, object);
2715 					zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_OBJECT], &tmp);
2716 					Z_ADDREF(tmp);
2717 				}
2718 
2719 				ZVAL_INTERNED_STR(&tmp, CG(known_strings)[ZEND_STR_OBJECT_OPERATOR]);
2720 				zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_TYPE], &tmp);
2721 			} else if (func->common.scope) {
2722 				ZVAL_STR_COPY(&tmp, func->common.scope->name);
2723 				zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_CLASS], &tmp);
2724 				ZVAL_INTERNED_STR(&tmp, CG(known_strings)[ZEND_STR_PAAMAYIM_NEKUDOTAYIM]);
2725 				zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_TYPE], &tmp);
2726 			}
2727 
2728 			if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 &&
2729 				func->type != ZEND_EVAL_CODE) {
2730 
2731 				debug_backtrace_get_args(call, &tmp);
2732 				zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_ARGS], &tmp);
2733 			}
2734 		} else {
2735 			/* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
2736 			zend_bool build_filename_arg = 1;
2737 			zend_string *pseudo_function_name;
2738 
2739 			if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
2740 				/* can happen when calling eval from a custom sapi */
2741 				pseudo_function_name = CG(known_strings)[ZEND_STR_UNKNOWN];
2742 				build_filename_arg = 0;
2743 			} else
2744 			switch (ptr->opline->extended_value) {
2745 				case ZEND_EVAL:
2746 					pseudo_function_name = CG(known_strings)[ZEND_STR_EVAL];
2747 					build_filename_arg = 0;
2748 					break;
2749 				case ZEND_INCLUDE:
2750 					pseudo_function_name = CG(known_strings)[ZEND_STR_INCLUDE];
2751 					break;
2752 				case ZEND_REQUIRE:
2753 					pseudo_function_name = CG(known_strings)[ZEND_STR_REQUIRE];
2754 					break;
2755 				case ZEND_INCLUDE_ONCE:
2756 					pseudo_function_name = CG(known_strings)[ZEND_STR_INCLUDE_ONCE];
2757 					break;
2758 				case ZEND_REQUIRE_ONCE:
2759 					pseudo_function_name = CG(known_strings)[ZEND_STR_REQUIRE_ONCE];
2760 					break;
2761 				default:
2762 					/* this can actually happen if you use debug_backtrace() in your error_handler and
2763 					 * you're in the top-scope */
2764 					pseudo_function_name = CG(known_strings)[ZEND_STR_UNKNOWN];
2765 					build_filename_arg = 0;
2766 					break;
2767 			}
2768 
2769 			if (build_filename_arg && include_filename) {
2770 				zval arg_array;
2771 
2772 				array_init(&arg_array);
2773 
2774 				/* include_filename always points to the last filename of the last last called-function.
2775 				   if we have called include in the frame above - this is the file we have included.
2776 				 */
2777 
2778 				ZVAL_STR_COPY(&tmp, include_filename);
2779 				zend_hash_next_index_insert_new(Z_ARRVAL(arg_array), &tmp);
2780 				zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_ARGS], &arg_array);
2781 			}
2782 
2783 			ZVAL_INTERNED_STR(&tmp, pseudo_function_name);
2784 			zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_FUNCTION], &tmp);
2785 		}
2786 
2787 		zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &stack_frame);
2788 
2789 		include_filename = filename;
2790 
2791 		call = skip;
2792 		ptr = skip->prev_execute_data;
2793 	}
2794 }
2795 /* }}} */
2796 
2797 /* {{{ proto array debug_backtrace([int options[, int limit]])
2798    Return backtrace as array */
ZEND_FUNCTION(debug_backtrace)2799 ZEND_FUNCTION(debug_backtrace)
2800 {
2801 	zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
2802 	zend_long limit = 0;
2803 
2804 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) {
2805 		return;
2806 	}
2807 
2808 	zend_fetch_debug_backtrace(return_value, 1, options, limit);
2809 }
2810 /* }}} */
2811 
2812 /* {{{ proto bool extension_loaded(string extension_name)
2813    Returns true if the named extension is loaded */
ZEND_FUNCTION(extension_loaded)2814 ZEND_FUNCTION(extension_loaded)
2815 {
2816 	zend_string *extension_name;
2817 	zend_string *lcname;
2818 
2819 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &extension_name) == FAILURE) {
2820 		return;
2821 	}
2822 
2823 	lcname = zend_string_tolower(extension_name);
2824 	if (zend_hash_exists(&module_registry, lcname)) {
2825 		RETVAL_TRUE;
2826 	} else {
2827 		RETVAL_FALSE;
2828 	}
2829 	zend_string_release(lcname);
2830 }
2831 /* }}} */
2832 
2833 /* {{{ proto array get_extension_funcs(string extension_name)
2834    Returns an array with the names of functions belonging to the named extension */
ZEND_FUNCTION(get_extension_funcs)2835 ZEND_FUNCTION(get_extension_funcs)
2836 {
2837 	zend_string *extension_name;
2838 	zend_string *lcname;
2839 	int array;
2840 	zend_module_entry *module;
2841 	zend_function *zif;
2842 
2843 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &extension_name) == FAILURE) {
2844 		return;
2845 	}
2846 	if (strncasecmp(ZSTR_VAL(extension_name), "zend", sizeof("zend"))) {
2847 		lcname = zend_string_tolower(extension_name);
2848 		module = zend_hash_find_ptr(&module_registry, lcname);
2849 		zend_string_release(lcname);
2850 	} else {
2851 		module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core") - 1);
2852 	}
2853 
2854 	if (!module) {
2855 		RETURN_FALSE;
2856 	}
2857 
2858 	if (module->functions) {
2859 		/* avoid BC break, if functions list is empty, will return an empty array */
2860 		array_init(return_value);
2861 		array = 1;
2862 	} else {
2863 		array = 0;
2864 	}
2865 
2866 	ZEND_HASH_FOREACH_PTR(CG(function_table), zif) {
2867 		if (zif->common.type == ZEND_INTERNAL_FUNCTION
2868 			&& zif->internal_function.module == module) {
2869 			if (!array) {
2870 				array_init(return_value);
2871 				array = 1;
2872 			}
2873 			add_next_index_str(return_value, zend_string_copy(zif->common.function_name));
2874 		}
2875 	} ZEND_HASH_FOREACH_END();
2876 
2877 	if (!array) {
2878 		RETURN_FALSE;
2879 	}
2880 }
2881 /* }}} */
2882 
2883 /*
2884  * Local variables:
2885  * tab-width: 4
2886  * c-basic-offset: 4
2887  * indent-tabs-mode: t
2888  * End:
2889  */
2890