Coverage Report

Created: 2025-12-14 06:10

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