Coverage Report

Created: 2025-12-14 06:05

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