Coverage Report

Created: 2026-06-02 06:40

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