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