Coverage Report

Created: 2025-12-14 06:06

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