Coverage Report

Created: 2026-01-18 06:49

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