Coverage Report

Created: 2026-06-02 06:36

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