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