Coverage Report

Created: 2026-07-25 06:39

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