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