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