Coverage Report

Created: 2026-01-18 06:46

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