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