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