1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Andi Gutmans <andi@php.net> |
16 | Zeev Suraski <zeev@php.net> |
17 | Dmitry Stogov <dmitry@php.net> |
18 +----------------------------------------------------------------------+
19 */
20
21 #include <stdio.h>
22 #include <signal.h>
23
24 #include "zend.h"
25 #include "zend_compile.h"
26 #include "zend_execute.h"
27 #include "zend_API.h"
28 #include "zend_stack.h"
29 #include "zend_constants.h"
30 #include "zend_extensions.h"
31 #include "zend_exceptions.h"
32 #include "zend_closures.h"
33 #include "zend_generators.h"
34 #include "zend_vm.h"
35 #include "zend_float.h"
36 #include "zend_weakrefs.h"
37 #include "zend_inheritance.h"
38 #include "zend_observer.h"
39 #ifdef HAVE_SYS_TIME_H
40 #include <sys/time.h>
41 #endif
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45
46 ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data);
47 ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value);
48 ZEND_API zend_class_entry *(*zend_autoload)(zend_string *name, zend_string *lc_name);
49
50 /* true globals */
51 ZEND_API const zend_fcall_info empty_fcall_info = {0};
52 ZEND_API const zend_fcall_info_cache empty_fcall_info_cache = { NULL, NULL, NULL, NULL };
53
54 #ifdef ZEND_WIN32
55 ZEND_TLS HANDLE tq_timer = NULL;
56 #endif
57
58 #if 0&&ZEND_DEBUG
59 static void (*original_sigsegv_handler)(int);
60 static void zend_handle_sigsegv(void) /* {{{ */
61 {
62 fflush(stdout);
63 fflush(stderr);
64 if (original_sigsegv_handler == zend_handle_sigsegv) {
65 signal(SIGSEGV, original_sigsegv_handler);
66 } else {
67 signal(SIGSEGV, SIG_DFL);
68 }
69 {
70
71 fprintf(stderr, "SIGSEGV caught on opcode %d on opline %d of %s() at %s:%d\n\n",
72 active_opline->opcode,
73 active_opline-EG(active_op_array)->opcodes,
74 get_active_function_name(),
75 zend_get_executed_filename(),
76 zend_get_executed_lineno());
77 /* See http://support.microsoft.com/kb/190351 */
78 #ifdef ZEND_WIN32
79 fflush(stderr);
80 #endif
81 }
82 if (original_sigsegv_handler!=zend_handle_sigsegv) {
83 original_sigsegv_handler(dummy);
84 }
85 }
86 /* }}} */
87 #endif
88
zend_extension_activator(zend_extension * extension)89 static void zend_extension_activator(zend_extension *extension) /* {{{ */
90 {
91 if (extension->activate) {
92 extension->activate();
93 }
94 }
95 /* }}} */
96
zend_extension_deactivator(zend_extension * extension)97 static void zend_extension_deactivator(zend_extension *extension) /* {{{ */
98 {
99 if (extension->deactivate) {
100 extension->deactivate();
101 }
102 }
103 /* }}} */
104
clean_non_persistent_constant_full(zval * zv)105 static int clean_non_persistent_constant_full(zval *zv) /* {{{ */
106 {
107 zend_constant *c = Z_PTR_P(zv);
108 return (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
109 }
110 /* }}} */
111
clean_non_persistent_function_full(zval * zv)112 static int clean_non_persistent_function_full(zval *zv) /* {{{ */
113 {
114 zend_function *function = Z_PTR_P(zv);
115 return (function->type == ZEND_INTERNAL_FUNCTION) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
116 }
117 /* }}} */
118
clean_non_persistent_class_full(zval * zv)119 static int clean_non_persistent_class_full(zval *zv) /* {{{ */
120 {
121 zend_class_entry *ce = Z_PTR_P(zv);
122 return (ce->type == ZEND_INTERNAL_CLASS) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
123 }
124 /* }}} */
125
init_executor(void)126 void init_executor(void) /* {{{ */
127 {
128 zend_init_fpu();
129
130 ZVAL_NULL(&EG(uninitialized_zval));
131 ZVAL_ERROR(&EG(error_zval));
132 /* destroys stack frame, therefore makes core dumps worthless */
133 #if 0&&ZEND_DEBUG
134 original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv);
135 #endif
136
137 EG(symtable_cache_ptr) = EG(symtable_cache);
138 EG(symtable_cache_limit) = EG(symtable_cache) + SYMTABLE_CACHE_SIZE;
139 EG(no_extensions) = 0;
140
141 EG(function_table) = CG(function_table);
142 EG(class_table) = CG(class_table);
143
144 EG(in_autoload) = NULL;
145 EG(error_handling) = EH_NORMAL;
146 EG(flags) = EG_FLAGS_INITIAL;
147
148 zend_vm_stack_init();
149
150 zend_hash_init(&EG(symbol_table), 64, NULL, ZVAL_PTR_DTOR, 0);
151
152 zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator);
153
154 zend_hash_init(&EG(included_files), 8, NULL, NULL, 0);
155
156 EG(ticks_count) = 0;
157
158 ZVAL_UNDEF(&EG(user_error_handler));
159 ZVAL_UNDEF(&EG(user_exception_handler));
160
161 EG(current_execute_data) = NULL;
162
163 zend_stack_init(&EG(user_error_handlers_error_reporting), sizeof(int));
164 zend_stack_init(&EG(user_error_handlers), sizeof(zval));
165 zend_stack_init(&EG(user_exception_handlers), sizeof(zval));
166
167 zend_objects_store_init(&EG(objects_store), 1024);
168
169 EG(full_tables_cleanup) = 0;
170 EG(vm_interrupt) = 0;
171 EG(timed_out) = 0;
172
173 EG(exception) = NULL;
174 EG(prev_exception) = NULL;
175
176 EG(fake_scope) = NULL;
177 EG(trampoline).common.function_name = NULL;
178
179 EG(ht_iterators_count) = sizeof(EG(ht_iterators_slots)) / sizeof(HashTableIterator);
180 EG(ht_iterators_used) = 0;
181 EG(ht_iterators) = EG(ht_iterators_slots);
182 memset(EG(ht_iterators), 0, sizeof(EG(ht_iterators_slots)));
183
184 EG(persistent_constants_count) = EG(zend_constants)->nNumUsed;
185 EG(persistent_functions_count) = EG(function_table)->nNumUsed;
186 EG(persistent_classes_count) = EG(class_table)->nNumUsed;
187
188 EG(get_gc_buffer).start = EG(get_gc_buffer).end = EG(get_gc_buffer).cur = NULL;
189
190 zend_weakrefs_init();
191
192 EG(active) = 1;
193 }
194 /* }}} */
195
zval_call_destructor(zval * zv)196 static int zval_call_destructor(zval *zv) /* {{{ */
197 {
198 if (Z_TYPE_P(zv) == IS_INDIRECT) {
199 zv = Z_INDIRECT_P(zv);
200 }
201 if (Z_TYPE_P(zv) == IS_OBJECT && Z_REFCOUNT_P(zv) == 1) {
202 return ZEND_HASH_APPLY_REMOVE;
203 } else {
204 return ZEND_HASH_APPLY_KEEP;
205 }
206 }
207 /* }}} */
208
zend_unclean_zval_ptr_dtor(zval * zv)209 static void zend_unclean_zval_ptr_dtor(zval *zv) /* {{{ */
210 {
211 if (Z_TYPE_P(zv) == IS_INDIRECT) {
212 zv = Z_INDIRECT_P(zv);
213 }
214 i_zval_ptr_dtor(zv);
215 }
216 /* }}} */
217
zend_throw_or_error(int fetch_type,zend_class_entry * exception_ce,const char * format,...)218 static ZEND_COLD void zend_throw_or_error(int fetch_type, zend_class_entry *exception_ce, const char *format, ...) /* {{{ */
219 {
220 va_list va;
221 char *message = NULL;
222
223 va_start(va, format);
224 zend_vspprintf(&message, 0, format, va);
225
226 if (fetch_type & ZEND_FETCH_CLASS_EXCEPTION) {
227 zend_throw_error(exception_ce, "%s", message);
228 } else {
229 zend_error(E_ERROR, "%s", message);
230 }
231
232 efree(message);
233 va_end(va);
234 }
235 /* }}} */
236
shutdown_destructors(void)237 void shutdown_destructors(void) /* {{{ */
238 {
239 if (CG(unclean_shutdown)) {
240 EG(symbol_table).pDestructor = zend_unclean_zval_ptr_dtor;
241 }
242 zend_try {
243 uint32_t symbols;
244 do {
245 symbols = zend_hash_num_elements(&EG(symbol_table));
246 zend_hash_reverse_apply(&EG(symbol_table), (apply_func_t) zval_call_destructor);
247 } while (symbols != zend_hash_num_elements(&EG(symbol_table)));
248 zend_objects_store_call_destructors(&EG(objects_store));
249 } zend_catch {
250 /* if we couldn't destruct cleanly, mark all objects as destructed anyway */
251 zend_objects_store_mark_destructed(&EG(objects_store));
252 } zend_end_try();
253 }
254 /* }}} */
255
shutdown_executor(void)256 void shutdown_executor(void) /* {{{ */
257 {
258 zend_string *key;
259 zval *zv;
260 #if ZEND_DEBUG
261 zend_bool fast_shutdown = 0;
262 #else
263 zend_bool fast_shutdown = is_zend_mm() && !EG(full_tables_cleanup);
264 #endif
265
266 zend_try {
267 zend_llist_destroy(&CG(open_files));
268 } zend_end_try();
269
270 EG(flags) |= EG_FLAGS_IN_RESOURCE_SHUTDOWN;
271 zend_try {
272 zend_close_rsrc_list(&EG(regular_list));
273 } zend_end_try();
274
275 /* No PHP callback functions should be called after this point. */
276 EG(active) = 0;
277
278 if (!fast_shutdown) {
279 zend_hash_graceful_reverse_destroy(&EG(symbol_table));
280
281 /* Release static properties and static variables prior to the final GC run,
282 * as they may hold GC roots. */
283 ZEND_HASH_REVERSE_FOREACH_VAL(EG(function_table), zv) {
284 zend_op_array *op_array = Z_PTR_P(zv);
285 if (op_array->type == ZEND_INTERNAL_FUNCTION) {
286 break;
287 }
288 if (op_array->static_variables) {
289 HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
290 if (ht) {
291 zend_array_release(ht);
292 ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
293 }
294 }
295 } ZEND_HASH_FOREACH_END();
296 ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) {
297 zend_class_entry *ce = Z_PTR_P(zv);
298 if (ce->default_static_members_count) {
299 zend_cleanup_internal_class_data(ce);
300 }
301 if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
302 zend_op_array *op_array;
303 ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
304 if (op_array->type == ZEND_USER_FUNCTION) {
305 if (op_array->static_variables) {
306 HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
307 if (ht) {
308 zend_array_release(ht);
309 ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
310 }
311 }
312 }
313 } ZEND_HASH_FOREACH_END();
314 }
315 } ZEND_HASH_FOREACH_END();
316
317 /* Also release error and exception handlers, which may hold objects. */
318 if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
319 zval_ptr_dtor(&EG(user_error_handler));
320 ZVAL_UNDEF(&EG(user_error_handler));
321 }
322
323 if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
324 zval_ptr_dtor(&EG(user_exception_handler));
325 ZVAL_UNDEF(&EG(user_exception_handler));
326 }
327
328 zend_stack_clean(&EG(user_error_handlers_error_reporting), NULL, 1);
329 zend_stack_clean(&EG(user_error_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);
330 zend_stack_clean(&EG(user_exception_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);
331
332 #if ZEND_DEBUG
333 if (!CG(unclean_shutdown)) {
334 gc_collect_cycles();
335 }
336 #endif
337 }
338
339 zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown);
340
341 zend_weakrefs_shutdown();
342
343 zend_try {
344 zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator);
345 } zend_end_try();
346
347 if (fast_shutdown) {
348 /* Fast Request Shutdown
349 * =====================
350 * Zend Memory Manager frees memory by its own. We don't have to free
351 * each allocated block separately.
352 */
353 zend_hash_discard(EG(zend_constants), EG(persistent_constants_count));
354 zend_hash_discard(EG(function_table), EG(persistent_functions_count));
355 zend_hash_discard(EG(class_table), EG(persistent_classes_count));
356 zend_cleanup_internal_classes();
357 } else {
358 zend_vm_stack_destroy();
359
360 if (EG(full_tables_cleanup)) {
361 zend_hash_reverse_apply(EG(zend_constants), clean_non_persistent_constant_full);
362 zend_hash_reverse_apply(EG(function_table), clean_non_persistent_function_full);
363 zend_hash_reverse_apply(EG(class_table), clean_non_persistent_class_full);
364 } else {
365 ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(zend_constants), key, zv) {
366 zend_constant *c = Z_PTR_P(zv);
367 if (_idx == EG(persistent_constants_count)) {
368 break;
369 }
370 zval_ptr_dtor_nogc(&c->value);
371 if (c->name) {
372 zend_string_release_ex(c->name, 0);
373 }
374 efree(c);
375 zend_string_release_ex(key, 0);
376 } ZEND_HASH_FOREACH_END_DEL();
377
378 ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(function_table), key, zv) {
379 zend_function *func = Z_PTR_P(zv);
380 if (_idx == EG(persistent_functions_count)) {
381 break;
382 }
383 destroy_op_array(&func->op_array);
384 zend_string_release_ex(key, 0);
385 } ZEND_HASH_FOREACH_END_DEL();
386
387 ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) {
388 if (_idx == EG(persistent_classes_count)) {
389 break;
390 }
391 destroy_zend_class(zv);
392 zend_string_release_ex(key, 0);
393 } ZEND_HASH_FOREACH_END_DEL();
394 }
395
396 while (EG(symtable_cache_ptr) > EG(symtable_cache)) {
397 EG(symtable_cache_ptr)--;
398 zend_hash_destroy(*EG(symtable_cache_ptr));
399 FREE_HASHTABLE(*EG(symtable_cache_ptr));
400 }
401
402 zend_hash_destroy(&EG(included_files));
403
404 zend_stack_destroy(&EG(user_error_handlers_error_reporting));
405 zend_stack_destroy(&EG(user_error_handlers));
406 zend_stack_destroy(&EG(user_exception_handlers));
407 zend_objects_store_destroy(&EG(objects_store));
408 if (EG(in_autoload)) {
409 zend_hash_destroy(EG(in_autoload));
410 FREE_HASHTABLE(EG(in_autoload));
411 }
412
413 if (EG(ht_iterators) != EG(ht_iterators_slots)) {
414 efree(EG(ht_iterators));
415 }
416 }
417
418 #if ZEND_DEBUG
419 if (EG(ht_iterators_used) && !CG(unclean_shutdown)) {
420 zend_error(E_WARNING, "Leaked %" PRIu32 " hashtable iterators", EG(ht_iterators_used));
421 }
422 #endif
423
424 /* Check whether anyone is hogging the trampoline. */
425 ZEND_ASSERT(EG(trampoline).common.function_name == NULL || CG(unclean_shutdown));
426
427 EG(ht_iterators_used) = 0;
428
429 zend_shutdown_fpu();
430 }
431 /* }}} */
432
433 /* return class name and "::" or "". */
get_active_class_name(const char ** space)434 ZEND_API const char *get_active_class_name(const char **space) /* {{{ */
435 {
436 zend_function *func;
437
438 if (!zend_is_executing()) {
439 if (space) {
440 *space = "";
441 }
442 return "";
443 }
444
445 func = EG(current_execute_data)->func;
446
447 switch (func->type) {
448 case ZEND_USER_FUNCTION:
449 case ZEND_INTERNAL_FUNCTION:
450 {
451 zend_class_entry *ce = func->common.scope;
452
453 if (space) {
454 *space = ce ? "::" : "";
455 }
456 return ce ? ZSTR_VAL(ce->name) : "";
457 }
458 default:
459 if (space) {
460 *space = "";
461 }
462 return "";
463 }
464 }
465 /* }}} */
466
get_active_function_name(void)467 ZEND_API const char *get_active_function_name(void) /* {{{ */
468 {
469 zend_function *func;
470
471 if (!zend_is_executing()) {
472 return NULL;
473 }
474
475 func = EG(current_execute_data)->func;
476
477 switch (func->type) {
478 case ZEND_USER_FUNCTION: {
479 zend_string *function_name = func->common.function_name;
480
481 if (function_name) {
482 return ZSTR_VAL(function_name);
483 } else {
484 return "main";
485 }
486 }
487 break;
488 case ZEND_INTERNAL_FUNCTION:
489 return ZSTR_VAL(func->common.function_name);
490 break;
491 default:
492 return NULL;
493 }
494 }
495 /* }}} */
496
get_active_function_or_method_name(void)497 ZEND_API zend_string *get_active_function_or_method_name(void) /* {{{ */
498 {
499 ZEND_ASSERT(zend_is_executing());
500
501 return get_function_or_method_name(EG(current_execute_data)->func);
502 }
503 /* }}} */
504
get_function_or_method_name(const zend_function * func)505 ZEND_API zend_string *get_function_or_method_name(const zend_function *func) /* {{{ */
506 {
507 if (func->common.scope && func->common.function_name) {
508 return zend_create_member_string(func->common.scope->name, func->common.function_name);
509 }
510
511 return func->common.function_name ? zend_string_copy(func->common.function_name) : zend_string_init("main", sizeof("main") - 1, 0);
512 }
513 /* }}} */
514
get_active_function_arg_name(uint32_t arg_num)515 ZEND_API const char *get_active_function_arg_name(uint32_t arg_num) /* {{{ */
516 {
517 zend_function *func;
518
519 if (!zend_is_executing()) {
520 return NULL;
521 }
522
523 func = EG(current_execute_data)->func;
524
525 return get_function_arg_name(func, arg_num);
526 }
527 /* }}} */
528
get_function_arg_name(const zend_function * func,uint32_t arg_num)529 ZEND_API const char *get_function_arg_name(const zend_function *func, uint32_t arg_num) /* {{{ */
530 {
531 if (!func || func->common.num_args < arg_num) {
532 return NULL;
533 }
534
535 if (func->type == ZEND_USER_FUNCTION || (func->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
536 return ZSTR_VAL(func->common.arg_info[arg_num - 1].name);
537 } else {
538 return ((zend_internal_arg_info*) func->common.arg_info)[arg_num - 1].name;
539 }
540 }
541 /* }}} */
542
zend_get_executed_filename(void)543 ZEND_API const char *zend_get_executed_filename(void) /* {{{ */
544 {
545 zend_execute_data *ex = EG(current_execute_data);
546
547 while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
548 ex = ex->prev_execute_data;
549 }
550 if (ex) {
551 return ZSTR_VAL(ex->func->op_array.filename);
552 } else {
553 return "[no active file]";
554 }
555 }
556 /* }}} */
557
zend_get_executed_filename_ex(void)558 ZEND_API zend_string *zend_get_executed_filename_ex(void) /* {{{ */
559 {
560 zend_execute_data *ex = EG(current_execute_data);
561
562 while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
563 ex = ex->prev_execute_data;
564 }
565 if (ex) {
566 return ex->func->op_array.filename;
567 } else {
568 return NULL;
569 }
570 }
571 /* }}} */
572
zend_get_executed_lineno(void)573 ZEND_API uint32_t zend_get_executed_lineno(void) /* {{{ */
574 {
575 zend_execute_data *ex = EG(current_execute_data);
576
577 while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
578 ex = ex->prev_execute_data;
579 }
580 if (ex) {
581 if (EG(exception) && ex->opline->opcode == ZEND_HANDLE_EXCEPTION &&
582 ex->opline->lineno == 0 && EG(opline_before_exception)) {
583 return EG(opline_before_exception)->lineno;
584 }
585 return ex->opline->lineno;
586 } else {
587 return 0;
588 }
589 }
590 /* }}} */
591
zend_get_executed_scope(void)592 ZEND_API zend_class_entry *zend_get_executed_scope(void) /* {{{ */
593 {
594 zend_execute_data *ex = EG(current_execute_data);
595
596 while (1) {
597 if (!ex) {
598 return NULL;
599 } else if (ex->func && (ZEND_USER_CODE(ex->func->type) || ex->func->common.scope)) {
600 return ex->func->common.scope;
601 }
602 ex = ex->prev_execute_data;
603 }
604 }
605 /* }}} */
606
zend_is_executing(void)607 ZEND_API zend_bool zend_is_executing(void) /* {{{ */
608 {
609 return EG(current_execute_data) != 0;
610 }
611 /* }}} */
612
zval_update_constant_ex(zval * p,zend_class_entry * scope)613 ZEND_API zend_result zval_update_constant_ex(zval *p, zend_class_entry *scope) /* {{{ */
614 {
615 if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
616 zend_ast *ast = Z_ASTVAL_P(p);
617
618 if (ast->kind == ZEND_AST_CONSTANT) {
619 zend_string *name = zend_ast_get_constant_name(ast);
620 zval *zv = zend_get_constant_ex(name, scope, ast->attr);
621 if (UNEXPECTED(zv == NULL)) {
622 return FAILURE;
623 }
624
625 zval_ptr_dtor_nogc(p);
626 ZVAL_COPY_OR_DUP(p, zv);
627 } else {
628 zval tmp;
629
630 if (UNEXPECTED(zend_ast_evaluate(&tmp, ast, scope) != SUCCESS)) {
631 return FAILURE;
632 }
633 zval_ptr_dtor_nogc(p);
634 ZVAL_COPY_VALUE(p, &tmp);
635 }
636 }
637 return SUCCESS;
638 }
639 /* }}} */
640
zval_update_constant(zval * pp)641 ZEND_API zend_result zval_update_constant(zval *pp) /* {{{ */
642 {
643 return zval_update_constant_ex(pp, EG(current_execute_data) ? zend_get_executed_scope() : CG(active_class_entry));
644 }
645 /* }}} */
646
_call_user_function_impl(zval * object,zval * function_name,zval * retval_ptr,uint32_t param_count,zval params[],HashTable * named_params)647 zend_result _call_user_function_impl(zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], HashTable *named_params) /* {{{ */
648 {
649 zend_fcall_info fci;
650
651 fci.size = sizeof(fci);
652 fci.object = object ? Z_OBJ_P(object) : NULL;
653 ZVAL_COPY_VALUE(&fci.function_name, function_name);
654 fci.retval = retval_ptr;
655 fci.param_count = param_count;
656 fci.params = params;
657 fci.named_params = named_params;
658
659 return zend_call_function(&fci, NULL);
660 }
661 /* }}} */
662
zend_call_function(zend_fcall_info * fci,zend_fcall_info_cache * fci_cache)663 zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /* {{{ */
664 {
665 uint32_t i;
666 zend_execute_data *call, dummy_execute_data;
667 zend_fcall_info_cache fci_cache_local;
668 zend_function *func;
669 uint32_t call_info;
670 void *object_or_called_scope;
671 zend_class_entry *orig_fake_scope;
672
673 ZVAL_UNDEF(fci->retval);
674
675 if (!EG(active)) {
676 return FAILURE; /* executor is already inactive */
677 }
678
679 if (EG(exception)) {
680 return FAILURE; /* we would result in an instable executor otherwise */
681 }
682
683 ZEND_ASSERT(fci->size == sizeof(zend_fcall_info));
684
685 /* Initialize execute_data */
686 if (!EG(current_execute_data)) {
687 /* This only happens when we're called outside any execute()'s
688 * It shouldn't be strictly necessary to NULL execute_data out,
689 * but it may make bugs easier to spot
690 */
691 memset(&dummy_execute_data, 0, sizeof(zend_execute_data));
692 EG(current_execute_data) = &dummy_execute_data;
693 } else if (EG(current_execute_data)->func &&
694 ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
695 EG(current_execute_data)->opline->opcode != ZEND_DO_FCALL &&
696 EG(current_execute_data)->opline->opcode != ZEND_DO_ICALL &&
697 EG(current_execute_data)->opline->opcode != ZEND_DO_UCALL &&
698 EG(current_execute_data)->opline->opcode != ZEND_DO_FCALL_BY_NAME) {
699 /* Insert fake frame in case of include or magic calls */
700 dummy_execute_data = *EG(current_execute_data);
701 dummy_execute_data.prev_execute_data = EG(current_execute_data);
702 dummy_execute_data.call = NULL;
703 dummy_execute_data.opline = NULL;
704 dummy_execute_data.func = NULL;
705 EG(current_execute_data) = &dummy_execute_data;
706 }
707
708 if (!fci_cache || !fci_cache->function_handler) {
709 char *error = NULL;
710
711 if (!fci_cache) {
712 fci_cache = &fci_cache_local;
713 }
714
715 if (!zend_is_callable_ex(&fci->function_name, fci->object, IS_CALLABLE_CHECK_SILENT, NULL, fci_cache, &error)) {
716 if (error) {
717 zend_string *callable_name
718 = zend_get_callable_name_ex(&fci->function_name, fci->object);
719 zend_error(E_WARNING, "Invalid callback %s, %s", ZSTR_VAL(callable_name), error);
720 efree(error);
721 zend_string_release_ex(callable_name, 0);
722 }
723 if (EG(current_execute_data) == &dummy_execute_data) {
724 EG(current_execute_data) = dummy_execute_data.prev_execute_data;
725 }
726 return FAILURE;
727 }
728
729 ZEND_ASSERT(!error);
730 }
731
732 func = fci_cache->function_handler;
733 if ((func->common.fn_flags & ZEND_ACC_STATIC) || !fci_cache->object) {
734 fci->object = NULL;
735 object_or_called_scope = fci_cache->called_scope;
736 call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC;
737 } else {
738 fci->object = fci_cache->object;
739 object_or_called_scope = fci->object;
740 call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC | ZEND_CALL_HAS_THIS;
741 }
742
743 call = zend_vm_stack_push_call_frame(call_info,
744 func, fci->param_count, object_or_called_scope);
745
746 if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_DEPRECATED)) {
747 zend_deprecated_function(func);
748
749 if (UNEXPECTED(EG(exception))) {
750 zend_vm_stack_free_call_frame(call);
751 if (EG(current_execute_data) == &dummy_execute_data) {
752 EG(current_execute_data) = dummy_execute_data.prev_execute_data;
753 zend_rethrow_exception(EG(current_execute_data));
754 }
755 return FAILURE;
756 }
757 }
758
759 for (i=0; i<fci->param_count; i++) {
760 zval *param = ZEND_CALL_ARG(call, i+1);
761 zval *arg = &fci->params[i];
762 zend_bool must_wrap = 0;
763 if (UNEXPECTED(Z_ISUNDEF_P(arg))) {
764 /* Allow forwarding undef slots. This is only used by Closure::__invoke(). */
765 ZVAL_UNDEF(param);
766 ZEND_ADD_CALL_FLAG(call, ZEND_CALL_MAY_HAVE_UNDEF);
767 continue;
768 }
769
770 if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) {
771 if (UNEXPECTED(!Z_ISREF_P(arg))) {
772 if (!ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
773 /* By-value send is not allowed -- emit a warning,
774 * and perform the call with the value wrapped in a reference. */
775 zend_param_must_be_ref(func, i + 1);
776 must_wrap = 1;
777 if (UNEXPECTED(EG(exception))) {
778 ZEND_CALL_NUM_ARGS(call) = i;
779 cleanup_args:
780 zend_vm_stack_free_args(call);
781 zend_vm_stack_free_call_frame(call);
782 if (EG(current_execute_data) == &dummy_execute_data) {
783 EG(current_execute_data) = dummy_execute_data.prev_execute_data;
784 }
785 return FAILURE;
786 }
787 }
788 }
789 } else {
790 if (Z_ISREF_P(arg) &&
791 !(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
792 /* don't separate references for __call */
793 arg = Z_REFVAL_P(arg);
794 }
795 }
796
797 if (EXPECTED(!must_wrap)) {
798 ZVAL_COPY(param, arg);
799 } else {
800 Z_TRY_ADDREF_P(arg);
801 ZVAL_NEW_REF(param, arg);
802 }
803 }
804
805 if (fci->named_params) {
806 zend_string *name;
807 zval *arg;
808 uint32_t arg_num = ZEND_CALL_NUM_ARGS(call) + 1;
809 zend_bool have_named_params = 0;
810 ZEND_HASH_FOREACH_STR_KEY_VAL(fci->named_params, name, arg) {
811 zend_bool must_wrap = 0;
812 zval *target;
813 if (name) {
814 void *cache_slot[2] = {NULL, NULL};
815 have_named_params = 1;
816 target = zend_handle_named_arg(&call, name, &arg_num, cache_slot);
817 if (!target) {
818 goto cleanup_args;
819 }
820 } else {
821 if (have_named_params) {
822 zend_throw_error(NULL,
823 "Cannot use positional argument after named argument");
824 goto cleanup_args;
825 }
826
827 zend_vm_stack_extend_call_frame(&call, arg_num - 1, 1);
828 target = ZEND_CALL_ARG(call, arg_num);
829 }
830
831 if (ARG_SHOULD_BE_SENT_BY_REF(func, arg_num)) {
832 if (UNEXPECTED(!Z_ISREF_P(arg))) {
833 if (!ARG_MAY_BE_SENT_BY_REF(func, arg_num)) {
834 /* By-value send is not allowed -- emit a warning,
835 * and perform the call with the value wrapped in a reference. */
836 zend_param_must_be_ref(func, arg_num);
837 must_wrap = 1;
838 if (UNEXPECTED(EG(exception))) {
839 goto cleanup_args;
840 }
841 }
842 }
843 } else {
844 if (Z_ISREF_P(arg) &&
845 !(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
846 /* don't separate references for __call */
847 arg = Z_REFVAL_P(arg);
848 }
849 }
850
851 if (EXPECTED(!must_wrap)) {
852 ZVAL_COPY(target, arg);
853 } else {
854 Z_TRY_ADDREF_P(arg);
855 ZVAL_NEW_REF(target, arg);
856 }
857 if (!name) {
858 ZEND_CALL_NUM_ARGS(call)++;
859 arg_num++;
860 }
861 } ZEND_HASH_FOREACH_END();
862 }
863
864 if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_MAY_HAVE_UNDEF)) {
865 if (zend_handle_undef_args(call) == FAILURE) {
866 zend_vm_stack_free_args(call);
867 zend_vm_stack_free_call_frame(call);
868 if (EG(current_execute_data) == &dummy_execute_data) {
869 EG(current_execute_data) = dummy_execute_data.prev_execute_data;
870 }
871 return SUCCESS;
872 }
873 }
874
875 if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
876 uint32_t call_info;
877
878 GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
879 call_info = ZEND_CALL_CLOSURE;
880 if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
881 call_info |= ZEND_CALL_FAKE_CLOSURE;
882 }
883 ZEND_ADD_CALL_FLAG(call, call_info);
884 }
885
886 orig_fake_scope = EG(fake_scope);
887 EG(fake_scope) = NULL;
888 if (func->type == ZEND_USER_FUNCTION) {
889 int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
890 const zend_op *current_opline_before_exception = EG(opline_before_exception);
891 uint32_t orig_jit_trace_num = EG(jit_trace_num);
892
893 zend_init_func_execute_data(call, &func->op_array, fci->retval);
894 ZEND_OBSERVER_FCALL_BEGIN(call);
895 zend_execute_ex(call);
896 EG(jit_trace_num) = orig_jit_trace_num;
897 EG(opline_before_exception) = current_opline_before_exception;
898 if (call_via_handler) {
899 /* We must re-initialize function again */
900 fci_cache->function_handler = NULL;
901 }
902 } else {
903 int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
904
905 ZEND_ASSERT(func->type == ZEND_INTERNAL_FUNCTION);
906 ZVAL_NULL(fci->retval);
907 call->prev_execute_data = EG(current_execute_data);
908 EG(current_execute_data) = call;
909 if (EXPECTED(zend_execute_internal == NULL)) {
910 /* saves one function call if zend_execute_internal is not used */
911 func->internal_function.handler(call, fci->retval);
912 } else {
913 zend_execute_internal(call, fci->retval);
914 }
915 EG(current_execute_data) = call->prev_execute_data;
916 zend_vm_stack_free_args(call);
917 if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
918 zend_array_release(call->extra_named_params);
919 }
920
921 if (EG(exception)) {
922 zval_ptr_dtor(fci->retval);
923 ZVAL_UNDEF(fci->retval);
924 }
925
926 if (call_via_handler) {
927 /* We must re-initialize function again */
928 fci_cache->function_handler = NULL;
929 }
930
931 /* This flag is regularly checked while running user functions, but not internal
932 * So see whether interrupt flag was set while the function was running... */
933 if (EG(vm_interrupt)) {
934 EG(vm_interrupt) = 0;
935 if (EG(timed_out)) {
936 zend_timeout();
937 } else if (zend_interrupt_function) {
938 zend_interrupt_function(EG(current_execute_data));
939 }
940 }
941 }
942 EG(fake_scope) = orig_fake_scope;
943
944 zend_vm_stack_free_call_frame(call);
945
946 if (EG(current_execute_data) == &dummy_execute_data) {
947 EG(current_execute_data) = dummy_execute_data.prev_execute_data;
948 }
949
950 if (UNEXPECTED(EG(exception))) {
951 if (UNEXPECTED(!EG(current_execute_data))) {
952 zend_throw_exception_internal(NULL);
953 } else if (EG(current_execute_data)->func &&
954 ZEND_USER_CODE(EG(current_execute_data)->func->common.type)) {
955 zend_rethrow_exception(EG(current_execute_data));
956 }
957 }
958
959 return SUCCESS;
960 }
961 /* }}} */
962
zend_call_known_function(zend_function * fn,zend_object * object,zend_class_entry * called_scope,zval * retval_ptr,uint32_t param_count,zval * params,HashTable * named_params)963 ZEND_API void zend_call_known_function(
964 zend_function *fn, zend_object *object, zend_class_entry *called_scope, zval *retval_ptr,
965 uint32_t param_count, zval *params, HashTable *named_params)
966 {
967 zval retval;
968 zend_fcall_info fci;
969 zend_fcall_info_cache fcic;
970
971 ZEND_ASSERT(fn && "zend_function must be passed!");
972
973 fci.size = sizeof(fci);
974 fci.object = object;
975 fci.retval = retval_ptr ? retval_ptr : &retval;
976 fci.param_count = param_count;
977 fci.params = params;
978 fci.named_params = named_params;
979 ZVAL_UNDEF(&fci.function_name); /* Unused */
980
981 fcic.function_handler = fn;
982 fcic.object = object;
983 fcic.called_scope = called_scope;
984
985 zend_result result = zend_call_function(&fci, &fcic);
986 if (UNEXPECTED(result == FAILURE)) {
987 if (!EG(exception)) {
988 zend_error_noreturn(E_CORE_ERROR, "Couldn't execute method %s%s%s",
989 fn->common.scope ? ZSTR_VAL(fn->common.scope->name) : "",
990 fn->common.scope ? "::" : "", ZSTR_VAL(fn->common.function_name));
991 }
992 }
993
994 if (!retval_ptr) {
995 zval_ptr_dtor(&retval);
996 }
997 }
998
zend_call_known_instance_method_with_2_params(zend_function * fn,zend_object * object,zval * retval_ptr,zval * param1,zval * param2)999 ZEND_API void zend_call_known_instance_method_with_2_params(
1000 zend_function *fn, zend_object *object, zval *retval_ptr, zval *param1, zval *param2)
1001 {
1002 zval params[2];
1003 ZVAL_COPY_VALUE(¶ms[0], param1);
1004 ZVAL_COPY_VALUE(¶ms[1], param2);
1005 zend_call_known_instance_method(fn, object, retval_ptr, 2, params);
1006 }
1007
1008 /* 0-9 a-z A-Z _ \ 0x80-0xff */
1009 static const uint32_t valid_chars[8] = {
1010 0x00000000,
1011 0x03ff0000,
1012 0x97fffffe,
1013 0x07fffffe,
1014 0xffffffff,
1015 0xffffffff,
1016 0xffffffff,
1017 0xffffffff,
1018 };
1019
zend_is_valid_class_name(zend_string * name)1020 ZEND_API zend_bool zend_is_valid_class_name(zend_string *name) {
1021 for (size_t i = 0; i < ZSTR_LEN(name); i++) {
1022 unsigned char c = ZSTR_VAL(name)[i];
1023 if (!ZEND_BIT_TEST(valid_chars, c)) {
1024 return 0;
1025 }
1026 }
1027 return 1;
1028 }
1029
zend_lookup_class_ex(zend_string * name,zend_string * key,uint32_t flags)1030 ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *key, uint32_t flags) /* {{{ */
1031 {
1032 zend_class_entry *ce = NULL;
1033 zval *zv;
1034 zend_string *lc_name;
1035 zend_string *autoload_name;
1036
1037 if (key) {
1038 lc_name = key;
1039 } else {
1040 if (name == NULL || !ZSTR_LEN(name)) {
1041 return NULL;
1042 }
1043
1044 if (ZSTR_VAL(name)[0] == '\\') {
1045 lc_name = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
1046 zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
1047 } else {
1048 lc_name = zend_string_tolower(name);
1049 }
1050 }
1051
1052 zv = zend_hash_find(EG(class_table), lc_name);
1053 if (zv) {
1054 if (!key) {
1055 zend_string_release_ex(lc_name, 0);
1056 }
1057 ce = (zend_class_entry*)Z_PTR_P(zv);
1058 if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_LINKED))) {
1059 if ((flags & ZEND_FETCH_CLASS_ALLOW_UNLINKED) ||
1060 ((flags & ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED) &&
1061 (ce->ce_flags & ZEND_ACC_NEARLY_LINKED))) {
1062 ce->ce_flags |= ZEND_ACC_HAS_UNLINKED_USES;
1063 return ce;
1064 }
1065 return NULL;
1066 }
1067 return ce;
1068 }
1069
1070 /* The compiler is not-reentrant. Make sure we autoload only during run-time. */
1071 if ((flags & ZEND_FETCH_CLASS_NO_AUTOLOAD) || zend_is_compiling()) {
1072 if (!key) {
1073 zend_string_release_ex(lc_name, 0);
1074 }
1075 return NULL;
1076 }
1077
1078 if (!zend_autoload) {
1079 if (!key) {
1080 zend_string_release_ex(lc_name, 0);
1081 }
1082 return NULL;
1083 }
1084
1085 /* Verify class name before passing it to the autoloader. */
1086 if (!key && !zend_is_valid_class_name(name)) {
1087 zend_string_release_ex(lc_name, 0);
1088 return NULL;
1089 }
1090
1091 if (EG(in_autoload) == NULL) {
1092 ALLOC_HASHTABLE(EG(in_autoload));
1093 zend_hash_init(EG(in_autoload), 8, NULL, NULL, 0);
1094 }
1095
1096 if (zend_hash_add_empty_element(EG(in_autoload), lc_name) == NULL) {
1097 if (!key) {
1098 zend_string_release_ex(lc_name, 0);
1099 }
1100 return NULL;
1101 }
1102
1103 if (ZSTR_VAL(name)[0] == '\\') {
1104 autoload_name = zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
1105 } else {
1106 autoload_name = zend_string_copy(name);
1107 }
1108
1109 zend_exception_save();
1110 ce = zend_autoload(autoload_name, lc_name);
1111 zend_exception_restore();
1112
1113 zend_string_release_ex(autoload_name, 0);
1114 zend_hash_del(EG(in_autoload), lc_name);
1115
1116 if (!key) {
1117 zend_string_release_ex(lc_name, 0);
1118 }
1119 return ce;
1120 }
1121 /* }}} */
1122
zend_lookup_class(zend_string * name)1123 ZEND_API zend_class_entry *zend_lookup_class(zend_string *name) /* {{{ */
1124 {
1125 return zend_lookup_class_ex(name, NULL, 0);
1126 }
1127 /* }}} */
1128
zend_get_called_scope(zend_execute_data * ex)1129 ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex) /* {{{ */
1130 {
1131 while (ex) {
1132 if (Z_TYPE(ex->This) == IS_OBJECT) {
1133 return Z_OBJCE(ex->This);
1134 } else if (Z_CE(ex->This)) {
1135 return Z_CE(ex->This);
1136 } else if (ex->func) {
1137 if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
1138 return NULL;
1139 }
1140 }
1141 ex = ex->prev_execute_data;
1142 }
1143 return NULL;
1144 }
1145 /* }}} */
1146
zend_get_this_object(zend_execute_data * ex)1147 ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex) /* {{{ */
1148 {
1149 while (ex) {
1150 if (Z_TYPE(ex->This) == IS_OBJECT) {
1151 return Z_OBJ(ex->This);
1152 } else if (ex->func) {
1153 if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
1154 return NULL;
1155 }
1156 }
1157 ex = ex->prev_execute_data;
1158 }
1159 return NULL;
1160 }
1161 /* }}} */
1162
zend_eval_stringl(const char * str,size_t str_len,zval * retval_ptr,const char * string_name)1163 ZEND_API zend_result zend_eval_stringl(const char *str, size_t str_len, zval *retval_ptr, const char *string_name) /* {{{ */
1164 {
1165 zend_op_array *new_op_array;
1166 uint32_t original_compiler_options;
1167 zend_result retval;
1168 zend_string *code_str;
1169
1170 if (retval_ptr) {
1171 code_str = zend_string_concat3(
1172 "return ", sizeof("return ")-1, str, str_len, ";", sizeof(";")-1);
1173 } else {
1174 code_str = zend_string_init(str, str_len, 0);
1175 }
1176
1177 /*printf("Evaluating '%s'\n", pv.value.str.val);*/
1178
1179 original_compiler_options = CG(compiler_options);
1180 CG(compiler_options) = ZEND_COMPILE_DEFAULT_FOR_EVAL;
1181 new_op_array = zend_compile_string(code_str, string_name);
1182 CG(compiler_options) = original_compiler_options;
1183
1184 if (new_op_array) {
1185 zval local_retval;
1186
1187 EG(no_extensions)=1;
1188
1189 new_op_array->scope = zend_get_executed_scope();
1190
1191 zend_try {
1192 ZVAL_UNDEF(&local_retval);
1193 zend_execute(new_op_array, &local_retval);
1194 } zend_catch {
1195 destroy_op_array(new_op_array);
1196 efree_size(new_op_array, sizeof(zend_op_array));
1197 zend_bailout();
1198 } zend_end_try();
1199
1200 if (Z_TYPE(local_retval) != IS_UNDEF) {
1201 if (retval_ptr) {
1202 ZVAL_COPY_VALUE(retval_ptr, &local_retval);
1203 } else {
1204 zval_ptr_dtor(&local_retval);
1205 }
1206 } else {
1207 if (retval_ptr) {
1208 ZVAL_NULL(retval_ptr);
1209 }
1210 }
1211
1212 EG(no_extensions)=0;
1213 destroy_op_array(new_op_array);
1214 efree_size(new_op_array, sizeof(zend_op_array));
1215 retval = SUCCESS;
1216 } else {
1217 retval = FAILURE;
1218 }
1219 zend_string_release(code_str);
1220 return retval;
1221 }
1222 /* }}} */
1223
zend_eval_string(const char * str,zval * retval_ptr,const char * string_name)1224 ZEND_API zend_result zend_eval_string(const char *str, zval *retval_ptr, const char *string_name) /* {{{ */
1225 {
1226 return zend_eval_stringl(str, strlen(str), retval_ptr, string_name);
1227 }
1228 /* }}} */
1229
zend_eval_stringl_ex(const char * str,size_t str_len,zval * retval_ptr,const char * string_name,bool handle_exceptions)1230 ZEND_API zend_result zend_eval_stringl_ex(const char *str, size_t str_len, zval *retval_ptr, const char *string_name, bool handle_exceptions) /* {{{ */
1231 {
1232 zend_result result;
1233
1234 result = zend_eval_stringl(str, str_len, retval_ptr, string_name);
1235 if (handle_exceptions && EG(exception)) {
1236 result = zend_exception_error(EG(exception), E_ERROR);
1237 }
1238 return result;
1239 }
1240 /* }}} */
1241
zend_eval_string_ex(const char * str,zval * retval_ptr,const char * string_name,bool handle_exceptions)1242 ZEND_API zend_result zend_eval_string_ex(const char *str, zval *retval_ptr, const char *string_name, bool handle_exceptions) /* {{{ */
1243 {
1244 return zend_eval_stringl_ex(str, strlen(str), retval_ptr, string_name, handle_exceptions);
1245 }
1246 /* }}} */
1247
1248 static void zend_set_timeout_ex(zend_long seconds, bool reset_signals);
1249
zend_timeout(void)1250 ZEND_API ZEND_NORETURN void ZEND_FASTCALL zend_timeout(void) /* {{{ */
1251 {
1252 #if defined(PHP_WIN32)
1253 # ifndef ZTS
1254 /* No action is needed if we're timed out because zero seconds are
1255 just ignored. Also, the hard timeout needs to be respected. If the
1256 timer is not restarted properly, it could hang in the shutdown
1257 function. */
1258 if (EG(hard_timeout) > 0) {
1259 EG(timed_out) = 0;
1260 zend_set_timeout_ex(EG(hard_timeout), 1);
1261 /* XXX Abused, introduce an additional flag if the value needs to be kept. */
1262 EG(hard_timeout) = 0;
1263 }
1264 # endif
1265 #else
1266 EG(timed_out) = 0;
1267 zend_set_timeout_ex(0, 1);
1268 #endif
1269
1270 zend_error_noreturn(E_ERROR, "Maximum execution time of " ZEND_LONG_FMT " second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
1271 }
1272 /* }}} */
1273
1274 #ifndef ZEND_WIN32
zend_timeout_handler(int dummy)1275 static void zend_timeout_handler(int dummy) /* {{{ */
1276 {
1277 #ifndef ZTS
1278 if (EG(timed_out)) {
1279 /* Die on hard timeout */
1280 const char *error_filename = NULL;
1281 uint32_t error_lineno = 0;
1282 char log_buffer[2048];
1283 int output_len = 0;
1284
1285 if (zend_is_compiling()) {
1286 error_filename = ZSTR_VAL(zend_get_compiled_filename());
1287 error_lineno = zend_get_compiled_lineno();
1288 } else if (zend_is_executing()) {
1289 error_filename = zend_get_executed_filename();
1290 if (error_filename[0] == '[') { /* [no active file] */
1291 error_filename = NULL;
1292 error_lineno = 0;
1293 } else {
1294 error_lineno = zend_get_executed_lineno();
1295 }
1296 }
1297 if (!error_filename) {
1298 error_filename = "Unknown";
1299 }
1300
1301 output_len = snprintf(log_buffer, sizeof(log_buffer), "\nFatal error: Maximum execution time of " ZEND_LONG_FMT "+" ZEND_LONG_FMT " seconds exceeded (terminated) in %s on line %d\n", EG(timeout_seconds), EG(hard_timeout), error_filename, error_lineno);
1302 if (output_len > 0) {
1303 zend_quiet_write(2, log_buffer, MIN(output_len, sizeof(log_buffer)));
1304 }
1305 _exit(124);
1306 }
1307 #endif
1308
1309 if (zend_on_timeout) {
1310 zend_on_timeout(EG(timeout_seconds));
1311 }
1312
1313 EG(timed_out) = 1;
1314 EG(vm_interrupt) = 1;
1315
1316 #ifndef ZTS
1317 if (EG(hard_timeout) > 0) {
1318 /* Set hard timeout */
1319 zend_set_timeout_ex(EG(hard_timeout), 1);
1320 }
1321 #endif
1322 }
1323 /* }}} */
1324 #endif
1325
1326 #ifdef ZEND_WIN32
tq_timer_cb(PVOID arg,BOOLEAN timed_out)1327 VOID CALLBACK tq_timer_cb(PVOID arg, BOOLEAN timed_out)
1328 {
1329 zend_executor_globals *eg;
1330
1331 /* The doc states it'll be always true, however it theoretically
1332 could be FALSE when the thread was signaled. */
1333 if (!timed_out) {
1334 return;
1335 }
1336
1337 eg = (zend_executor_globals *)arg;
1338 eg->timed_out = 1;
1339 eg->vm_interrupt = 1;
1340 }
1341 #endif
1342
1343 /* This one doesn't exists on QNX */
1344 #ifndef SIGPROF
1345 #define SIGPROF 27
1346 #endif
1347
zend_set_timeout_ex(zend_long seconds,bool reset_signals)1348 static void zend_set_timeout_ex(zend_long seconds, bool reset_signals) /* {{{ */
1349 {
1350 #ifdef ZEND_WIN32
1351 zend_executor_globals *eg;
1352
1353 if (!seconds) {
1354 return;
1355 }
1356
1357 /* Don't use ChangeTimerQueueTimer() as it will not restart an expired
1358 * timer, so we could end up with just an ignored timeout. Instead
1359 * delete and recreate. */
1360 if (NULL != tq_timer) {
1361 if (!DeleteTimerQueueTimer(NULL, tq_timer, INVALID_HANDLE_VALUE)) {
1362 tq_timer = NULL;
1363 zend_error_noreturn(E_ERROR, "Could not delete queued timer");
1364 return;
1365 }
1366 tq_timer = NULL;
1367 }
1368
1369 /* XXX passing NULL means the default timer queue provided by the system is used */
1370 eg = ZEND_MODULE_GLOBALS_BULK(executor);
1371 if (!CreateTimerQueueTimer(&tq_timer, NULL, (WAITORTIMERCALLBACK)tq_timer_cb, (VOID*)eg, seconds*1000, 0, WT_EXECUTEONLYONCE)) {
1372 tq_timer = NULL;
1373 zend_error_noreturn(E_ERROR, "Could not queue new timer");
1374 return;
1375 }
1376 #elif defined(HAVE_SETITIMER)
1377 {
1378 struct itimerval t_r; /* timeout requested */
1379 int signo;
1380
1381 if(seconds) {
1382 t_r.it_value.tv_sec = seconds;
1383 t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0;
1384
1385 # if defined(__CYGWIN__) || defined(__PASE__)
1386 setitimer(ITIMER_REAL, &t_r, NULL);
1387 }
1388 signo = SIGALRM;
1389 # else
1390 setitimer(ITIMER_PROF, &t_r, NULL);
1391 }
1392 signo = SIGPROF;
1393 # endif
1394
1395 if (reset_signals) {
1396 # ifdef ZEND_SIGNALS
1397 zend_signal(signo, zend_timeout_handler);
1398 # else
1399 sigset_t sigset;
1400 # ifdef HAVE_SIGACTION
1401 struct sigaction act;
1402
1403 act.sa_handler = zend_timeout_handler;
1404 sigemptyset(&act.sa_mask);
1405 act.sa_flags = SA_RESETHAND | SA_NODEFER;
1406 sigaction(signo, &act, NULL);
1407 # else
1408 signal(signo, zend_timeout_handler);
1409 # endif /* HAVE_SIGACTION */
1410 sigemptyset(&sigset);
1411 sigaddset(&sigset, signo);
1412 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1413 # endif /* ZEND_SIGNALS */
1414 }
1415 }
1416 #endif /* HAVE_SETITIMER */
1417 }
1418 /* }}} */
1419
zend_set_timeout(zend_long seconds,bool reset_signals)1420 void zend_set_timeout(zend_long seconds, bool reset_signals) /* {{{ */
1421 {
1422
1423 EG(timeout_seconds) = seconds;
1424 zend_set_timeout_ex(seconds, reset_signals);
1425 EG(timed_out) = 0;
1426 }
1427 /* }}} */
1428
zend_unset_timeout(void)1429 void zend_unset_timeout(void) /* {{{ */
1430 {
1431 #ifdef ZEND_WIN32
1432 if (NULL != tq_timer) {
1433 if (!DeleteTimerQueueTimer(NULL, tq_timer, INVALID_HANDLE_VALUE)) {
1434 EG(timed_out) = 0;
1435 tq_timer = NULL;
1436 zend_error_noreturn(E_ERROR, "Could not delete queued timer");
1437 return;
1438 }
1439 tq_timer = NULL;
1440 }
1441 #elif defined(HAVE_SETITIMER)
1442 if (EG(timeout_seconds)) {
1443 struct itimerval no_timeout;
1444
1445 no_timeout.it_value.tv_sec = no_timeout.it_value.tv_usec = no_timeout.it_interval.tv_sec = no_timeout.it_interval.tv_usec = 0;
1446
1447 # if defined(__CYGWIN__) || defined(__PASE__)
1448 setitimer(ITIMER_REAL, &no_timeout, NULL);
1449 # else
1450 setitimer(ITIMER_PROF, &no_timeout, NULL);
1451 # endif
1452 }
1453 #endif
1454 EG(timed_out) = 0;
1455 }
1456 /* }}} */
1457
zend_fetch_class(zend_string * class_name,int fetch_type)1458 zend_class_entry *zend_fetch_class(zend_string *class_name, int fetch_type) /* {{{ */
1459 {
1460 zend_class_entry *ce, *scope;
1461 int fetch_sub_type = fetch_type & ZEND_FETCH_CLASS_MASK;
1462
1463 check_fetch_type:
1464 switch (fetch_sub_type) {
1465 case ZEND_FETCH_CLASS_SELF:
1466 scope = zend_get_executed_scope();
1467 if (UNEXPECTED(!scope)) {
1468 zend_throw_or_error(fetch_type, NULL, "Cannot access \"self\" when no class scope is active");
1469 }
1470 return scope;
1471 case ZEND_FETCH_CLASS_PARENT:
1472 scope = zend_get_executed_scope();
1473 if (UNEXPECTED(!scope)) {
1474 zend_throw_or_error(fetch_type, NULL, "Cannot access \"parent\" when no class scope is active");
1475 return NULL;
1476 }
1477 if (UNEXPECTED(!scope->parent)) {
1478 zend_throw_or_error(fetch_type, NULL, "Cannot access \"parent\" when current class scope has no parent");
1479 }
1480 return scope->parent;
1481 case ZEND_FETCH_CLASS_STATIC:
1482 ce = zend_get_called_scope(EG(current_execute_data));
1483 if (UNEXPECTED(!ce)) {
1484 zend_throw_or_error(fetch_type, NULL, "Cannot access \"static\" when no class scope is active");
1485 return NULL;
1486 }
1487 return ce;
1488 case ZEND_FETCH_CLASS_AUTO: {
1489 fetch_sub_type = zend_get_class_fetch_type(class_name);
1490 if (UNEXPECTED(fetch_sub_type != ZEND_FETCH_CLASS_DEFAULT)) {
1491 goto check_fetch_type;
1492 }
1493 }
1494 break;
1495 }
1496
1497 if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
1498 return zend_lookup_class_ex(class_name, NULL, fetch_type);
1499 } else if ((ce = zend_lookup_class_ex(class_name, NULL, fetch_type)) == NULL) {
1500 if (!(fetch_type & ZEND_FETCH_CLASS_SILENT) && !EG(exception)) {
1501 if (fetch_sub_type == ZEND_FETCH_CLASS_INTERFACE) {
1502 zend_throw_or_error(fetch_type, NULL, "Interface \"%s\" not found", ZSTR_VAL(class_name));
1503 } else if (fetch_sub_type == ZEND_FETCH_CLASS_TRAIT) {
1504 zend_throw_or_error(fetch_type, NULL, "Trait \"%s\" not found", ZSTR_VAL(class_name));
1505 } else {
1506 zend_throw_or_error(fetch_type, NULL, "Class \"%s\" not found", ZSTR_VAL(class_name));
1507 }
1508 }
1509 return NULL;
1510 }
1511 return ce;
1512 }
1513 /* }}} */
1514
zend_fetch_class_by_name(zend_string * class_name,zend_string * key,int fetch_type)1515 zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, zend_string *key, int fetch_type) /* {{{ */
1516 {
1517 zend_class_entry *ce;
1518
1519 if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
1520 return zend_lookup_class_ex(class_name, key, fetch_type);
1521 } else if ((ce = zend_lookup_class_ex(class_name, key, fetch_type)) == NULL) {
1522 if (fetch_type & ZEND_FETCH_CLASS_SILENT) {
1523 return NULL;
1524 }
1525 if (EG(exception)) {
1526 if (!(fetch_type & ZEND_FETCH_CLASS_EXCEPTION)) {
1527 zend_string *exception_str;
1528 zval exception_zv;
1529 ZVAL_OBJ(&exception_zv, EG(exception));
1530 Z_ADDREF(exception_zv);
1531 zend_clear_exception();
1532 exception_str = zval_get_string(&exception_zv);
1533 zend_error_noreturn(E_ERROR,
1534 "During class fetch: Uncaught %s", ZSTR_VAL(exception_str));
1535 }
1536 return NULL;
1537 }
1538 if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_INTERFACE) {
1539 zend_throw_or_error(fetch_type, NULL, "Interface \"%s\" not found", ZSTR_VAL(class_name));
1540 } else if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_TRAIT) {
1541 zend_throw_or_error(fetch_type, NULL, "Trait \"%s\" not found", ZSTR_VAL(class_name));
1542 } else {
1543 zend_throw_or_error(fetch_type, NULL, "Class \"%s\" not found", ZSTR_VAL(class_name));
1544 }
1545 return NULL;
1546 }
1547 return ce;
1548 }
1549 /* }}} */
1550
zend_delete_global_variable(zend_string * name)1551 ZEND_API zend_result zend_delete_global_variable(zend_string *name) /* {{{ */
1552 {
1553 return zend_hash_del_ind(&EG(symbol_table), name);
1554 }
1555 /* }}} */
1556
zend_rebuild_symbol_table(void)1557 ZEND_API zend_array *zend_rebuild_symbol_table(void) /* {{{ */
1558 {
1559 zend_execute_data *ex;
1560 zend_array *symbol_table;
1561
1562 /* Search for last called user function */
1563 ex = EG(current_execute_data);
1564 while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->common.type))) {
1565 ex = ex->prev_execute_data;
1566 }
1567 if (!ex) {
1568 return NULL;
1569 }
1570 if (ZEND_CALL_INFO(ex) & ZEND_CALL_HAS_SYMBOL_TABLE) {
1571 return ex->symbol_table;
1572 }
1573
1574 ZEND_ADD_CALL_FLAG(ex, ZEND_CALL_HAS_SYMBOL_TABLE);
1575 if (EG(symtable_cache_ptr) > EG(symtable_cache)) {
1576 symbol_table = ex->symbol_table = *(--EG(symtable_cache_ptr));
1577 if (!ex->func->op_array.last_var) {
1578 return symbol_table;
1579 }
1580 zend_hash_extend(symbol_table, ex->func->op_array.last_var, 0);
1581 } else {
1582 symbol_table = ex->symbol_table = zend_new_array(ex->func->op_array.last_var);
1583 if (!ex->func->op_array.last_var) {
1584 return symbol_table;
1585 }
1586 zend_hash_real_init_mixed(symbol_table);
1587 /*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/
1588 }
1589 if (EXPECTED(ex->func->op_array.last_var)) {
1590 zend_string **str = ex->func->op_array.vars;
1591 zend_string **end = str + ex->func->op_array.last_var;
1592 zval *var = ZEND_CALL_VAR_NUM(ex, 0);
1593
1594 do {
1595 _zend_hash_append_ind(symbol_table, *str, var);
1596 str++;
1597 var++;
1598 } while (str != end);
1599 }
1600 return symbol_table;
1601 }
1602 /* }}} */
1603
zend_attach_symbol_table(zend_execute_data * execute_data)1604 ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */
1605 {
1606 zend_op_array *op_array = &execute_data->func->op_array;
1607 HashTable *ht = execute_data->symbol_table;
1608
1609 /* copy real values from symbol table into CV slots and create
1610 INDIRECT references to CV in symbol table */
1611 if (EXPECTED(op_array->last_var)) {
1612 zend_string **str = op_array->vars;
1613 zend_string **end = str + op_array->last_var;
1614 zval *var = EX_VAR_NUM(0);
1615
1616 do {
1617 zval *zv = zend_hash_find_ex(ht, *str, 1);
1618
1619 if (zv) {
1620 if (Z_TYPE_P(zv) == IS_INDIRECT) {
1621 zval *val = Z_INDIRECT_P(zv);
1622
1623 ZVAL_COPY_VALUE(var, val);
1624 } else {
1625 ZVAL_COPY_VALUE(var, zv);
1626 }
1627 } else {
1628 ZVAL_UNDEF(var);
1629 zv = zend_hash_add_new(ht, *str, var);
1630 }
1631 ZVAL_INDIRECT(zv, var);
1632 str++;
1633 var++;
1634 } while (str != end);
1635 }
1636 }
1637 /* }}} */
1638
zend_detach_symbol_table(zend_execute_data * execute_data)1639 ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */
1640 {
1641 zend_op_array *op_array = &execute_data->func->op_array;
1642 HashTable *ht = execute_data->symbol_table;
1643
1644 /* copy real values from CV slots into symbol table */
1645 if (EXPECTED(op_array->last_var)) {
1646 zend_string **str = op_array->vars;
1647 zend_string **end = str + op_array->last_var;
1648 zval *var = EX_VAR_NUM(0);
1649
1650 do {
1651 if (Z_TYPE_P(var) == IS_UNDEF) {
1652 zend_hash_del(ht, *str);
1653 } else {
1654 zend_hash_update(ht, *str, var);
1655 ZVAL_UNDEF(var);
1656 }
1657 str++;
1658 var++;
1659 } while (str != end);
1660 }
1661 }
1662 /* }}} */
1663
zend_set_local_var(zend_string * name,zval * value,bool force)1664 ZEND_API zend_result zend_set_local_var(zend_string *name, zval *value, bool force) /* {{{ */
1665 {
1666 zend_execute_data *execute_data = EG(current_execute_data);
1667
1668 while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) {
1669 execute_data = execute_data->prev_execute_data;
1670 }
1671
1672 if (execute_data) {
1673 if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) {
1674 zend_ulong h = zend_string_hash_val(name);
1675 zend_op_array *op_array = &execute_data->func->op_array;
1676
1677 if (EXPECTED(op_array->last_var)) {
1678 zend_string **str = op_array->vars;
1679 zend_string **end = str + op_array->last_var;
1680
1681 do {
1682 if (ZSTR_H(*str) == h &&
1683 zend_string_equal_content(*str, name)) {
1684 zval *var = EX_VAR_NUM(str - op_array->vars);
1685 ZVAL_COPY_VALUE(var, value);
1686 return SUCCESS;
1687 }
1688 str++;
1689 } while (str != end);
1690 }
1691 if (force) {
1692 zend_array *symbol_table = zend_rebuild_symbol_table();
1693 if (symbol_table) {
1694 zend_hash_update(symbol_table, name, value);
1695 return SUCCESS;
1696 }
1697 }
1698 } else {
1699 zend_hash_update_ind(execute_data->symbol_table, name, value);
1700 return SUCCESS;
1701 }
1702 }
1703 return FAILURE;
1704 }
1705 /* }}} */
1706
zend_set_local_var_str(const char * name,size_t len,zval * value,bool force)1707 ZEND_API zend_result zend_set_local_var_str(const char *name, size_t len, zval *value, bool force) /* {{{ */
1708 {
1709 zend_execute_data *execute_data = EG(current_execute_data);
1710
1711 while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) {
1712 execute_data = execute_data->prev_execute_data;
1713 }
1714
1715 if (execute_data) {
1716 if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) {
1717 zend_ulong h = zend_hash_func(name, len);
1718 zend_op_array *op_array = &execute_data->func->op_array;
1719 if (EXPECTED(op_array->last_var)) {
1720 zend_string **str = op_array->vars;
1721 zend_string **end = str + op_array->last_var;
1722
1723 do {
1724 if (ZSTR_H(*str) == h &&
1725 ZSTR_LEN(*str) == len &&
1726 memcmp(ZSTR_VAL(*str), name, len) == 0) {
1727 zval *var = EX_VAR_NUM(str - op_array->vars);
1728 zval_ptr_dtor(var);
1729 ZVAL_COPY_VALUE(var, value);
1730 return SUCCESS;
1731 }
1732 str++;
1733 } while (str != end);
1734 }
1735 if (force) {
1736 zend_array *symbol_table = zend_rebuild_symbol_table();
1737 if (symbol_table) {
1738 zend_hash_str_update(symbol_table, name, len, value);
1739 return SUCCESS;
1740 }
1741 }
1742 } else {
1743 zend_hash_str_update_ind(execute_data->symbol_table, name, len, value);
1744 return SUCCESS;
1745 }
1746 }
1747 return FAILURE;
1748 }
1749 /* }}} */
1750