Coverage Report

Created: 2026-06-02 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/Zend/zend_execute_API.c
Line
Count
Source
1
/*
2
   +----------------------------------------------------------------------+
3
   | Zend Engine                                                          |
4
   +----------------------------------------------------------------------+
5
   | Copyright © Zend Technologies Ltd., a subsidiary company of          |
6
   |     Perforce Software, Inc., and Contributors.                       |
7
   +----------------------------------------------------------------------+
8
   | This source file is subject to the Modified BSD License that is      |
9
   | bundled with this package in the file LICENSE, and is available      |
10
   | through the World Wide Web at <https://www.php.net/license/>.        |
11
   |                                                                      |
12
   | SPDX-License-Identifier: BSD-3-Clause                                |
13
   +----------------------------------------------------------------------+
14
   | Authors: Andi Gutmans <andi@php.net>                                 |
15
   |          Zeev Suraski <zeev@php.net>                                 |
16
   |          Dmitry Stogov <dmitry@php.net>                              |
17
   +----------------------------------------------------------------------+
18
*/
19
20
#include <stdio.h>
21
#include <signal.h>
22
23
#include "zend.h"
24
#include "zend_compile.h"
25
#include "zend_execute.h"
26
#include "zend_API.h"
27
#include "zend_stack.h"
28
#include "zend_constants.h"
29
#include "zend_extensions.h"
30
#include "zend_exceptions.h"
31
#include "zend_closures.h"
32
#include "zend_generators.h"
33
#include "zend_vm.h"
34
#include "zend_float.h"
35
#include "zend_fibers.h"
36
#include "zend_weakrefs.h"
37
#include "zend_inheritance.h"
38
#include "zend_observer.h"
39
#include "zend_call_stack.h"
40
#include "zend_frameless_function.h"
41
#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
44.4k
{
92
44.4k
  if (extension->activate) {
93
44.4k
    extension->activate();
94
44.4k
  }
95
44.4k
}
96
/* }}} */
97
98
static void zend_extension_deactivator(const zend_extension *extension) /* {{{ */
99
44.4k
{
100
44.4k
  if (extension->deactivate) {
101
44.4k
    extension->deactivate();
102
44.4k
  }
103
44.4k
}
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
44.4k
{
129
44.4k
  zend_init_fpu();
130
131
44.4k
  ZVAL_NULL(&EG(uninitialized_zval));
132
44.4k
  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
44.4k
  ZVAL_UNDEF(&EG(last_fatal_error_backtrace));
139
140
44.4k
  EG(symtable_cache_ptr) = EG(symtable_cache);
141
44.4k
  EG(symtable_cache_limit) = EG(symtable_cache) + SYMTABLE_CACHE_SIZE;
142
44.4k
  EG(no_extensions) = 0;
143
144
44.4k
  EG(function_table) = CG(function_table);
145
44.4k
  EG(class_table) = CG(class_table);
146
147
44.4k
  EG(error_handling) = EH_NORMAL;
148
44.4k
  EG(flags) = EG_FLAGS_INITIAL;
149
150
44.4k
  zend_vm_stack_init();
151
152
44.4k
  zend_hash_init(&EG(symbol_table), 64, NULL, ZVAL_PTR_DTOR, 0);
153
154
44.4k
  zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator);
155
156
44.4k
  zend_hash_init(&EG(included_files), 8, NULL, NULL, 0);
157
44.4k
  zend_hash_init(&EG(autoload_current_classnames), 8, NULL, NULL, 0);
158
159
44.4k
  EG(ticks_count) = 0;
160
161
44.4k
  ZVAL_UNDEF(&EG(user_error_handler));
162
44.4k
  ZVAL_UNDEF(&EG(user_exception_handler));
163
164
44.4k
  EG(current_execute_data) = NULL;
165
166
44.4k
  zend_stack_init(&EG(user_error_handlers_error_reporting), sizeof(int));
167
44.4k
  zend_stack_init(&EG(user_error_handlers), sizeof(zval));
168
44.4k
  zend_stack_init(&EG(user_exception_handlers), sizeof(zval));
169
170
44.4k
  zend_objects_store_init(&EG(objects_store), 1024);
171
44.4k
  zend_lazy_objects_init(&EG(lazy_objects_store));
172
173
44.4k
  EG(full_tables_cleanup) = 0;
174
44.4k
  ZEND_ATOMIC_BOOL_INIT(&EG(vm_interrupt), false);
175
44.4k
  ZEND_ATOMIC_BOOL_INIT(&EG(timed_out), false);
176
177
44.4k
  EG(exception) = NULL;
178
179
44.4k
  EG(fake_scope) = NULL;
180
44.4k
  EG(trampoline).common.function_name = NULL;
181
182
44.4k
  EG(ht_iterators_count) = sizeof(EG(ht_iterators_slots)) / sizeof(HashTableIterator);
183
44.4k
  EG(ht_iterators_used) = 0;
184
44.4k
  EG(ht_iterators) = EG(ht_iterators_slots);
185
44.4k
  memset(EG(ht_iterators), 0, sizeof(EG(ht_iterators_slots)));
186
187
44.4k
  EG(persistent_constants_count) = EG(zend_constants)->nNumUsed;
188
44.4k
  EG(persistent_functions_count) = EG(function_table)->nNumUsed;
189
44.4k
  EG(persistent_classes_count)   = EG(class_table)->nNumUsed;
190
191
44.4k
  EG(get_gc_buffer).start = EG(get_gc_buffer).end = EG(get_gc_buffer).cur = NULL;
192
193
44.4k
  EG(record_errors) = false;
194
44.4k
  memset(&EG(errors), 0, sizeof(EG(errors)));
195
196
44.4k
  EG(filename_override) = NULL;
197
44.4k
  EG(lineno_override) = -1;
198
199
44.4k
  zend_max_execution_timer_init();
200
44.4k
  zend_fiber_init();
201
44.4k
  zend_weakrefs_init();
202
203
44.4k
  zend_hash_init(&EG(callable_convert_cache), 8, NULL, ZVAL_PTR_DTOR, 0);
204
205
44.4k
  EG(active) = 1;
