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