Coverage Report

Created: 2025-12-14 06:06

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