206
44.4k
}
207
/* }}} */
208
209
static int zval_call_destructor(zval *zv) /* {{{ */
210
463k
{
211
463k
  if (Z_TYPE_P(zv) == IS_INDIRECT) {
212
106k
    zv = Z_INDIRECT_P(zv);
213
106k
  }
214
463k
  if (Z_TYPE_P(zv) == IS_OBJECT && Z_REFCOUNT_P(zv) == 1) {
215
20.0k
    return ZEND_HASH_APPLY_REMOVE;
216
443k
  } else {
217
443k
    return ZEND_HASH_APPLY_KEEP;
218
443k
  }
219
463k
}
220
/* }}} */
221
222
static void zend_unclean_zval_ptr_dtor(zval *zv) /* {{{ */
223
93.3k
{
224
93.3k
  if (Z_TYPE_P(zv) == IS_INDIRECT) {
225
59.0k
    zv = Z_INDIRECT_P(zv);
226
59.0k
  }
227
93.3k
  i_zval_ptr_dtor(zv);
228
93.3k
}
229
/* }}} */
230
231
static ZEND_COLD void zend_throw_or_error(uint32_t fetch_type, zend_class_entry *exception_ce, const char *format, ...) /* {{{ */
232
592
{
233
592
  va_list va;
234
592
  char *message = NULL;
235
236
592
  va_start(va, format);
237
592
  zend_vspprintf(&message, 0, format, va);
238
239
592
  if (fetch_type & ZEND_FETCH_CLASS_EXCEPTION) {
240
592
    zend_throw_error(exception_ce, "%s", message);
241
592
  } else {
242
0
    zend_error_noreturn(E_ERROR, "%s", message);
243
0
  }
244
245
592
  efree(message);
246
592
  va_end(va);
247
592
}
248
/* }}} */
249
250
void shutdown_destructors(void) /* {{{ */
251
44.4k
{
252
44.4k
  if (CG(unclean_shutdown)) {
253
8.32k
    EG(symbol_table).pDestructor = zend_unclean_zval_ptr_dtor;
254
8.32k
  }
255
44.4k
  zend_try {
256
44.4k
    uint32_t symbols;
257
58.7k
    do {
258
58.7k
      symbols = zend_hash_num_elements(&EG(symbol_table));
259
58.7k
      zend_hash_reverse_apply(&EG(symbol_table), (apply_func_t) zval_call_destructor);
260
58.7k
    } while (symbols != zend_hash_num_elements(&EG(symbol_table)));
261
44.4k
    zend_objects_store_call_destructors(&EG(objects_store));
262
44.4k
  } zend_catch {
263
    /* if we couldn't destruct cleanly, mark all objects as destructed anyway */
264
236
    zend_objects_store_mark_destructed(&EG(objects_store));
265
44.4k
  } zend_end_try();
266
44.4k
}
267
/* }}} */
268
269
/* Free values held by the executor. */
270
ZEND_API void zend_shutdown_executor_values(bool fast_shutdown)
271
44.4k
{
272
44.4k
  EG(flags) |= EG_FLAGS_IN_RESOURCE_SHUTDOWN;
273
44.4k
  zend_close_rsrc_list(&EG(regular_list));
274
275
  /* No PHP callback functions should be called after this point. */
276
44.4k
  EG(active) = 0;
277
278
44.4k
  if (!fast_shutdown) {
279
44.4k
    zval *zv;
280
281
44.4k
    zend_hash_graceful_reverse_destroy(&EG(symbol_table));
282
283
    /* Constants may contain objects, destroy them before the object store. */
284
44.4k
    if (EG(full_tables_cleanup)) {
285
0
      zend_hash_reverse_apply(EG(zend_constants), clean_non_persistent_constant_full);
286
44.4k
    } else {
287
44.4k
      zend_string *key;
288
180k
      ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(EG(zend_constants), key, zv) {
289
180k
        zend_constant *c = Z_PTR_P(zv);
290
180k
        if (_idx == EG(persistent_constants_count)) {
291
44.4k
          break;
292
44.4k
        }
293
1.46k
        zval_ptr_dtor_nogc(&c->value);
294
1.46k
        if (c->name) {
295
1.46k
          zend_string_release_ex(c->name, 0);
296
1.46k
        }
297
1.46k
        if (c->filename) {
298
1.40k
          zend_string_release_ex(c->filename, 0);
299
1.40k
        }
300
1.46k
        if (c->attributes) {
301
138
          zend_hash_release(c->attributes);
302
138
        }
303
1.46k
        efree(c);
304
1.46k
        zend_string_release_ex(key, 0);
305
1.46k
      } ZEND_HASH_MAP_FOREACH_END_DEL();
306
44.4k
    }
307
308
44.4k
    zval_ptr_dtor(&EG(last_fatal_error_backtrace));
309
44.4k
    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
199k
    ZEND_HASH_MAP_REVERSE_FOREACH_VAL(EG(function_table), zv) {
314
199k
      zend_op_array *op_array = Z_PTR_P(zv);
315
199k
      if (op_array->type == ZEND_INTERNAL_FUNCTION) {
316
44.4k
        break;
317
44.4k
      }
318
10.7k
      if (ZEND_MAP_PTR(op_array->static_variables_ptr)) {
319
195
        HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
320
195
        if (ht) {
321
161
          zend_array_destroy(ht);
322
161
          ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
323
161
        }
324
195
      }
325
10.7k
    } ZEND_HASH_FOREACH_END();
326
15.5M
    ZEND_HASH_MAP_REVERSE_FOREACH_VAL(EG(class_table), zv) {
327
15.5M
      zend_class_entry *ce = Z_PTR_P(zv);
328
329
15.5M
      if (ce->default_static_members_count) {
330
1.24k
        zend_cleanup_internal_class_data(ce);
331
1.24k
      }
332
333
15.5M
      if (ZEND_MAP_PTR(ce->mutable_data)) {
334
533k
        if (ZEND_MAP_PTR_GET_IMM(ce->mutable_data)) {
335
447
          zend_cleanup_mutable_class_data(ce);
336
447
        }
337
7.21M
      } 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
3.61k
        zend_class_constant *c;
340
11.0k
        ZEND_HASH_MAP_FOREACH_PTR(&ce->constants_table, c) {
341
11.0k
          if (c->ce == ce) {
342
1.52k
            zval_ptr_dtor_nogc(&c->value);
343
1.52k
            ZVAL_UNDEF(&c->value);
344
1.52k
          }
345
11.0k
        } ZEND_HASH_FOREACH_END();
346
347
        /* properties may contain objects as well */
348
3.61k
        if (ce->default_properties_table) {
349
1.28k
          zval *p = ce->default_properties_table;
350
1.28k
          zval *end = p + ce->default_properties_count;
351
352
3.14k
          while (p != end) {
353
1.86k
            i_zval_ptr_dtor(p);
354
1.86k
            ZVAL_UNDEF(p);
355
1.86k
            p++;
356
1.86k
          }
357
1.28k
        }
358
3.61k
      }
359
360
15.5M
      if (ce->type == ZEND_USER_CLASS && ce->backed_enum_table) {
361
126
        ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_IMMUTABLE));
362
126
        zend_hash_release(ce->backed_enum_table);
363
126
        ce->backed_enum_table = NULL;
364
126
      }
365
366
7.74M
      if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
367
171
        zend_op_array *op_array;
368
852
        ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) {
369
852
          if (op_array->type == ZEND_USER_FUNCTION) {
370
255
            if (ZEND_MAP_PTR(op_array->static_variables_ptr)) {
371
168
              HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
372
168
              if (ht) {
373
96
                zend_array_destroy(ht);
374
96
                ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
375
96
              }
376
168
            }
377
255
          }
378
852
        } ZEND_HASH_FOREACH_END();
379
380
171
        if (ce->num_hooked_props) {
381
12
          zend_property_info *prop_info;
382
48
          ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop_info) {
383
48
            if (prop_info->ce == ce) {
384
12
              if (prop_info->hooks) {
385
36
                for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
386
24
                  if (prop_info->hooks[i]) {
387
12
                    ZEND_ASSERT(ZEND_USER_CODE(prop_info->hooks[i]->type));
388
12
                    op_array = &prop_info->hooks[i]->op_array;
389
12
                    if (ZEND_MAP_PTR(op_array->static_variables_ptr)) {
390
12
                      HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
391
12
                      if (ht) {
392
12
                        zend_array_destroy(ht);
393
12
                        ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
394
12
                      }
395
12
                    }
396
12
                  }
397
24
                }
398
12
              }
399
12
            }
400
48
          } ZEND_HASH_FOREACH_END();
401
12
        }
402
171
      }
403
7.74M
    } ZEND_HASH_FOREACH_END();
404
405
    /* Also release error and exception handlers, which may hold objects. */
406
44.4k
    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
44.4k
    if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
412
39
      zval_ptr_dtor(&EG(user_exception_handler));
413
39
      ZVAL_UNDEF(&EG(user_exception_handler));
414
39
    }
415
416
44.4k
    zend_stack_clean(&EG(user_error_handlers_error_reporting), NULL, 1);
