Coverage Report

Created: 2025-12-31 07:28

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