Coverage Report

Created: 2026-01-18 06:49

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