417
44.4k
    zend_stack_clean(&EG(user_error_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);
418
44.4k
    zend_stack_clean(&EG(user_exception_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);
419
420
44.4k
    zend_hash_clean(&EG(callable_convert_cache));
421
422
44.4k
#if ZEND_DEBUG
423
44.4k
    if (!CG(unclean_shutdown)) {
424
36.0k
      gc_collect_cycles();
425
36.0k
    }
426
44.4k
#endif
427
44.4k
  } else {
428
0
    zend_hash_discard(EG(zend_constants), EG(persistent_constants_count));
429
0
  }
430
431
44.4k
  zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown);
432
44.4k
}
433
434
void shutdown_executor(void) /* {{{ */
435
44.4k
{
436
44.4k
#if ZEND_DEBUG
437
44.4k
  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
44.4k
  zend_try {
449
44.4k
    zend_stream_shutdown();
450
44.4k
  } zend_end_try();
451
452
44.4k
  zend_shutdown_executor_values(fast_shutdown);
453
454
44.4k
  zend_weakrefs_shutdown();
455
44.4k
  zend_max_execution_timer_shutdown();
456
44.4k
  zend_fiber_shutdown();
457
458
44.4k
  zend_try {
459
44.4k
    zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator);
460
44.4k
  } zend_end_try();
461
462
44.4k
  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
44.4k
  } else {
471
44.4k
    zend_vm_stack_destroy();
472
473
44.4k
    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
44.4k
    } else {
477
44.4k
      zend_string *key;
478
44.4k
      zval *zv;
479
199k
      ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(EG(function_table), key, zv) {
480
199k
        zend_function *func = Z_PTR_P(zv);
481
199k
        if (_idx == EG(persistent_functions_count)) {
482
44.4k
          break;
483
44.4k
        }
484
10.7k
        destroy_op_array(&func->op_array);
485
10.7k
        zend_string_release_ex(key, 0);
486
10.7k
      } ZEND_HASH_MAP_FOREACH_END_DEL();
487
488
220k
      ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) {
489
220k
        if (_idx == EG(persistent_classes_count)) {
490
44.4k
          break;
491
44.4k
        }
492
21.3k
        destroy_zend_class(zv);
493
21.3k
        zend_string_release_ex(key, 0);
494
21.3k
      } ZEND_HASH_MAP_FOREACH_END_DEL();
495
44.4k
    }
496
497
45.2k
    while (EG(symtable_cache_ptr) > EG(symtable_cache)) {
498
785
      EG(symtable_cache_ptr)--;
499
785
      zend_hash_destroy(*EG(symtable_cache_ptr));
500
785
      FREE_HASHTABLE(*EG(symtable_cache_ptr));
501
785
    }
502
503
44.4k
    zend_hash_destroy(&EG(included_files));
504
44.4k
    zend_hash_destroy(&EG(autoload_current_classnames));
505
506
44.4k
    zend_stack_destroy(&EG(user_error_handlers_error_reporting));
507
44.4k
    zend_stack_destroy(&EG(user_error_handlers));
508
44.4k
    zend_stack_destroy(&EG(user_exception_handlers));
509
44.4k
    zend_lazy_objects_destroy(&EG(lazy_objects_store));
510
44.4k
    zend_objects_store_destroy(&EG(objects_store));
511
512
44.4k
    if (EG(ht_iterators) != EG(ht_iterators_slots)) {
513
6
      efree(EG(ht_iterators));
514
6
    }
515
516
44.4k
    zend_hash_destroy(&EG(callable_convert_cache));
517
44.4k
  }
518
519
44.4k
#if ZEND_DEBUG
520
44.4k
  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
44.4k
#endif
524
525
  /* Check whether anyone is hogging the trampoline. */
526
44.4k
  ZEND_ASSERT(EG(trampoline).common.function_name == NULL || CG(unclean_shutdown));
527
528
44.4k
  EG(ht_iterators_used) = 0;
529
530
44.4k
  zend_shutdown_fpu();
531
44.4k
}
532
/* }}} */
533
534
/* return class name and "::" or "". */
535
ZEND_API const char *get_active_class_name(const char **space) /* {{{ */
536
15
{
537
15
  const zend_function *func;
538
539
15
  if (!zend_is_executing()) {
540
0
    if (space) {
541
0
      *space = "";
542
0
    }
543
0
    return "";
544
0
  }
545
546
15
  func = zend_active_function();
547
548
15
  switch (func->type) {
549
0
    case ZEND_USER_FUNCTION:
550
15
    case ZEND_INTERNAL_FUNCTION:
551
15
    {
552
15
      const zend_class_entry *ce = func->common.scope;
553
554
15
      if (space) {
555
15
        *space = ce ? "::" : "";
556
15
      }
557
15
      return ce ? ZSTR_VAL(ce->name) : "";
558
0
    }
559
0
    default:
560
0
      if (space) {
561
0
        *space = "";
562
0
      }
563
0
      return "";
564
15
  }
565
15
}
566
/* }}} */
567
568
ZEND_API const char *get_active_function_name(void) /* {{{ */
569
45
{
570
45
  const zend_function *func;
571
572
45
  if (!zend_is_executing()) {
573
0
    return NULL;
574
0
  }
575
576
45
  func = zend_active_function();
577
578
45
  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
45
    case ZEND_INTERNAL_FUNCTION:
590
45
      return ZSTR_VAL(func->common.function_name);
591
0
      break;
592
0
    default:
593
0
      return NULL;
594
45
  }
595
45
}
596
/* }}} */
597
598
ZEND_API const zend_function *zend_active_function_ex(const zend_execute_data *execute_data)
599
796
{
600
796
  const zend_function *func = EX(func);
601
602
  /* Resolve function if op is a frameless call. */
603
796
  if (ZEND_USER_CODE(func->type)) {
604
796
    const zend_op *op = EX(opline);
605
796
    if (ZEND_OP_IS_FRAMELESS_ICALL(op->opcode)) {
606
0
      func = ZEND_FLF_FUNC(op);
607
0
    }
608
796
  }
609
610
796
  return func;
611
796
}
612
613
ZEND_API zend_string *get_active_function_or_method_name(void) /* {{{ */
614
3.11k
{
615
3.11k
  ZEND_ASSERT(zend_is_executing());
616
617
3.11k
  return get_function_or_method_name(zend_active_function());
618
3.11k
}
619
/* }}} */
620
621
ZEND_API zend_string *get_function_or_method_name(const zend_function *func) /* {{{ */
622
3.25k
{
623
3.25k
  if (func->common.scope && func->common.function_name) {
624
1.75k
    return zend_create_member_string(func->common.scope->name, func->common.function_name);
625
1.75k
  }
626
627
1.49k
  return func->common.function_name ? zend_string_copy(func->common.function_name) : ZSTR_INIT_LITERAL("main", 0);
628
3.25k
}
629
/* }}} */
630
631
ZEND_API const char *get_active_function_arg_name(uint32_t arg_num) /* {{{ */
632
2.84k
{
633
2.84k
  if (!zend_is_executing()) {
634
0
    return NULL;
635
0
  }
636
637
2.84k
  const zend_function *func = zend_active_function();
638
639
2.84k
  return get_function_arg_name(func, arg_num);
640
2.84k
}
641
/* }}} */
642
643
ZEND_API const char *get_function_arg_name(const zend_function *func, uint32_t arg_num) /* {{{ */
644
3.07k
{
645
3.07k
  if (!func || arg_num == 0 || func->common.num_args < arg_num) {
646
24
    return NULL;
647
24
  }
648
649
3.04k
  return ZSTR_VAL(func->common.arg_info[arg_num - 1].name);
650
3.07k
}
651
/* }}} */
652
653
ZEND_API const char *zend_get_executed_filename(void) /* {{{ */
654
207k
{
655
207k
  const zend_string *filename = zend_get_executed_filename_ex();
656
207k
  return filename != NULL ? ZSTR_VAL(filename) : "[no active file]";
657
207k
}
658
/* }}} */
659
660
ZEND_API zend_string *zend_get_executed_filename_ex(void) /* {{{ */
661
919k
{
662
919k
  zend_string *filename_override = EG(filename_override);
663
919k
  if (filename_override != NULL) {
664
117
    return filename_override;
665
117
  }
666
667
918k
  const zend_execute_data *ex = EG(current_execute_data);
668
669
1.09M
  while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
670
175k
    ex = ex->prev_execute_data;
671
175k
  }
