Coverage Report

Created: 2026-06-02 06:36

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