Coverage Report

Created: 2025-06-13 06:43

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