672
918k
  if (ex) {
673
905k
    return ex->func->op_array.filename;
674
905k
  } else {
675
12.9k
    return NULL;
676
12.9k
  }
677
918k
}
678
/* }}} */
679
680
ZEND_API uint32_t zend_get_executed_lineno(void) /* {{{ */
681
890k
{
682
890k
  zend_long lineno_override = EG(lineno_override);
683
890k
  if (lineno_override != -1) {
684
117
    return lineno_override;
685
117
  }
686
687
890k
  const zend_execute_data *ex = EG(current_execute_data);
688
689
1.06M
  while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
690
175k
    ex = ex->prev_execute_data;
691
175k
  }
692
890k
  if (ex) {
693
877k
    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
877k
    if (EG(exception) && ex->opline->opcode == ZEND_HANDLE_EXCEPTION &&
698
39
        ex->opline->lineno == 0 && EG(opline_before_exception)) {
699
39
      return EG(opline_before_exception)->lineno;
700
39
    }
701
877k
    return ex->opline->lineno;
702
877k
  } else {
703
12.9k
    return 0;
704
12.9k
  }
705
890k
}
706
/* }}} */
707
708
ZEND_API zend_class_entry *zend_get_executed_scope(void) /* {{{ */
709
7.29k
{
710
7.29k
  const zend_execute_data *ex = EG(current_execute_data);
711
712
8.02k
  while (1) {
713
8.02k
    if (!ex) {
714
10
      return NULL;
715
8.01k
    } else if (ex->func && (ZEND_USER_CODE(ex->func->type) || ex->func->common.scope)) {
716
7.28k
      return ex->func->common.scope;
717
7.28k
    }
718
729
    ex = ex->prev_execute_data;
719
729
  }
720
7.29k
}
721
/* }}} */
722
723
ZEND_API bool zend_is_executing(void) /* {{{ */
724
770k
{
725
770k
  return EG(current_execute_data) != 0;
726
770k
}
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
2.90k
{
731
2.90k
  if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
732
2.90k
    zend_ast *ast = Z_ASTVAL_P(p);
733
734
2.90k
    if (ast->kind == ZEND_AST_CONSTANT) {
735
389
      zend_string *name = zend_ast_get_constant_name(ast);
736
389
      const zval *zv = zend_get_constant_ex(name, scope, ast->attr);
737
389
      if (UNEXPECTED(zv == NULL)) {
738
54
        return FAILURE;
739
54
      }
740
741
335
      zval_ptr_dtor_nogc(p);
742
335
      ZVAL_COPY_OR_DUP(p, zv);
743
2.51k
    } else {
744
2.51k
      zval tmp;
745
2.51k
      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
2.51k
      zend_ast_ref *ast_ref = Z_AST_P(p);
751
2.51k
      bool ast_is_refcounted = !(GC_FLAGS(ast_ref) & GC_IMMUTABLE);
752
2.51k
      if (ast_is_refcounted) {
753
105
        GC_ADDREF(ast_ref);
754
105
      }
755
2.51k
      zend_result result = zend_ast_evaluate_ex(&tmp, ast, scope, &short_circuited, ctx) != SUCCESS;
756
2.51k
      if (ast_is_refcounted && !GC_DELREF(ast_ref)) {
757
6
        rc_dtor_func((zend_refcounted *)ast_ref);
758
6
      }
759
2.51k
      if (UNEXPECTED(result != SUCCESS)) {
760
309
        return FAILURE;
761
309
      }
762
2.20k
      zval_ptr_dtor_nogc(p);
763
2.20k
      ZVAL_COPY_VALUE(p, &tmp);
764
2.20k
    }
765
2.90k
  }
766
2.53k
  return SUCCESS;
767
2.90k
}
768
/* }}} */
769
770
ZEND_API zend_result ZEND_FASTCALL zval_update_constant_ex(zval *p, zend_class_entry *scope)
771
2.53k
{
772
2.53k
  zend_ast_evaluate_ctx ctx = {0};
773
2.53k
  return zval_update_constant_with_ctx(p, scope, &ctx);
774
2.53k
}
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
36
{
784
36
  zend_fcall_info fci;
785
786
36
  fci.size = sizeof(fci);
787
36
  if (object) {
788
24
    ZEND_ASSERT(Z_TYPE_P(object) == IS_OBJECT);
789
24
    fci.object = Z_OBJ_P(object);
790
24
  } else {
791
12
    fci.object = NULL;
792
12
  }
793
36
  ZVAL_COPY_VALUE(&fci.function_name, function_name);
794
36
  fci.retval = retval_ptr;
795
36
  fci.param_count = param_count;
796
36
  fci.params = params;
797
36
  fci.named_params = named_params;
798
36
  fci.consumed_args = 0;
799
800
36
  return zend_call_function(&fci, NULL);
801
36
}
802
/* }}} */
803
804
zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /* {{{ */
805
72.4k
{
806
72.4k
  zend_execute_data *call;
807
72.4k
  zend_fcall_info_cache fci_cache_local;
808
72.4k
  zend_function *func;
809
72.4k
  uint32_t call_info;
810
72.4k
  void *object_or_called_scope;
811
812
72.4k
  ZVAL_UNDEF(fci->retval);
813
814
72.4k
  if (!EG(active)) {
815
0
    return FAILURE; /* executor is already inactive */
816
0
  }
817
818
72.4k
  if (EG(exception)) {
819
54
    if (fci_cache) {
820
54
      zend_release_fcall_info_cache(fci_cache);
821
54
    }
822
54
    return SUCCESS; /* we would result in an unstable executor otherwise */
823
54
  }
824
825
72.3k
  ZEND_ASSERT(ZEND_FCI_INITIALIZED(*fci));
826
827
72.3k
  if (!fci_cache || !fci_cache->function_handler) {
828
54
    char *error = NULL;
829
830
54
    if (!fci_cache) {
831
36
      fci_cache = &fci_cache_local;
832
36
    }
833
834
54
    if (!zend_is_callable_ex(&fci->function_name, fci->object, 0, NULL, fci_cache, &error)) {
835
3
      ZEND_ASSERT(error && "Should have error if not callable");
836
3
      zend_string *callable_name
837
3
        = zend_get_callable_name_ex(&fci->function_name, fci->object);
838
3
      zend_throw_error(NULL, "Invalid callback %s, %s", ZSTR_VAL(callable_name), error);
839
3
      efree(error);
840
3
      zend_string_release_ex(callable_name, 0);
841
3
      return SUCCESS;
842
3
    }
843
844
51
    ZEND_ASSERT(!error);
845
51
  }
846
847
72.3k
  func = fci_cache->function_handler;
848
72.3k
  if ((func->common.fn_flags & ZEND_ACC_STATIC) || !fci_cache->object) {
849
34.9k
    object_or_called_scope = fci_cache->called_scope;
850
34.9k
    call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC;
851
37.4k
  } else {
852
37.4k
    object_or_called_scope = fci_cache->object;
853
37.4k
    call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC | ZEND_CALL_HAS_THIS;
854
37.4k
  }
855
856
72.3k
  if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_DEPRECATED)) {
857
9
    zend_deprecated_function(func);
858
859
9
    if (UNEXPECTED(EG(exception))) {
860
0
      return SUCCESS;
861
0
    }
862
9
  }
