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