Coverage Report

Created: 2026-10-28 06:20

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