863
864
72.3k
  call = zend_vm_stack_push_call_frame(call_info,
865
72.3k
    func, fci->param_count, object_or_called_scope);
866
72.3k
  uint32_t consumed_args = fci->param_count ? fci->consumed_args : 0;
867
868
72.3k
  ZEND_ASSERT((consumed_args & (consumed_args - 1)) == 0);
869
870
145k
  for (uint32_t i = 0; i < fci->param_count; i++) {
871
73.1k
    zval *param = ZEND_CALL_ARG(call, i+1);
872
73.1k
    zval *arg = &fci->params[i];
873
73.1k
    bool must_wrap = false;
874
73.1k
    if (UNEXPECTED(Z_ISUNDEF_P(arg))) {
875
      /* Allow forwarding undef slots. This is only used by Closure::__invoke(). */
876
3
      ZVAL_UNDEF(param);
877
3
      ZEND_ADD_CALL_FLAG(call, ZEND_CALL_MAY_HAVE_UNDEF);
878
3
      continue;
879
3
    }
880
881
73.1k
    if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) {
882
285
      if (UNEXPECTED(!Z_ISREF_P(arg))) {
883
78
        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
66
          zend_param_must_be_ref(func, i + 1);
887
66
          must_wrap = true;
888
66
          if (UNEXPECTED(EG(exception))) {
889
0
            ZEND_CALL_NUM_ARGS(call) = i;
890
27
cleanup_args:
891
27
            zend_vm_stack_free_args(call);
892
27
            if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
893
3
              zend_free_extra_named_params(call->extra_named_params);
894
3
            }
895
27
            zend_vm_stack_free_call_frame(call);
896
27
            zend_release_fcall_info_cache(fci_cache);
897
27
            return SUCCESS;
898
0
          }
899
66
        }
900
78
      }
901
72.8k
    } else {
902
72.8k
      if (Z_ISREF_P(arg) &&
903
48
          !(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
904
        /* don't separate references for __call */
905
48
        arg = Z_REFVAL_P(arg);
906
48
      }
907
72.8k
    }
908
909
73.1k
    if (EXPECTED(!must_wrap)) {
910
73.0k
      if (EXPECTED(consumed_args == 0)
911
207
          || !zend_fci_is_consumed_arg(consumed_args, i)
912
73.0k
          || Z_ISREF_P(arg)
913
72.8k
          || arg != &fci->params[i]) {
914
72.8k
        ZVAL_COPY(param, arg);
915
72.8k
      } else {
916
168
        ZVAL_COPY_VALUE(param, arg);
917
168
        ZVAL_UNDEF(arg);
918
168
      }
919
73.0k
    } else {
920
66
      Z_TRY_ADDREF_P(arg);
921
66
      ZVAL_NEW_REF(param, arg);
922
66
    }
923
73.1k
  }
924
925
72.3k
  if (fci->named_params) {
926
264
    zend_string *name;
927
264
    zval *arg;
928
264
    uint32_t arg_num = ZEND_CALL_NUM_ARGS(call) + 1;
929
264
    bool have_named_params = false;
930
1.10k
    ZEND_HASH_FOREACH_STR_KEY_VAL(fci->named_params, name, arg) {
931
1.10k
      bool must_wrap = false;
932
1.10k
      zval *target;
933
1.10k
      if (name) {
934
291
        void *cache_slot[2] = {NULL, NULL};
935
291
        have_named_params = true;
936
291
        target = zend_handle_named_arg(&call, name, &arg_num, cache_slot);
937
291
        if (!target) {
938
15
          goto cleanup_args;
939
15
        }
940
291
      } else {
941
129
        if (have_named_params) {
942
12
          zend_throw_error(NULL,
943
12
            "Cannot use positional argument after named argument");
944
12
          goto cleanup_args;
945
12
        }
946
947
117
        zend_vm_stack_extend_call_frame(&call, arg_num - 1, 1);
948
117
        target = ZEND_CALL_ARG(call, arg_num);
949
117
      }
950
951
393
      if (ARG_SHOULD_BE_SENT_BY_REF(func, arg_num)) {
952
18
        if (UNEXPECTED(!Z_ISREF_P(arg))) {
953
18
          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
12
            zend_param_must_be_ref(func, arg_num);
957
12
            must_wrap = true;
958
12
            if (UNEXPECTED(EG(exception))) {
959
0
              goto cleanup_args;
960
0
            }
961
12
          }
962
18
        }
963
375
      } else {
964
375
        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
375
      }
970
971
393
      if (EXPECTED(!must_wrap)) {
972
381
        ZVAL_COPY(target, arg);
973
381
      } else {
974
12
        Z_TRY_ADDREF_P(arg);
975
12
        ZVAL_NEW_REF(target, arg);
976
12
      }
977
393
      if (!name) {
978
117
        ZEND_CALL_NUM_ARGS(call)++;
979
117
        arg_num++;
980
117
      }
981
393
    } ZEND_HASH_FOREACH_END();
982
264
  }
983
984
72.3k
  if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_MAY_HAVE_UNDEF)) {
985
    /* zend_handle_undef_args assumes prev_execute_data is initialized. */
986
147
    call->prev_execute_data = NULL;
987
147
    if (zend_handle_undef_args(call) == FAILURE) {
988
6
      zend_vm_stack_free_args(call);
989
6
      zend_vm_stack_free_call_frame(call);
990
6
      return SUCCESS;
991
6
    }
992
147
  }
993
994
72.3k
  if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
995
3.97k
    uint32_t call_info;
996
997
3.97k
    GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
998
3.97k
    call_info = ZEND_CALL_CLOSURE;
999
3.97k
    if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
1000
27
      call_info |= ZEND_CALL_FAKE_CLOSURE;
1001
27
    }
1002
3.97k
    ZEND_ADD_CALL_FLAG(call, call_info);
1003
3.97k
  }
1004
1005
72.3k
  if (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
1006
36
    fci_cache->function_handler = NULL;
1007
36
  }
1008
1009
72.3k
  const zend_class_entry *orig_fake_scope = EG(fake_scope);
1010
72.3k
  EG(fake_scope) = NULL;
1011
72.3k
  if (func->type == ZEND_USER_FUNCTION) {
1012
36.1k
    uint32_t orig_jit_trace_num = EG(jit_trace_num);
1013
1014
36.1k
    zend_init_func_execute_data(call, &func->op_array, fci->retval);
1015
36.1k
    ZEND_OBSERVER_FCALL_BEGIN(call);
1016
36.1k
    zend_execute_ex(call);
1017
36.1k
    EG(jit_trace_num) = orig_jit_trace_num;
1018
36.2k
  } else {
1019
36.2k
    ZEND_ASSERT(func->type == ZEND_INTERNAL_FUNCTION);
1020
36.2k
    ZVAL_NULL(fci->retval);
1021
36.2k
    call->prev_execute_data = EG(current_execute_data);
1022
36.2k
    EG(current_execute_data) = call;
1023
36.2k
#if ZEND_DEBUG
1024
36.2k
    bool should_throw = zend_internal_call_should_throw(func, call);
1025
36.2k
#endif
1026
36.2k
    ZEND_OBSERVER_FCALL_BEGIN(call);
1027
36.2k
    if (EXPECTED(zend_execute_internal == NULL)) {
1028
      /* saves one function call if zend_execute_internal is not used */
1029
0
      func->internal_function.handler(call, fci->retval);
1030
36.2k
    } else {
1031
36.2k
      zend_execute_internal(call, fci->retval);
1032
36.2k
    }
1033
1034
36.2k
#if ZEND_DEBUG
1035
36.2k
    if (!EG(exception) && call->func) {
1036
36.0k
      if (should_throw) {
1037
0
        zend_internal_call_arginfo_violation(call->func);
1038
0
      }
1039
36.0k
      if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
1040
35.6k
        bool result = zend_verify_internal_return_type(call->func, fci->retval);
1041
35.6k
        ZEND_ASSERT(result);
1042
35.6k
      }
1043
36.0k
      ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
1044
36.0k
        ? Z_ISREF_P(fci->retval) : !Z_ISREF_P(fci->retval));
