Coverage Report

Created: 2026-06-02 06:40

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