Coverage Report

Created: 2025-12-14 06:05

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