1045
36.0k
      ZEND_ASSERT(!(call->func->common.fn_flags2 & ZEND_ACC2_FORBID_DYN_CALLS));
1046
36.0k
    }
1047
36.2k
#endif
1048
36.2k
    ZEND_OBSERVER_FCALL_END(call, fci->retval);
1049
36.2k
    EG(current_execute_data) = call->prev_execute_data;
1050
36.2k
    zend_vm_stack_free_args(call);
1051
36.2k
    if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
1052
3
      zend_array_release(call->extra_named_params);
1053
3
    }
1054
1055
36.2k
    if (EG(exception)) {
1056
132
      zval_ptr_dtor(fci->retval);
1057
132
      ZVAL_UNDEF(fci->retval);
1058
132
    }
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
36.2k
    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
36.2k
    if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) {
1071
6
      OBJ_RELEASE(Z_OBJ(call->This));
1072
6
    }
1073
36.2k
  }
1074
72.3k
  EG(fake_scope) = orig_fake_scope;
1075
1076
72.3k
  zend_vm_stack_free_call_frame(call);
1077
1078
72.3k
  if (UNEXPECTED(EG(exception))) {
1079
2.06k
    if (UNEXPECTED(!EG(current_execute_data))) {
1080
133
      zend_throw_exception_internal(NULL);
1081
1.92k
    } else if (EG(current_execute_data)->func &&
1082
1.92k
               ZEND_USER_CODE(EG(current_execute_data)->func->common.type)) {
1083
1.23k
      zend_rethrow_exception(EG(current_execute_data));
1084
1.23k
    }
1085
2.06k
  }
1086
1087
72.3k
  return SUCCESS;
1088
72.3k
}
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
67.9k
{
1095
67.9k
  zval retval;
1096
67.9k
  zend_fcall_info fci;
1097
67.9k
  zend_fcall_info_cache fcic;
1098
1099
67.9k
  ZEND_ASSERT(fn && "zend_function must be passed!");
1100
1101
67.9k
  fci.size = sizeof(fci);
1102
67.9k
  fci.object = object;
1103
67.9k
  fci.retval = retval_ptr ? retval_ptr : &retval;
1104
67.9k
  fci.param_count = param_count;
1105
67.9k
  fci.params = params;
1106
67.9k
  fci.named_params = named_params;
1107
67.9k
  fci.consumed_args = 0;
1108
67.9k
  ZVAL_UNDEF(&fci.function_name); /* Unused */
1109
1110
67.9k
  fcic.function_handler = fn;
1111
67.9k
  fcic.object = object;
1112
67.9k
  fcic.called_scope = called_scope;
1113
1114
67.9k
  zend_result result = zend_call_function(&fci, &fcic);
1115
67.9k
  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
67.9k
  if (!retval_ptr) {
1124
6.09k
    zval_ptr_dtor(&retval);
1125
6.09k
  }
1126
67.9k
}
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
198
{
1131
198
  zval params[2];
1132
198
  ZVAL_COPY_VALUE(&params[0], param1);
1133
198
  ZVAL_COPY_VALUE(&params[1], param2);
1134
198
  zend_call_known_instance_method(fn, object, retval_ptr, 2, params);
1135
198
}
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
654
{
1141
654
  zval zval_method;
1142
654
  zend_fcall_info_cache fcc;
1143
1144
654
  ZVAL_STR(&zval_method, method_name);
1145
1146
654
  if (UNEXPECTED(!zend_is_callable_ex(&zval_method, object, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &fcc, NULL))) {
1147
73
    ZVAL_UNDEF(retval);
1148
73
    return FAILURE;
1149
73
  }
1150
1151
581
  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
581
  zend_release_fcall_info_cache(&fcc);
1154
581
  return SUCCESS;
1155
654
}
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
291
ZEND_API bool zend_is_valid_class_name(const zend_string *name) {
1170
2.70k
  for (size_t i = 0; i < ZSTR_LEN(name); i++) {
1171
2.44k
    unsigned char c = ZSTR_VAL(name)[i];
1172
2.44k
    if (!ZEND_BIT_TEST(valid_chars, c)) {
1173
30
      return 0;
1174
30
    }
1175
2.44k
  }
1176
261
  return 1;
1177
291
}
1178
1179
ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *key, uint32_t flags) /* {{{ */
1180
170k
{
1181
170k
  zend_class_entry *ce = NULL;
1182
170k
  zval *zv;
1183
170k
  zend_string *lc_name;
1184
170k
  zend_string *autoload_name;
1185
170k
  uint32_t ce_cache = 0;
1186
1187
170k
  if (ZSTR_HAS_CE_CACHE(name) && ZSTR_VALID_CE_CACHE(name)) {
1188
123k
    ce_cache = GC_REFCOUNT(name);
1189
123k
    ce = GET_CE_CACHE(ce_cache);
1190
123k
    if (EXPECTED(ce)) {
1191
94.5k
      return ce;
1192
94.5k
    }
1193
123k
  }
1194
1195
75.9k
  if (key) {
1196
66.0k
    lc_name = key;
1197
66.0k
  } else {
1198
9.92k
    if (!ZSTR_LEN(name)) {
1199
45
      return NULL;
1200
45
    }
1201
1202
9.88k
    if (ZSTR_VAL(name)[0] == '\\') {
1203
33
      lc_name = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
1204
33
      zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
1205
9.85k
    } else {
1206
9.85k
      lc_name = zend_string_tolower(name);
1207
9.85k
    }
1208
9.88k
  }
1209
1210
75.9k
  zv = zend_hash_find(EG(class_table), lc_name);
1211
75.9k
  if (zv) {
1212
32.5k
    if (!key) {
1213
6.07k
      zend_string_release_ex(lc_name, 0);
1214
6.07k
    }
1215
32.5k
    ce = (zend_class_entry*)Z_PTR_P(zv);
1216
32.5k
    if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_LINKED))) {
1217
339
      if ((flags & ZEND_FETCH_CLASS_ALLOW_UNLINKED) ||
1218
51
        ((flags & ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED) &&
1219
312
          (ce->ce_flags & ZEND_ACC_NEARLY_LINKED))) {
1220
312
        if (!CG(unlinked_uses)) {
1221
103
          ALLOC_HASHTABLE(CG(unlinked_uses));
1222
103
          zend_hash_init(CG(unlinked_uses), 0, NULL, NULL, 0);
1223
103
        }
1224
312
        zend_hash_index_add_empty_element(CG(unlinked_uses), (zend_ulong)(uintptr_t)ce);
1225
312
        return ce;
1226
312
      }
1227
27
      return NULL;
1228
339
    }
1229
    /* Don't populate CE_CACHE for mutable classes during compilation.
1230
     * The class may be freed while persisting. */
1231
32.2k
    if (ce_cache &&
1232
25.0k
        (!CG(in_compilation) || (ce->ce_flags & ZEND_ACC_IMMUTABLE))) {
1233
23.3k
      SET_CE_CACHE(ce_cache, ce);
1234
23.3k
    }
1235
32.2k
    return ce;
1236
32.5k
  }
1237
1238
  /* The compiler is not-reentrant. Make sure we autoload only during run-time. */
1239
43.3k
  if ((flags & ZEND_FETCH_CLASS_NO_AUTOLOAD) || zend_is_compiling()) {
1240
41.7k
    if (!key) {
1241
3.17k
      zend_string_release_ex(lc_name, 0);
1242
3.17k
    }
1243
41.7k
    return NULL;
1244
41.7k
  }
1245
1246
1.57k
  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
1.57k
  if (!key && !ZSTR_HAS_CE_CACHE(name) && !zend_is_valid_class_name(name)) {
1255
27
    zend_string_release_ex(lc_name, 0);
1256
27
    return NULL;
1257
27
  }
1258
1259
1.55k
  if (zend_hash_add_empty_element(&EG(autoload_current_classnames), lc_name) == NULL) {
1260
15
    if (!key) {
1261
15
      zend_string_release_ex(lc_name, 0);
1262
15
    }
1263
15
    return NULL;
1264
15
  }
1265
1266
1.53k
  if (ZSTR_VAL(name)[0] == '\\') {
1267
6
    autoload_name = zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
1268
1.52k
  } else {
1269
1.52k
    autoload_name = zend_string_copy(name);
1270
1.52k
  }
1271
1272
1.53k
  zend_string *previous_filename = EG(filename_override);
1273
1.53k
  zend_long previous_lineno = EG(lineno_override);
1274
1.53k
  EG(filename_override) = NULL;
1275
1.53k
  EG(lineno_override) = -1;
1276
1.53k
  ce = zend_autoload(autoload_name, lc_name);
1277
1.53k
  EG(filename_override) = previous_filename;
1278
1.53k
  EG(lineno_override) = previous_lineno;
1279
1280
1.53k
  zend_string_release_ex(autoload_name, 0);
1281
1.53k
  zend_hash_del(&EG(autoload_current_classnames), lc_name);
1282
1283
1.53k
  if (!key) {
1284
549
    zend_string_release_ex(lc_name, 0);
1285
549
  }
1286
1.53k
  if (ce) {
1287
360
    ZEND_ASSERT(!CG(in_compilation));
1288
360
    if (ce_cache) {
1289
282
      SET_CE_CACHE(ce_cache, ce);
1290
282
    }
1291
360
  }
1292
1.53k
  return ce;
1293
1.53k
}
1294
/* }}} */
1295
1296
ZEND_API zend_class_entry *zend_lookup_class(zend_string *name) /* {{{ */
1297
5.38k
{
1298
5.38k
  return zend_lookup_class_ex(name, NULL, 0);
1299
5.38k
}
1300
/* }}} */
1301
1302
ZEND_API zend_class_entry *zend_get_called_scope(const zend_execute_data *ex) /* {{{ */
1303
37.9k
{
1304
37.9k
  while (ex) {
1305
1.50k
    if (Z_TYPE(ex->This) == IS_OBJECT) {
1306
663
      return Z_OBJCE(ex->This);
1307
840
    } else if (Z_CE(ex->This)) {
1308
555
      return Z_CE(ex->This);
1309
555
    } else if (ex->func) {
1310
285
      if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
1311
258
        return NULL;
1312
258
      }
1313
285
    }
1314
27
    ex = ex->prev_execute_data;
1315
27
  }
1316
36.4k
  return NULL;
1317
37.9k
}
1318
/* }}} */
1319
1320
ZEND_API zend_object *zend_get_this_object(const zend_execute_data *ex) /* {{{ */
1321
37.2k
{
1322
37.2k
  while (ex) {
1323
837
    if (Z_TYPE(ex->This) == IS_OBJECT) {
1324
438
      return Z_OBJ(ex->This);
1325
438
    } else if (ex->func) {
1326
399
      if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
1327
366
        return NULL;
1328
366
      }
1329
399
    }
1330
33
    ex = ex->prev_execute_data;
1331
33
  }
1332
36.4k
  return NULL;
1333
37.2k
}
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
44.4k
{
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
44.4k
    struct itimerval t_r;   /* timeout requested */
1601
44.4k
    int signo;
1602
1603
    // Prevent EINVAL error
1604
44.4k
    if (seconds < 0 || seconds > 999999999) {
1605
0
      seconds = 0;
1606
0
    }
1607
1608
44.4k
    if(seconds) {
1609
6
      t_r.it_value.tv_sec = seconds;
1610
6
      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
6
      setitimer(ITIMER_PROF, &t_r, NULL);
1620
6
    }
1621
44.4k
    signo = SIGPROF;
1622
44.4k
# endif
1623
1624
44.4k
    if (reset_signals) {
1625
44.4k
# ifdef ZEND_SIGNALS
1626
44.4k
      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
44.4k
    }
1644
44.4k
  }
1645
44.4k
#endif /* HAVE_SETITIMER */
1646
44.4k
}
1647
/* }}} */
1648
1649
void zend_set_timeout(zend_long seconds, bool reset_signals) /* {{{ */
1650
44.4k
{
1651
1652
44.4k
  EG(timeout_seconds) = seconds;
1653
44.4k
  zend_set_timeout_ex(seconds, reset_signals);
1654
44.4k
  zend_atomic_bool_store_ex(&EG(timed_out), false);
1655
44.4k
}
1656
/* }}} */
1657
1658
void zend_unset_timeout(void) /* {{{ */
1659
44.4k
{
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
44.4k
  if (EG(timeout_seconds)) {
1675
12
    struct itimerval no_timeout;
1676
1677
12
    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
12
    setitimer(ITIMER_PROF, &no_timeout, NULL);
1683
12
# endif
1684
12
  }
1685
44.4k
#endif
1686
44.4k
  zend_atomic_bool_store_ex(&EG(timed_out), false);
1687
44.4k
}
1688
/* }}} */
1689
1690
static ZEND_COLD void report_class_fetch_error(const zend_string *class_name, uint32_t fetch_type)
1691
39.2k
{
1692
39.2k
  if (fetch_type & ZEND_FETCH_CLASS_SILENT) {
1693
38.5k
    return;
1694
38.5k
  }
1695
1696
685
  if (EG(exception)) {
1697
156
    if (!(fetch_type & ZEND_FETCH_CLASS_EXCEPTION)) {
1698
0
      zend_exception_uncaught_error("During class fetch");
1699
0
    }
1700
156
    return;
1701
156
  }
1702
1703
529
  if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_INTERFACE) {
1704
18
    zend_throw_or_error(fetch_type, NULL, "Interface \"%s\" not found", ZSTR_VAL(class_name));
1705
511
  } else if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_TRAIT) {
1706
27
    zend_throw_or_error(fetch_type, NULL, "Trait \"%s\" not found", ZSTR_VAL(class_name));
1707
484
  } else {
1708
484
    zend_throw_or_error(fetch_type, NULL, "Class \"%s\" not found", ZSTR_VAL(class_name));
1709
484
  }
1710
529
}
1711
1712
zend_class_entry *zend_fetch_class(zend_string *class_name, uint32_t fetch_type) /* {{{ */
1713
3.11k
{
1714
3.11k
  zend_class_entry *ce, *scope;
1715
3.11k
  uint32_t fetch_sub_type = fetch_type & ZEND_FETCH_CLASS_MASK;
1716
1717
3.17k
check_fetch_type:
1718
3.17k
  switch (fetch_sub_type) {
1719
1.20k
    case ZEND_FETCH_CLASS_SELF:
1720
1.20k
      scope = zend_get_executed_scope();
1721
1.20k
      if (UNEXPECTED(!scope)) {
1722
30
        zend_throw_or_error(fetch_type, NULL, "Cannot access \"self\" when no class scope is active");
1723
30
      }
1724
1.20k
      return scope;
1725
515
    case ZEND_FETCH_CLASS_PARENT:
1726
515
      scope = zend_get_executed_scope();
1727
515
      if (UNEXPECTED(!scope)) {
1728
6
        zend_throw_or_error(fetch_type, NULL, "Cannot access \"parent\" when no class scope is active");
1729
6
        return NULL;
1730
6
      }
1731
509
      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
509
      return scope->parent;
1735
495
    case ZEND_FETCH_CLASS_STATIC:
1736
495
      ce = zend_get_called_scope(EG(current_execute_data));
1737
495
      if (UNEXPECTED(!ce)) {
1738
21
        zend_throw_or_error(fetch_type, NULL, "Cannot access \"static\" when no class scope is active");
1739
21
        return NULL;
1740
21
      }
1741
474
      return ce;
1742
60
    case ZEND_FETCH_CLASS_AUTO: {
1743
60
        fetch_sub_type = zend_get_class_fetch_type(class_name);
1744
60
        if (UNEXPECTED(fetch_sub_type != ZEND_FETCH_CLASS_DEFAULT)) {
1745
60
          goto check_fetch_type;
1746
60
        }
1747
60
      }
1748
0
      break;
1749
3.17k
  }
1750
1751
904
  ce = zend_lookup_class_ex(class_name, NULL, fetch_type);
1752
904
  if (!ce) {
1753
84
    report_class_fetch_error(class_name, fetch_type);
1754
84
    return NULL;
1755
84
  }
1756
820
  return ce;
1757
904
}
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
234
{
1763
234
  zend_class_entry *ce;
1764
234
  switch (fetch_type & ZEND_FETCH_CLASS_MASK) {
1765
15
    case ZEND_FETCH_CLASS_SELF:
1766
15
      if (UNEXPECTED(!scope)) {
1767
3
        zend_throw_or_error(fetch_type, NULL, "Cannot access \"self\" when no class scope is active");
1768
3
      }
1769
15
      return scope;
1770
6
    case ZEND_FETCH_CLASS_PARENT:
1771
6
      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
6
      if (UNEXPECTED(!scope->parent)) {
1776
3
        zend_throw_or_error(fetch_type, NULL, "Cannot access \"parent\" when current class scope has no parent");
1777
3
      }
1778
6
      return scope->parent;
1779
213
    case 0:
1780
213
      break;
1781
    /* Other fetch types are not supported by this function. */
1782
0
    default: ZEND_UNREACHABLE();
1783
234
  }
1784
1785
213
  ce = zend_lookup_class_ex(class_name, NULL, fetch_type);
1786
213
  if (!ce) {
1787
9
    report_class_fetch_error(class_name, fetch_type);
1788
9
    return NULL;
1789
9
  }
1790
204
  return ce;
1791
213
}
1792
1793
zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, zend_string *key, uint32_t fetch_type) /* {{{ */
1794
153k
{
1795
153k
  zend_class_entry *ce = zend_lookup_class_ex(class_name, key, fetch_type);
1796
153k
  if (!ce) {
1797
39.1k
    report_class_fetch_error(class_name, fetch_type);
1798
39.1k
    return NULL;
1799
39.1k
  }
1800
114k
  return ce;
1801
153k
}
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
1.69k
{
1812
1.69k
  zend_execute_data *ex;
1813
1.69k
  zend_array *symbol_table;
1814
1815
  /* Search for last called user function */
1816
1.69k
  ex = EG(current_execute_data);
1817
1.78k
  while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->common.type))) {
1818
90
    ex = ex->prev_execute_data;
1819
90
  }
1820
1.69k
  if (!ex) {
1821
0
    return NULL;
1822
0
  }
1823
1.69k
  if (ZEND_CALL_INFO(ex) & ZEND_CALL_HAS_SYMBOL_TABLE) {
1824
39
    return ex->symbol_table;
1825
39
  }
1826
1827
1.65k
  ZEND_ADD_CALL_FLAG(ex, ZEND_CALL_HAS_SYMBOL_TABLE);
1828
1.65k
  if (EG(symtable_cache_ptr) > EG(symtable_cache)) {
1829
635
    symbol_table = ex->symbol_table = *(--EG(symtable_cache_ptr));
1830
635
    if (!ex->func->op_array.last_var) {
1831
3
      return symbol_table;
1832
3
    }
1833
632
    zend_hash_extend(symbol_table, ex->func->op_array.last_var, 0);
1834
1.01k
  } else {
1835
1.01k
    symbol_table = ex->symbol_table = zend_new_array(ex->func->op_array.last_var);
1836
1.01k
    if (!ex->func->op_array.last_var) {
1837
46
      return symbol_table;
1838
46
    }
1839
972
    zend_hash_real_init_mixed(symbol_table);
1840
    /*printf("Cache miss!  Initialized %x\n", EG(active_symbol_table));*/
1841
972
  }
1842
1.60k
  if (EXPECTED(ex->func->op_array.last_var)) {
1843
1.60k
    zend_string **str = ex->func->op_array.vars;
1844
1.60k
    zend_string **end = str + ex->func->op_array.last_var;
1845
1.60k
    zval *var = ZEND_CALL_VAR_NUM(ex, 0);
1846
1847
4.10k
    do {
1848
4.10k
      _zend_hash_append_ind(symbol_table, *str, var);
1849
4.10k
      str++;
1850
4.10k
      var++;
1851
4.10k
    } while (str != end);
1852
1.60k
  }
1853
1.60k
  return symbol_table;
1854
1.65k
}
1855
/* }}} */
1856
1857
ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */
1858
52.4k
{
1859
52.4k
  const zend_op_array *op_array = &execute_data->func->op_array;
1860
52.4k
  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
52.4k
  if (EXPECTED(op_array->last_var)) {
1865
52.4k
    zend_string **str = op_array->vars;
1866
52.4k
    zend_string **end = str + op_array->last_var;
1867
52.4k
    zval *var = EX_VAR_NUM(0);
1868
1869
402k
    do {
1870
402k
      zval *zv = zend_hash_find_known_hash(ht, *str);
1871
1872
402k
      if (zv) {
1873
240k
        if (Z_TYPE_P(zv) == IS_INDIRECT) {
1874
240k
          const zval *val = Z_INDIRECT_P(zv);
1875
1876
240k
          ZVAL_COPY_VALUE(var, val);
1877
240k
        } else {
1878
48
          ZVAL_COPY_VALUE(var, zv);
1879
48
        }
1880
240k
      } else {
1881
161k
        ZVAL_UNDEF(var);
1882
161k
        zv = zend_hash_add_new(ht, *str, var);
1883
161k
      }
1884
402k
      ZVAL_INDIRECT(zv, var);
1885
402k
      str++;
1886
402k
      var++;
1887
402k
    } while (str != end);
1888
52.4k
  }
1889
52.4k
}
1890
/* }}} */
1891
1892
ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */
1893
20.2k
{
1894
20.2k
  const zend_op_array *op_array = &execute_data->func->op_array;
1895
20.2k
  HashTable *ht = execute_data->symbol_table;
1896
1897
  /* copy real values from CV slots into symbol table */
1898
20.2k
  if (EXPECTED(op_array->last_var)) {
1899
20.2k
    zend_string **str = op_array->vars;
1900
20.2k
    zend_string **end = str + op_array->last_var;
1901
20.2k
    zval *var = EX_VAR_NUM(0);
1902
1903
102k
    do {
1904
102k
      if (Z_TYPE_P(var) == IS_UNDEF) {
1905
27.9k
        zend_hash_del(ht, *str);
1906
74.8k
      } else {
1907
74.8k
        zend_hash_update(ht, *str, var);
1908
74.8k
        ZVAL_UNDEF(var);
1909
74.8k
      }
1910
102k
      str++;
1911
102k
      var++;
1912
102k
    } while (str != end);
1913
20.2k
  }
1914
20.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
/* }}} */