Coverage Report

Created: 2026-06-13 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/Zend/zend_builtin_functions.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
   +----------------------------------------------------------------------+
17
*/
18
19
#include "php_version.h"
20
#include "zend.h"
21
#include "zend_API.h"
22
#include "zend_attributes.h"
23
#include "zend_gc.h"
24
#include "zend_builtin_functions.h"
25
#include "zend_constants.h"
26
#include "zend_ini.h"
27
#include "zend_interfaces.h"
28
#include "zend_exceptions.h"
29
#include "zend_extensions.h"
30
#include "zend_closures.h"
31
#include "zend_generators.h"
32
#include "zend_autoload.h"
33
#include "zend_builtin_functions_arginfo.h"
34
#include "zend_smart_str.h"
35
36
/* }}} */
37
38
16
ZEND_MINIT_FUNCTION(core) { /* {{{ */
39
16
  zend_autoload = zend_perform_class_autoload;
40
16
  zend_register_default_classes();
41
42
16
  zend_standard_class_def = register_class_stdClass();
43
44
16
  return SUCCESS;
45
16
}
46
/* }}} */
47
48
static zend_module_entry zend_builtin_module = { /* {{{ */
49
  STANDARD_MODULE_HEADER,
50
  "Core",
51
  ext_functions,
52
  ZEND_MINIT(core),
53
  NULL,
54
  NULL,
55
  NULL,
56
  NULL,
57
  ZEND_VERSION,
58
  STANDARD_MODULE_PROPERTIES
59
};
60
/* }}} */
61
62
zend_result zend_startup_builtin_functions(void) /* {{{ */
63
16
{
64
16
  zend_module_entry *module;
65
16
  EG(current_module) = module = zend_register_module_ex(&zend_builtin_module, MODULE_PERSISTENT);
66
16
  if (UNEXPECTED(module == NULL)) {
67
0
    return FAILURE;
68
0
  }
69
16
  ZEND_ASSERT(module->module_number == 0);
70
16
  return SUCCESS;
71
16
}
72
/* }}} */
73
74
ZEND_FUNCTION(clone)
75
258
{
76
258
  zend_object *zobj;
77
258
  HashTable *with = (HashTable*)&zend_empty_array;
78
79
774
  ZEND_PARSE_PARAMETERS_START(1, 2)
80
1.03k
    Z_PARAM_OBJ(zobj)
81
249
    Z_PARAM_OPTIONAL
82
918
    Z_PARAM_ARRAY_HT(with)
83
258
  ZEND_PARSE_PARAMETERS_END();
84
85
  /* clone() also exists as the ZEND_CLONE OPcode and both implementations must be kept in sync. */
86
87
238
  const zend_class_entry *scope = zend_get_executed_scope();
88
89
238
  const zend_class_entry *ce = zobj->ce;
90
238
  const zend_function *clone = ce->clone;
91
92
238
  if (UNEXPECTED(zobj->handlers->clone_obj == NULL)) {
93
6
    zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name));
94
6
    RETURN_THROWS();
95
6
  }
96
97
232
  if (clone && !zend_check_method_accessible(clone, scope)) {
98
0
    zend_bad_method_call(clone, clone->common.function_name, scope);
99
0
    RETURN_THROWS();
100
0
  }
101
102
232
  zend_object *cloned;
103
232
  if (zend_hash_num_elements(with) > 0) {
104
193
    if (UNEXPECTED(!zobj->handlers->clone_obj_with)) {
105
0
      zend_throw_error(NULL, "Cloning objects of class %s with updated properties is not supported", ZSTR_VAL(ce->name));
106
0
      RETURN_THROWS();
107
0
    }
108
109
193
    cloned = zobj->handlers->clone_obj_with(zobj, scope, with);
110
193
  } else {
111
39
    cloned = zobj->handlers->clone_obj(zobj);
112
39
  }
113
114
232
  ZEND_ASSERT(cloned || EG(exception));
115
232
  if (EXPECTED(cloned)) {
116
232
    RETURN_OBJ(cloned);
117
232
  }
118
232
}
119
120
ZEND_FUNCTION(exit)
121
143
{
122
143
  zend_string *str = NULL;
123
143
  zend_long status = 0;
124
125
429
  ZEND_PARSE_PARAMETERS_START(0, 1)
126
429
    Z_PARAM_OPTIONAL
127
612
    Z_PARAM_STR_OR_LONG(str, status)
128
612
  ZEND_PARSE_PARAMETERS_END();
129
130
139
  if (str) {
131
103
    size_t len = ZSTR_LEN(str);
132
103
    if (len != 0) {
133
      /* An exception might be emitted by an output handler */
134
103
      zend_write(ZSTR_VAL(str), len);
135
103
      if (EG(exception)) {
136
7
        RETURN_THROWS();
137
7
      }
138
103
    }
139
103
  } else {
140
36
    EG(exit_status) = status;
141
36
  }
142
143
132
  ZEND_ASSERT(!EG(exception));
144
132
  zend_throw_unwind_exit();
145
132
}
146
147
/* {{{ Get the version of the Zend Engine */
148
ZEND_FUNCTION(zend_version)
149
0
{
150
0
  ZEND_PARSE_PARAMETERS_NONE();
151
152
0
  RETURN_STRINGL(ZEND_VERSION, sizeof(ZEND_VERSION)-1);
153
0
}
154
/* }}} */
155
156
/* {{{ Reclaims memory used by MM caches.
157
   Returns number of freed bytes */
158
ZEND_FUNCTION(gc_mem_caches)
159
0
{
160
0
  ZEND_PARSE_PARAMETERS_NONE();
161
162
0
  RETURN_LONG(zend_mm_gc(zend_mm_get_heap()));
163
0
}
164
/* }}} */
165
166
/* {{{ Forces collection of any existing garbage cycles.
167
   Returns number of freed zvals */
168
ZEND_FUNCTION(gc_collect_cycles)
169
1.49k
{
170
1.49k
  ZEND_PARSE_PARAMETERS_NONE();
171
172
1.49k
  RETURN_LONG(gc_collect_cycles());
173
1.49k
}
174
/* }}} */
175
176
/* {{{ Returns status of the circular reference collector */
177
ZEND_FUNCTION(gc_enabled)
178
119
{
179
119
  ZEND_PARSE_PARAMETERS_NONE();
180
181
118
  RETURN_BOOL(gc_enabled());
182
118
}
183
/* }}} */
184
185
/* {{{ Activates the circular reference collector */
186
ZEND_FUNCTION(gc_enable)
187
30
{
188
30
  zend_string *key;
189
190
30
  ZEND_PARSE_PARAMETERS_NONE();
191
192
30
  key = ZSTR_INIT_LITERAL("zend.enable_gc", 0);
193
30
  zend_alter_ini_entry_chars(key, "1", sizeof("1")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
194
30
  zend_string_release_ex(key, 0);
195
30
}
196
/* }}} */
197
198
/* {{{ Deactivates the circular reference collector */
199
ZEND_FUNCTION(gc_disable)
200
73
{
201
73
  zend_string *key;
202
203
73
  ZEND_PARSE_PARAMETERS_NONE();
204
205
73
  key = ZSTR_INIT_LITERAL("zend.enable_gc", 0);
206
73
  zend_alter_ini_entry_chars(key, "0", sizeof("0")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
207
73
  zend_string_release_ex(key, 0);
208
73
}
209
/* }}} */
210
211
/* {{{ Returns current GC statistics */
212
ZEND_FUNCTION(gc_status)
213
218
{
214
218
  zend_gc_status status;
215
216
218
  ZEND_PARSE_PARAMETERS_NONE();
217
218
218
  zend_gc_get_status(&status);
219
220
218
  array_init_size(return_value, 16);
221
222
218
  add_assoc_bool_ex(return_value, "running", sizeof("running")-1, status.active);
223
218
  add_assoc_bool_ex(return_value, "protected", sizeof("protected")-1, status.gc_protected);
224
218
  add_assoc_bool_ex(return_value, "full", sizeof("full")-1, status.full);
225
218
  add_assoc_long_ex(return_value, "runs", sizeof("runs")-1, (long)status.runs);
226
218
  add_assoc_long_ex(return_value, "collected", sizeof("collected")-1, (long)status.collected);
227
218
  add_assoc_long_ex(return_value, "threshold", sizeof("threshold")-1, (long)status.threshold);
228
218
  add_assoc_long_ex(return_value, "buffer_size", sizeof("buffer_size")-1, (long)status.buf_size);
229
218
  add_assoc_long_ex(return_value, "roots", sizeof("roots")-1, (long)status.num_roots);
230
231
  /* Using double because zend_long may be too small on some platforms */
232
218
  add_assoc_double_ex(return_value, "application_time", sizeof("application_time")-1, (double) status.application_time / ZEND_NANO_IN_SEC);
233
218
  add_assoc_double_ex(return_value, "collector_time", sizeof("collector_time")-1, (double) status.collector_time / ZEND_NANO_IN_SEC);
234
218
  add_assoc_double_ex(return_value, "destructor_time", sizeof("destructor_time")-1, (double) status.dtor_time / ZEND_NANO_IN_SEC);
235
218
  add_assoc_double_ex(return_value, "free_time", sizeof("free_time")-1, (double) status.free_time / ZEND_NANO_IN_SEC);
236
218
}
237
/* }}} */
238
239
/* {{{ Get the number of arguments that were passed to the function */
240
ZEND_FUNCTION(func_num_args)
241
20
{
242
20
  const zend_execute_data *ex = EX(prev_execute_data);
243
244
20
  ZEND_PARSE_PARAMETERS_NONE();
245
246
13
  if (ex && (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE)) {
247
5
    zend_throw_error(NULL, "func_num_args() must be called from a function context");
248
5
    RETURN_THROWS();
249
5
  }
250
251
8
  if (zend_forbid_dynamic_call() == FAILURE) {
252
8
    RETURN_THROWS();
253
8
  }
254
255
0
  RETURN_LONG(ZEND_CALL_NUM_ARGS(ex));
256
0
}
257
/* }}} */
258
259
/* {{{ Get the $arg_num'th argument that was passed to the function */
260
ZEND_FUNCTION(func_get_arg)
261
275
{
262
275
  uint32_t arg_count, first_extra_arg;
263
275
  zval *arg;
264
275
  zend_long requested_offset;
265
275
  zend_execute_data *ex;
266
267
275
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &requested_offset) == FAILURE) {
268
3
    RETURN_THROWS();
269
3
  }
270
271
272
  if (requested_offset < 0) {
272
15
    zend_argument_value_error(1, "must be greater than or equal to 0");
273
15
    RETURN_THROWS();
274
15
  }
275
276
257
  ex = EX(prev_execute_data);
277
257
  if (ex && (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE)) {
278
11
    zend_throw_error(NULL, "func_get_arg() cannot be called from the global scope");
279
11
    RETURN_THROWS();
280
11
  }
281
282
246
  if (zend_forbid_dynamic_call() == FAILURE) {
283
5
    RETURN_THROWS();
284
5
  }
285
286
241
  arg_count = ZEND_CALL_NUM_ARGS(ex);
287
288
241
  if ((zend_ulong)requested_offset >= arg_count) {
289
51
    zend_argument_value_error(1, "must be less than the number of the arguments passed to the currently executed function");
290
51
    RETURN_THROWS();
291
51
  }
292
293
190
  first_extra_arg = ex->func->op_array.num_args;
294
190
  if ((zend_ulong)requested_offset >= first_extra_arg && (ZEND_CALL_NUM_ARGS(ex) > first_extra_arg)) {
295
46
    arg = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T) + (requested_offset - first_extra_arg);
296
144
  } else {
297
144
    arg = ZEND_CALL_ARG(ex, requested_offset + 1);
298
144
  }
299
190
  if (EXPECTED(!Z_ISUNDEF_P(arg))) {
300
139
    RETURN_COPY_DEREF(arg);
301
139
  }
302
190
}
303
/* }}} */
304
305
/* {{{ Get an array of the arguments that were passed to the function */
306
ZEND_FUNCTION(func_get_args)
307
27
{
308
27
  zval *p, *q;
309
27
  uint32_t arg_count, first_extra_arg;
310
27
  uint32_t i;
311
27
  zend_execute_data *ex = EX(prev_execute_data);
312
313
27
  ZEND_PARSE_PARAMETERS_NONE();
314
315
18
  if (ex && (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE)) {
316
13
    zend_throw_error(NULL, "func_get_args() cannot be called from the global scope");
317
13
    RETURN_THROWS();
318
13
  }
319
320
5
  if (zend_forbid_dynamic_call() == FAILURE) {
321
5
    RETURN_THROWS();
322
5
  }
323
324
0
  arg_count = ZEND_CALL_NUM_ARGS(ex);
325
326
0
  if (arg_count) {
327
0
    array_init_size(return_value, arg_count);
328
0
    first_extra_arg = ex->func->op_array.num_args;
329
0
    zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
330
0
    ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
331
0
      i = 0;
332
0
      p = ZEND_CALL_ARG(ex, 1);
333
0
      if (arg_count > first_extra_arg) {
334
0
        while (i < first_extra_arg) {
335
0
          q = p;
336
0
          if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
337
0
            ZVAL_DEREF(q);
338
0
            if (Z_OPT_REFCOUNTED_P(q)) {
339
0
              Z_ADDREF_P(q);
340
0
            }
341
0
            ZEND_HASH_FILL_SET(q);
342
0
          } else {
343
0
            ZEND_HASH_FILL_SET_NULL();
344
0
          }
345
0
          ZEND_HASH_FILL_NEXT();
346
0
          p++;
347
0
          i++;
348
0
        }
349
0
        p = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T);
350
0
      }
351
0
      while (i < arg_count) {
352
0
        q = p;
353
0
        if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
354
0
          ZVAL_DEREF(q);
355
0
          if (Z_OPT_REFCOUNTED_P(q)) {
356
0
            Z_ADDREF_P(q);
357
0
          }
358
0
          ZEND_HASH_FILL_SET(q);
359
0
        } else {
360
0
          ZEND_HASH_FILL_SET_NULL();
361
0
        }
362
0
        ZEND_HASH_FILL_NEXT();
363
0
        p++;
364
0
        i++;
365
0
      }
366
0
    } ZEND_HASH_FILL_END();
367
0
    Z_ARRVAL_P(return_value)->nNumOfElements = arg_count;
368
0
  } else {
369
0
    RETURN_EMPTY_ARRAY();
370
0
  }
371
0
}
372
/* }}} */
373
374
/* {{{ Get string length
375
   Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
376
ZEND_FUNCTION(strlen)
377
86
{
378
86
  zend_string *s;
379
380
253
  ZEND_PARSE_PARAMETERS_START(1, 1)
381
324
    Z_PARAM_STR(s)
382
86
  ZEND_PARSE_PARAMETERS_END();
383
384
75
  RETVAL_LONG(ZSTR_LEN(s));
385
75
}
386
/* }}} */
387
388
/* {{{ Binary safe string comparison */
389
ZEND_FUNCTION(strcmp)
390
0
{
391
0
  zend_string *s1, *s2;
392
393
0
  ZEND_PARSE_PARAMETERS_START(2, 2)
394
0
    Z_PARAM_STR(s1)
395
0
    Z_PARAM_STR(s2)
396
0
  ZEND_PARSE_PARAMETERS_END();
397
398
0
  RETURN_LONG(zend_binary_strcmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)));
399
0
}
400
/* }}} */
401
402
/* {{{ Binary safe string comparison */
403
ZEND_FUNCTION(strncmp)
404
71
{
405
71
  zend_string *s1, *s2;
406
71
  zend_long len;
407
408
212
  ZEND_PARSE_PARAMETERS_START(3, 3)
409
280
    Z_PARAM_STR(s1)
410
350
    Z_PARAM_STR(s2)
411
350
    Z_PARAM_LONG(len)
412
71
  ZEND_PARSE_PARAMETERS_END();
413
414
70
  if (len < 0) {
415
11
    zend_argument_value_error(3, "must be greater than or equal to 0");
416
11
    RETURN_THROWS();
417
11
  }
418
419
59
  RETURN_LONG(zend_binary_strncmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), len));
420
59
}
421
/* }}} */
422
423
/* {{{ Binary safe case-insensitive string comparison */
424
ZEND_FUNCTION(strcasecmp)
425
52
{
426
52
  zend_string *s1, *s2;
427
428
155
  ZEND_PARSE_PARAMETERS_START(2, 2)
429
204
    Z_PARAM_STR(s1)
430
255
    Z_PARAM_STR(s2)
431
52
  ZEND_PARSE_PARAMETERS_END();
432
433
51
  RETURN_LONG(zend_binary_strcasecmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)));
434
51
}
435
/* }}} */
436
437
/* {{{ Binary safe string comparison */
438
ZEND_FUNCTION(strncasecmp)
439
50
{
440
50
  zend_string *s1, *s2;
441
50
  zend_long len;
442
443
149
  ZEND_PARSE_PARAMETERS_START(3, 3)
444
196
    Z_PARAM_STR(s1)
445
245
    Z_PARAM_STR(s2)
446
245
    Z_PARAM_LONG(len)
447
50
  ZEND_PARSE_PARAMETERS_END();
448
449
49
  if (len < 0) {
450
7
    zend_argument_value_error(3, "must be greater than or equal to 0");
451
7
    RETURN_THROWS();
452
7
  }
453
454
42
  RETURN_LONG(zend_binary_strncasecmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), len));
455
42
}
456
/* }}} */
457
458
/* {{{ Return the current error_reporting level, and if an argument was passed - change to the new level */
459
ZEND_FUNCTION(error_reporting)
460
634
{
461
634
  zend_long err;
462
634
  bool err_is_null = 1;
463
634
  int old_error_reporting;
464
465
1.90k
  ZEND_PARSE_PARAMETERS_START(0, 1)
466
1.90k
    Z_PARAM_OPTIONAL
467
2.28k
    Z_PARAM_LONG_OR_NULL(err, err_is_null)
468
634
  ZEND_PARSE_PARAMETERS_END();
469
470
629
  old_error_reporting = EG(error_reporting);
471
472
629
  if (!err_is_null && err != old_error_reporting) {
473
465
    zend_ini_entry *p = EG(error_reporting_ini_entry);
474
475
465
    if (!p) {
476
3
      zval *zv = zend_hash_find_known_hash(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING));
477
3
      if (!zv) {
478
        /* Ini setting does not exist -- can this happen? */
479
0
        RETURN_LONG(old_error_reporting);
480
0
      }
481
482
3
      p = EG(error_reporting_ini_entry) = (zend_ini_entry*)Z_PTR_P(zv);
483
3
    }
484
465
    if (!p->modified) {
485
414
      if (!EG(modified_ini_directives)) {
486
123
        ALLOC_HASHTABLE(EG(modified_ini_directives));
487
123
        zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
488
123
      }
489
414
      if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), p) != NULL)) {
490
414
        p->orig_value = p->value;
491
414
        p->orig_modifiable = p->modifiable;
492
414
        p->modified = 1;
493
414
      }
494
414
    } else if (p->orig_value != p->value) {
495
44
      zend_string_release_ex(p->value, 0);
496
44
    }
497
498
465
    p->value = zend_long_to_str(err);
499
465
    EG(error_reporting) = err;
500
465
  }
501
502
629
  RETURN_LONG(old_error_reporting);
503
629
}
504
/* }}} */
505
506
static bool validate_constant_array_argument(HashTable *ht, uint32_t argument_number) /* {{{ */
507
85
{
508
85
  bool ret = true;
509
85
  zval *val;
510
511
85
  GC_PROTECT_RECURSION(ht);
512
267
  ZEND_HASH_FOREACH_VAL(ht, val) {
513
267
    ZVAL_DEREF(val);
514
267
    if (Z_TYPE_P(val) == IS_ARRAY && Z_REFCOUNTED_P(val)) {
515
12
      if (Z_IS_RECURSIVE_P(val)) {
516
10
        zend_argument_value_error(argument_number, "cannot be a recursive array");
517
10
        ret = false;
518
10
        break;
519
10
      } else if (!validate_constant_array_argument(Z_ARRVAL_P(val), argument_number)) {
520
0
        ret = false;
521
0
        break;
522
0
      }
523
12
    }
524
267
  } ZEND_HASH_FOREACH_END();
525
85
  GC_UNPROTECT_RECURSION(ht);
526
85
  return ret;
527
85
}
528
/* }}} */
529
530
static void copy_constant_array(zval *dst, const zval *src) /* {{{ */
531
75
{
532
75
  zend_string *key;
533
75
  zend_ulong idx;
534
75
  zval *new_val, *val;
535
536
75
  array_init_size(dst, zend_hash_num_elements(Z_ARRVAL_P(src)));
537
237
  ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(src), idx, key, val) {
538
    /* constant arrays can't contain references */
539
237
    ZVAL_DEREF(val);
540
237
    if (key) {
541
0
      new_val = zend_hash_add_new(Z_ARRVAL_P(dst), key, val);
542
81
    } else {
543
81
      new_val = zend_hash_index_add_new(Z_ARRVAL_P(dst), idx, val);
544
81
    }
545
237
    if (Z_TYPE_P(val) == IS_ARRAY) {
546
4
      if (Z_REFCOUNTED_P(val)) {
547
2
        copy_constant_array(new_val, val);
548
2
      }
549
77
    } else {
550
77
      Z_TRY_ADDREF_P(val);
551
77
    }
552
237
  } ZEND_HASH_FOREACH_END();
553
75
}
554
/* }}} */
555
556
/* {{{ Define a new constant */
557
ZEND_FUNCTION(define)
558
654
{
559
654
  zend_string *name;
560
654
  zval *val;
561
654
  bool non_cs = 0;
562
654
  zend_constant c;
563
564
1.96k
  ZEND_PARSE_PARAMETERS_START(2, 3)
565
2.60k
    Z_PARAM_STR(name)
566
3.23k
    Z_PARAM_ZVAL(val)
567
3.23k
    Z_PARAM_OPTIONAL
568
3.23k
    Z_PARAM_BOOL(non_cs)
569
654
  ZEND_PARSE_PARAMETERS_END();
570
571
647
  if (zend_memnstr(ZSTR_VAL(name), "::", sizeof("::") - 1, ZSTR_VAL(name) + ZSTR_LEN(name))) {
572
12
    zend_argument_value_error(1, "cannot be a class constant");
573
12
    RETURN_THROWS();
574
12
  }
575
576
635
  if (non_cs) {
577
1
    zend_error(E_WARNING, "define(): Argument #3 ($case_insensitive) is ignored since declaration of case-insensitive constants is no longer supported");
578
1
  }
579
580
635
  if (Z_TYPE_P(val) == IS_ARRAY && Z_REFCOUNTED_P(val)) {
581
83
    if (!validate_constant_array_argument(Z_ARRVAL_P(val), 2)) {
582
10
      RETURN_THROWS();
583
73
    } else {
584
73
      copy_constant_array(&c.value, val);
585
73
    }
586
552
  } else {
587
552
    ZVAL_COPY(&c.value, val);
588
552
  }
589
590
  /* non persistent */
591
625
  ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
592
625
  c.name = zend_string_copy(name);
593
625
  RETURN_BOOL(zend_register_constant(&c) != NULL);
594
625
}
595
/* }}} */
596
597
/* {{{ Check whether a constant exists
598
   Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
599
ZEND_FUNCTION(defined)
600
251
{
601
251
  zend_string *name;
602
603
753
  ZEND_PARSE_PARAMETERS_START(1, 1)
604
1.00k
    Z_PARAM_STR(name)
605
251
  ZEND_PARSE_PARAMETERS_END();
606
607
251
  RETURN_BOOL(zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT));
608
251
}
609
/* }}} */
610
611
/* {{{ Retrieves the class name */
612
ZEND_FUNCTION(get_class)
613
75
{
614
75
  zval *obj = NULL;
615
616
75
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o", &obj) == FAILURE) {
617
0
    RETURN_THROWS();
618
0
  }
619
620
75
  if (!obj) {
621
0
    const zend_class_entry *scope = zend_get_executed_scope();
622
623
0
    if (scope) {
624
0
      zend_error(E_DEPRECATED, "Calling get_class() without arguments is deprecated");
625
0
      if (UNEXPECTED(EG(exception))) {
626
0
        RETURN_THROWS();
627
0
      }
628
0
      RETURN_STR_COPY(scope->name);
629
0
    } else {
630
0
      zend_throw_error(NULL, "get_class() without arguments must be called from within a class");
631
0
      RETURN_THROWS();
632
0
    }
633
0
  }
634
635
75
  RETURN_STR_COPY(Z_OBJCE_P(obj)->name);
636
75
}
637
/* }}} */
638
639
/* {{{ Retrieves the "Late Static Binding" class name */
640
ZEND_FUNCTION(get_called_class)
641
8
{
642
8
  ZEND_PARSE_PARAMETERS_NONE();
643
644
0
  const zend_class_entry *called_scope = zend_get_called_scope(execute_data);
645
0
  if (!called_scope) {
646
0
    zend_throw_error(NULL, "get_called_class() must be called from within a class");
647
0
    RETURN_THROWS();
648
0
  }
649
650
0
  RETURN_STR_COPY(called_scope->name);
651
0
}
652
/* }}} */
653
654
/* {{{ Retrieves the parent class name for object or class or current scope or false if not in a scope. */
655
ZEND_FUNCTION(get_parent_class)
656
28
{
657
28
  zend_class_entry *ce = NULL;
658
659
84
  ZEND_PARSE_PARAMETERS_START(0, 1)
660
84
    Z_PARAM_OPTIONAL
661
101
    Z_PARAM_OBJ_OR_CLASS_NAME(ce)
662
101
  ZEND_PARSE_PARAMETERS_END();
663
664
28
  if (!ce) {
665
13
    zend_error(E_DEPRECATED, "Calling get_parent_class() without arguments is deprecated");
666
13
    if (UNEXPECTED(EG(exception))) {
667
0
      RETURN_THROWS();
668
0
    }
669
13
    ce = zend_get_executed_scope();
670
13
  }
671
672
28
  if (ce && ce->parent) {
673
16
    RETURN_STR_COPY(ce->parent->name);
674
16
  } else {
675
12
    RETURN_FALSE;
676
12
  }
677
28
}
678
/* }}} */
679
680
static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, bool only_subclass) /* {{{ */
681
191
{
682
191
  zval *obj;
683
191
  zend_string *class_name;
684
191
  const zend_class_entry *instance_ce;
685
191
  bool allow_string = only_subclass;
686
687
561
  ZEND_PARSE_PARAMETERS_START(2, 3)
688
716
    Z_PARAM_ZVAL(obj)
689
716
    Z_PARAM_STR(class_name)
690
179
    Z_PARAM_OPTIONAL
691
360
    Z_PARAM_BOOL(allow_string)
692
191
  ZEND_PARSE_PARAMETERS_END();
693
  /*
694
   * allow_string - is_a default is no, is_subclass_of is yes.
695
   *   if it's allowed, then the autoloader will be called if the class does not exist.
696
   *   default behaviour is different, as 'is_a' used to be used to test mixed return values
697
   *   and there is no easy way to deprecate this.
698
   */
699
700
179
  if (allow_string && Z_TYPE_P(obj) == IS_STRING) {
701
37
    instance_ce = zend_lookup_class(Z_STR_P(obj));
702
37
    if (!instance_ce) {
703
8
      RETURN_FALSE;
704
8
    }
705
142
  } else if (Z_TYPE_P(obj) == IS_OBJECT) {
706
140
    instance_ce = Z_OBJCE_P(obj);
707
140
  } else {
708
2
    RETURN_FALSE;
709
2
  }
710
711
169
  if (!only_subclass && EXPECTED(zend_string_equals(instance_ce->name, class_name))) {
712
11
    RETURN_TRUE;
713
11
  }
714
715
158
  const zend_class_entry *ce = zend_lookup_class_ex(class_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
716
158
  if (!ce) {
717
36
    RETURN_FALSE;
718
36
  }
719
720
122
  if (only_subclass && instance_ce == ce) {
721
40
    RETURN_FALSE;
722
40
  }
723
724
82
  RETURN_BOOL(instanceof_function(instance_ce, ce));
725
82
}
726
/* }}} */
727
728
/* {{{ Returns true if the object has this class as one of its parents */
729
ZEND_FUNCTION(is_subclass_of)
730
128
{
731
128
  is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
732
128
}
733
/* }}} */
734
735
/* {{{ Returns true if the first argument is an object and is this class or has this class as one of its parents, */
736
ZEND_FUNCTION(is_a)
737
63
{
738
63
  is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
739
63
}
740
/* }}} */
741
742
/* {{{ add_class_vars */
743
static void add_class_vars(const zend_class_entry *scope, zend_class_entry *ce, bool statics, const zval *return_value)
744
290
{
745
290
  zend_property_info *prop_info;
746
290
  zval *prop, prop_copy;
747
290
  zend_string *key;
748
290
  zval *default_properties_table = CE_DEFAULT_PROPERTIES_TABLE(ce);
749
750
2.59k
  ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
751
2.59k
    if (((prop_info->flags & ZEND_ACC_PROTECTED) &&
752
302
       !zend_check_protected(prop_info->ce, scope)) ||
753
884
      ((prop_info->flags & ZEND_ACC_PRIVATE) &&
754
368
        prop_info->ce != scope) ||
755
614
      (prop_info->flags & ZEND_ACC_VIRTUAL)) {
756
404
      continue;
757
404
    }
758
602
    prop = NULL;
759
602
    if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
760
160
      prop = &ce->default_static_members_table[prop_info->offset];
761
160
      ZVAL_DEINDIRECT(prop);
762
442
    } else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
763
141
      prop = &default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
764
141
    }
765
602
    if (!prop) {
766
301
      continue;
767
301
    }
768
769
301
    if (Z_ISUNDEF_P(prop)) {
770
      /* Return uninitialized typed properties as a null value */
771
24
      ZVAL_NULL(&prop_copy);
772
277
    } else {
773
      /* copy: enforce read only access */
774
277
      ZVAL_COPY_OR_DUP(&prop_copy, prop);
775
277
    }
776
301
    prop = &prop_copy;
777
778
    /* this is necessary to make it able to work with default array
779
     * properties, returned to user */
780
301
    if (Z_OPT_TYPE_P(prop) == IS_CONSTANT_AST) {
781
0
      if (UNEXPECTED(zval_update_constant_ex(prop, ce) != SUCCESS)) {
782
0
        return;
783
0
      }
784
0
    }
785
786
301
    zend_hash_add_new(Z_ARRVAL_P(return_value), key, prop);
787
301
  } ZEND_HASH_FOREACH_END();
788
290
}
789
/* }}} */
790
791
/* {{{ Returns an array of default properties of the class. */
792
ZEND_FUNCTION(get_class_vars)
793
151
{
794
151
  zend_class_entry *ce = NULL;
795
796
151
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "C", &ce) == FAILURE) {
797
6
    RETURN_THROWS();
798
6
  }
799
800
145
  array_init(return_value);
801
145
  if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
802
0
    if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
803
0
      return;
804
0
    }
805
0
  }
806
807
145
  const zend_class_entry *scope = zend_get_executed_scope();
808
145
  add_class_vars(scope, ce, false, return_value);
809
145
  add_class_vars(scope, ce, true, return_value);
810
145
}
811
/* }}} */
812
813
/* {{{ Returns an array of object properties */
814
ZEND_FUNCTION(get_object_vars)
815
289
{
816
289
  zval *value;
817
289
  HashTable *properties;
818
289
  zend_string *key;
819
289
  zend_object *zobj;
820
289
  zend_ulong num_key;
821
822
867
  ZEND_PARSE_PARAMETERS_START(1, 1)
823
1.15k
    Z_PARAM_OBJ(zobj)
824
289
  ZEND_PARSE_PARAMETERS_END();
825
826
284
  zval obj_zv;
827
284
  ZVAL_OBJ(&obj_zv, zobj);
828
284
  properties = zend_get_properties_for(&obj_zv, ZEND_PROP_PURPOSE_GET_OBJECT_VARS);
829
284
  if (properties == NULL) {
830
0
    RETURN_EMPTY_ARRAY();
831
0
  }
832
833
284
  if (!zobj->ce->default_properties_count && properties == zobj->properties && !GC_IS_RECURSIVE(properties)) {
834
    /* fast copy */
835
9
    bool always_duplicate = zobj->handlers != &std_object_handlers;
836
9
    RETVAL_ARR(zend_proptable_to_symtable(properties, always_duplicate));
837
275
  } else {
838
275
    array_init_size(return_value, zend_hash_num_elements(properties));
839
840
2.10k
    ZEND_HASH_FOREACH_KEY_VAL(properties, num_key, key, value) {
841
2.10k
      bool is_dynamic = 1;
842
2.10k
      zval tmp;
843
2.10k
      ZVAL_UNDEF(&tmp);
844
2.10k
      if (Z_TYPE_P(value) == IS_INDIRECT) {
845
305
        value = Z_INDIRECT_P(value);
846
305
        if (UNEXPECTED(Z_ISUNDEF_P(value))) {
847
4
          continue;
848
4
        }
849
850
301
        is_dynamic = 0;
851
608
      } else if (Z_TYPE_P(value) == IS_PTR) {
852
594
        is_dynamic = 0;
853
594
      }
854
855
909
      if (key && zend_check_property_access(zobj, key, is_dynamic) == FAILURE) {
856
270
        continue;
857
270
      }
858
859
639
      if (Z_ISREF_P(value) && Z_REFCOUNT_P(value) == 1) {
860
11
        value = Z_REFVAL_P(value);
861
11
      }
862
639
      if (Z_TYPE_P(value) == IS_PTR) {
863
        /* value is IS_PTR for properties with hooks. */
864
410
        zend_property_info *prop_info = Z_PTR_P(value);
865
410
        if ((prop_info->flags & ZEND_ACC_VIRTUAL) && !prop_info->hooks[ZEND_PROPERTY_HOOK_GET]) {
866
85
          continue;
867
85
        }
868
325
        const char *unmangled_name_cstr = zend_get_unmangled_property_name(prop_info->name);
869
325
        zend_string *unmangled_name = zend_string_init(unmangled_name_cstr, strlen(unmangled_name_cstr), false);
870
325
        value = zend_read_property_ex(prop_info->ce, zobj, unmangled_name, /* silent */ true, &tmp);
871
325
        zend_string_release_ex(unmangled_name, false);
872
325
        if (EG(exception)) {
873
3
          zend_release_properties(properties);
874
3
          zval_ptr_dtor(return_value);
875
3
          ZVAL_UNDEF(return_value);
876
3
          RETURN_THROWS();
877
3
        }
878
325
      }
879
551
      Z_TRY_ADDREF_P(value);
880
881
551
      if (UNEXPECTED(!key)) {
882
        /* This case is only possible due to loopholes, e.g. ArrayObject */
883
0
        zend_hash_index_add(Z_ARRVAL_P(return_value), num_key, value);
884
551
      } else if (!is_dynamic && ZSTR_VAL(key)[0] == 0) {
885
182
        const char *prop_name, *class_name;
886
182
        size_t prop_len;
887
182
        zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_len);
888
        /* We assume here that a mangled property name is never
889
         * numeric. This is probably a safe assumption, but
890
         * theoretically someone might write an extension with
891
         * private, numeric properties. Well, too bad.
892
         */
893
182
        zend_hash_str_add_new(Z_ARRVAL_P(return_value), prop_name, prop_len, value);
894
369
      } else {
895
369
        zend_symtable_add_new(Z_ARRVAL_P(return_value), key, value);
896
369
      }
897
551
      zval_ptr_dtor(&tmp);
898
551
    } ZEND_HASH_FOREACH_END();
899
275
  }
900
281
  zend_release_properties(properties);
901
281
}
902
/* }}} */
903
904
/* {{{ Returns an array of mangled object properties. Does not respect property visibility. */
905
ZEND_FUNCTION(get_mangled_object_vars)
906
95
{
907
95
  zend_object *obj;
908
95
  HashTable *properties;
909
910
285
  ZEND_PARSE_PARAMETERS_START(1, 1)
911
380
    Z_PARAM_OBJ(obj)
912
95
  ZEND_PARSE_PARAMETERS_END();
913
914
92
  properties = zend_get_properties_no_lazy_init(obj);
915
92
  if (!properties) {
916
0
    ZVAL_EMPTY_ARRAY(return_value);
917
0
    return;
918
0
  }
919
920
92
  properties = zend_proptable_to_symtable(properties,
921
92
    (obj->ce->default_properties_count ||
922
0
     obj->handlers != &std_object_handlers ||
923
0
     GC_IS_RECURSIVE(properties)));
924
92
  RETURN_ARR(properties);
925
92
}
926
/* }}} */
927
928
/* {{{ Returns an array of method names for class or class instance. */
929
ZEND_FUNCTION(get_class_methods)
930
106
{
931
106
  zval method_name;
932
106
  zend_class_entry *ce = NULL;
933
106
  zend_function *mptr;
934
935
318
  ZEND_PARSE_PARAMETERS_START(1, 1)
936
527
    Z_PARAM_OBJ_OR_CLASS_NAME(ce)
937
527
  ZEND_PARSE_PARAMETERS_END();
938
939
103
  array_init(return_value);
940
103
  const zend_class_entry *scope = zend_get_executed_scope();
941
942
1.00k
  ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, mptr) {
943
1.00k
    if (zend_check_method_accessible(mptr, scope)) {
944
299
      ZVAL_STR_COPY(&method_name, mptr->common.function_name);
945
299
      zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
946
299
    }
947
1.00k
  } ZEND_HASH_FOREACH_END();
948
103
}
949
/* }}} */
950
951
/* {{{ Checks if the class method exists */
952
ZEND_FUNCTION(method_exists)
953
270
{
954
270
  zval *klass;
955
270
  zend_string *method_name;
956
270
  zend_string *lcname;
957
270
  zend_class_entry *ce;
958
270
  zend_function *func;
959
960
  /* We do not use Z_PARAM_OBJ_OR_STR here to be able to exclude int, float, and bool which are bogus class names */
961
806
  ZEND_PARSE_PARAMETERS_START(2, 2)
962
1.06k
    Z_PARAM_ZVAL(klass)
963
1.06k
    Z_PARAM_STR(method_name)
964
270
  ZEND_PARSE_PARAMETERS_END();
965
966
266
  if (Z_TYPE_P(klass) == IS_OBJECT) {
967
157
    ce = Z_OBJCE_P(klass);
968
157
  } else if (Z_TYPE_P(klass) == IS_STRING) {
969
103
    if ((ce = zend_lookup_class(Z_STR_P(klass))) == NULL) {
970
6
      RETURN_FALSE;
971
6
    }
972
103
  } else {
973
6
    zend_argument_type_error(1, "must be of type object|string, %s given", zend_zval_value_name(klass));
974
6
    RETURN_THROWS();
975
6
  }
976
977
254
  lcname = zend_string_tolower(method_name);
978
254
  func = zend_hash_find_ptr(&ce->function_table, lcname);
979
254
  zend_string_release_ex(lcname, 0);
980
981
254
  if (func) {
982
    /* Exclude shadow properties when checking a method on a specific class. Include
983
     * them when checking an object, as method_exists() generally ignores visibility.
984
     * TODO: Should we use EG(scope) for the object case instead? */
985
101
    RETURN_BOOL(Z_TYPE_P(klass) == IS_OBJECT
986
101
      || !(func->common.fn_flags & ZEND_ACC_PRIVATE) || func->common.scope == ce);
987
101
  }
988
989
153
  if (Z_TYPE_P(klass) == IS_OBJECT) {
990
105
    zend_object *obj = Z_OBJ_P(klass);
991
105
    func = Z_OBJ_HT_P(klass)->get_method(&obj, method_name, NULL);
992
105
    if (func != NULL) {
993
85
      if (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
994
        /* Returns true for the fake Closure's __invoke */
995
34
        RETVAL_BOOL(func->common.scope == zend_ce_closure
996
34
          && zend_string_equals_literal_ci(method_name, ZEND_INVOKE_FUNC_NAME));
997
998
34
        zend_string_release_ex(func->common.function_name, 0);
999
34
        zend_free_trampoline(func);
1000
34
        return;
1001
34
      }
1002
51
      RETURN_TRUE;
1003
51
    }
1004
105
  } else {
1005
      /* Returns true for fake Closure::__invoke */
1006
48
      if (ce == zend_ce_closure
1007
39
          && zend_string_equals_literal_ci(method_name, ZEND_INVOKE_FUNC_NAME)) {
1008
21
          RETURN_TRUE;
1009
21
      }
1010
48
  }
1011
47
  RETURN_FALSE;
1012
47
}
1013
/* }}} */
1014
1015
static void _property_exists(zval *return_value, const zval *object, zend_string *property)
1016
367
{
1017
367
  zend_class_entry *ce;
1018
1019
367
  if (Z_TYPE_P(object) == IS_STRING) {
1020
220
    ce = zend_lookup_class(Z_STR_P(object));
1021
220
    if (!ce) {
1022
21
      RETURN_FALSE;
1023
21
    }
1024
220
  } else if (Z_TYPE_P(object) == IS_OBJECT) {
1025
112
    ce = Z_OBJCE_P(object);
1026
112
  } else {
1027
35
    zend_argument_type_error(1, "must be of type object|string, %s given", zend_zval_value_name(object));
1028
35
    RETURN_THROWS();
1029
35
  }
1030
1031
311
  const zend_property_info *property_info = zend_hash_find_ptr(&ce->properties_info, property);
1032
311
  if (property_info != NULL
1033
233
   && (!(property_info->flags & ZEND_ACC_PRIVATE)
1034
228
    || property_info->ce == ce)) {
1035
228
    RETURN_TRUE;
1036
228
  }
1037
1038
83
  RETURN_BOOL(
1039
83
    Z_TYPE_P(object) == IS_OBJECT &&
1040
83
    Z_OBJ_HANDLER_P(object, has_property)(Z_OBJ_P(object), property, ZEND_PROPERTY_EXISTS, NULL)
1041
83
  );
1042
83
}
1043
1044
/* {{{ Checks if the object or class has a property */
1045
ZEND_FUNCTION(property_exists)
1046
367
{
1047
367
  zval *object;
1048
367
  zend_string *property;
1049
1050
  /* We do not use Z_PARAM_OBJ_OR_STR here to be able to exclude int, float, and bool which are bogus class names */
1051
367
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &object, &property) == FAILURE) {
1052
0
    RETURN_THROWS();
1053
0
  }
1054
1055
367
  _property_exists(return_value, object, property);
1056
367
}
1057
/* }}} */
1058
1059
ZEND_FRAMELESS_FUNCTION(property_exists, 2)
1060
0
{
1061
0
  zval *object;
1062
0
  zval property_tmp;
1063
0
  zend_string *property;
1064
1065
0
  Z_FLF_PARAM_ZVAL(1, object);
1066
0
  Z_FLF_PARAM_STR(2, property, property_tmp);
1067
1068
0
  _property_exists(return_value, object, property);
1069
1070
0
flf_clean:;
1071
0
  Z_FLF_PARAM_FREE_STR(2, property_tmp)
1072
0
}
1073
1074
static zend_always_inline void _class_exists_impl(zval *return_value, zend_string *name, bool autoload, int flags, int skip_flags) /* {{{ */
1075
1.67k
{
1076
1.67k
  zend_string *lcname;
1077
1.67k
  const zend_class_entry *ce;
1078
1079
1.67k
  if (ZSTR_HAS_CE_CACHE(name)) {
1080
1.42k
    ce = ZSTR_GET_CE_CACHE(name);
1081
1.42k
    if (ce) {
1082
164
      RETURN_BOOL(((ce->ce_flags & flags) == flags) && !(ce->ce_flags & skip_flags));
1083
164
    }
1084
1.42k
  }
1085
1086
1.50k
  if (!autoload) {
1087
140
    if (ZSTR_VAL(name)[0] == '\\') {
1088
      /* Ignore leading "\" */
1089
0
      lcname = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
1090
0
      zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
1091
140
    } else {
1092
140
      lcname = zend_string_tolower(name);
1093
140
    }
1094
1095
140
    ce = zend_hash_find_ptr(EG(class_table), lcname);
1096
140
    zend_string_release_ex(lcname, 0);
1097
1.36k
  } else {
1098
1.36k
    ce = zend_lookup_class(name);
1099
1.36k
  }
1100
1101
1.50k
  RETURN_BOOL(ce && ((ce->ce_flags & flags) == flags) && !(ce->ce_flags & skip_flags));
1102
1.50k
}
1103
/* {{{ */
1104
1105
static inline void class_exists_impl(INTERNAL_FUNCTION_PARAMETERS, int flags, int skip_flags) /* {{{ */
1106
1.67k
{
1107
1.67k
  zend_string *name;
1108
1.67k
  bool autoload = true;
1109
1110
5.01k
  ZEND_PARSE_PARAMETERS_START(1, 2)
1111
6.68k
    Z_PARAM_STR(name)
1112
1.67k
    Z_PARAM_OPTIONAL
1113
3.78k
    Z_PARAM_BOOL(autoload)
1114
1.67k
  ZEND_PARSE_PARAMETERS_END();
1115
1116
1.67k
  _class_exists_impl(return_value, name, autoload, flags, skip_flags);
1117
1.67k
}
1118
1119
/* {{{ Checks if the class exists */
1120
ZEND_FUNCTION(class_exists)
1121
1.38k
{
1122
1.38k
  class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT);
1123
1.38k
}
1124
/* }}} */
1125
1126
ZEND_FRAMELESS_FUNCTION(class_exists, 1)
1127
0
{
1128
0
  zval name_tmp;
1129
0
  zend_string *name;
1130
1131
0
  Z_FLF_PARAM_STR(1, name, name_tmp);
1132
1133
0
  _class_exists_impl(return_value, name, /* autoload */ true, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT);
1134
1135
0
flf_clean:
1136
0
  Z_FLF_PARAM_FREE_STR(1, name_tmp);
1137
0
}
1138
1139
ZEND_FRAMELESS_FUNCTION(class_exists, 2)
1140
0
{
1141
0
  zval name_tmp;
1142
0
  zend_string *name;
1143
0
  bool autoload;
1144
1145
0
  Z_FLF_PARAM_STR(1, name, name_tmp);
1146
0
  Z_FLF_PARAM_BOOL(2, autoload);
1147
1148
0
  _class_exists_impl(return_value, name, autoload, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT);
1149
1150
0
flf_clean:
1151
0
  Z_FLF_PARAM_FREE_STR(1, name_tmp);
1152
0
}
1153
1154
/* {{{ Checks if the class exists */
1155
ZEND_FUNCTION(interface_exists)
1156
156
{
1157
156
  class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED|ZEND_ACC_INTERFACE, 0);
1158
156
}
1159
/* }}} */
1160
1161
/* {{{ Checks if the trait exists */
1162
ZEND_FUNCTION(trait_exists)
1163
53
{
1164
53
  class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT, 0);
1165
53
}
1166
/* }}} */
1167
1168
ZEND_FUNCTION(enum_exists)
1169
76
{
1170
76
  class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_ENUM, 0);
1171
76
}
1172
1173
/* {{{ Checks if the function exists */
1174
ZEND_FUNCTION(function_exists)
1175
47
{
1176
47
  zend_string *name;
1177
47
  bool exists;
1178
47
  zend_string *lcname;
1179
1180
141
  ZEND_PARSE_PARAMETERS_START(1, 1)
1181
188
    Z_PARAM_STR(name)
1182
47
  ZEND_PARSE_PARAMETERS_END();
1183
1184
47
  if (ZSTR_VAL(name)[0] == '\\') {
1185
    /* Ignore leading "\" */
1186
6
    lcname = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
1187
6
    zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
1188
41
  } else {
1189
41
    lcname = zend_string_tolower(name);
1190
41
  }
1191
1192
47
  exists = zend_hash_exists(EG(function_table), lcname);
1193
47
  zend_string_release_ex(lcname, 0);
1194
1195
47
  RETURN_BOOL(exists);
1196
47
}
1197
/* }}} */
1198
1199
/* {{{ Creates an alias for user defined class */
1200
ZEND_FUNCTION(class_alias)
1201
236
{
1202
236
  zend_string *class_name;
1203
236
  zend_string *alias_name;
1204
236
  zend_class_entry *ce;
1205
236
  bool autoload = 1;
1206
1207
706
  ZEND_PARSE_PARAMETERS_START(2, 3)
1208
936
    Z_PARAM_STR(class_name)
1209
1.17k
    Z_PARAM_STR(alias_name)
1210
234
    Z_PARAM_OPTIONAL
1211
480
    Z_PARAM_BOOL(autoload)
1212
236
  ZEND_PARSE_PARAMETERS_END();
1213
1214
234
  ce = zend_lookup_class_ex(class_name, NULL, !autoload ? ZEND_FETCH_CLASS_NO_AUTOLOAD : 0);
1215
1216
234
  if (ce) {
1217
205
    if (zend_register_class_alias_ex(ZSTR_VAL(alias_name), ZSTR_LEN(alias_name), ce, false) == SUCCESS) {
1218
174
      RETURN_TRUE;
1219
174
    } else {
1220
31
      zend_class_redeclaration_error_ex(E_WARNING, alias_name, ce);
1221
31
      RETURN_FALSE;
1222
31
    }
1223
205
  } else {
1224
29
    zend_error(E_WARNING, "Class \"%s\" not found", ZSTR_VAL(class_name));
1225
29
    RETURN_FALSE;
1226
29
  }
1227
234
}
1228
/* }}} */
1229
1230
/* {{{ Returns an array with the file names that were include_once()'d */
1231
ZEND_FUNCTION(get_included_files)
1232
50
{
1233
50
  zend_string *entry;
1234
1235
50
  ZEND_PARSE_PARAMETERS_NONE();
1236
1237
50
  array_init(return_value);
1238
110
  ZEND_HASH_MAP_FOREACH_STR_KEY(&EG(included_files), entry) {
1239
110
    if (entry) {
1240
5
      add_next_index_str(return_value, zend_string_copy(entry));
1241
5
    }
1242
110
  } ZEND_HASH_FOREACH_END();
1243
50
}
1244
/* }}} */
1245
1246
/* {{{ Generates a user-level error/warning/notice message */
1247
ZEND_FUNCTION(trigger_error)
1248
139
{
1249
139
  zend_long error_type = E_USER_NOTICE;
1250
139
  zend_string *message;
1251
1252
139
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &message, &error_type) == FAILURE) {
1253
0
    RETURN_THROWS();
1254
0
  }
1255
1256
139
  switch (error_type) {
1257
62
    case E_USER_ERROR:
1258
62
      zend_error(E_DEPRECATED, "Passing E_USER_ERROR to trigger_error() is deprecated since 8.4,"
1259
62
        " throw an exception or call exit with a string message instead");
1260
62
      if (UNEXPECTED(EG(exception))) {
1261
0
        RETURN_THROWS();
1262
0
      }
1263
109
    case E_USER_WARNING:
1264
124
    case E_USER_NOTICE:
1265
129
    case E_USER_DEPRECATED:
1266
129
      break;
1267
10
    default:
1268
10
      zend_argument_value_error(2, "must be one of E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE,"
1269
10
        " or E_USER_DEPRECATED");
1270
10
      RETURN_THROWS();
1271
0
      break;
1272
139
  }
1273
1274
129
  zend_error_zstr_at(error_type, zend_get_executed_filename_ex(), zend_get_executed_lineno(), message);
1275
  // TODO Change to void
1276
129
  RETURN_TRUE;
1277
129
}
1278
/* }}} */
1279
1280
/* {{{ Sets a user-defined error handler function.  Returns the previously defined error handler, or false on error */
1281
ZEND_FUNCTION(set_error_handler)
1282
0
{
1283
0
  zend_fcall_info fci;
1284
0
  zend_fcall_info_cache fcc;
1285
0
  zend_long error_type = E_ALL;
1286
1287
0
  ZEND_PARSE_PARAMETERS_START(1, 2)
1288
0
    Z_PARAM_FUNC_OR_NULL(fci, fcc)
1289
0
    Z_PARAM_OPTIONAL
1290
0
    Z_PARAM_LONG(error_type)
1291
0
  ZEND_PARSE_PARAMETERS_END();
1292
1293
0
  if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
1294
0
    ZVAL_COPY(return_value, &EG(user_error_handler));
1295
0
  }
1296
1297
0
  zend_stack_push(&EG(user_error_handlers_error_reporting), &EG(user_error_handler_error_reporting));
1298
0
  zend_stack_push(&EG(user_error_handlers), &EG(user_error_handler));
1299
1300
0
  if (!ZEND_FCI_INITIALIZED(fci)) { /* unset user-defined handler */
1301
0
    ZVAL_UNDEF(&EG(user_error_handler));
1302
0
    return;
1303
0
  }
1304
1305
0
  ZVAL_COPY(&EG(user_error_handler), &(fci.function_name));
1306
0
  EG(user_error_handler_error_reporting) = (int)error_type;
1307
0
}
1308
/* }}} */
1309
1310
/* {{{ Restores the previously defined error handler function */
1311
ZEND_FUNCTION(restore_error_handler)
1312
0
{
1313
0
  ZEND_PARSE_PARAMETERS_NONE();
1314
1315
0
  if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
1316
0
    zval zeh;
1317
1318
0
    ZVAL_COPY_VALUE(&zeh, &EG(user_error_handler));
1319
0
    ZVAL_UNDEF(&EG(user_error_handler));
1320
0
    zval_ptr_dtor(&zeh);
1321
0
  }
1322
1323
0
  if (zend_stack_is_empty(&EG(user_error_handlers))) {
1324
0
    ZVAL_UNDEF(&EG(user_error_handler));
1325
0
  } else {
1326
0
    zval *tmp;
1327
0
    EG(user_error_handler_error_reporting) = zend_stack_int_top(&EG(user_error_handlers_error_reporting));
1328
0
    zend_stack_del_top(&EG(user_error_handlers_error_reporting));
1329
0
    tmp = zend_stack_top(&EG(user_error_handlers));
1330
0
    ZVAL_COPY_VALUE(&EG(user_error_handler), tmp);
1331
0
    zend_stack_del_top(&EG(user_error_handlers));
1332
0
  }
1333
1334
  // TODO Change to void
1335
0
  RETURN_TRUE;
1336
0
}
1337
/* }}} */
1338
1339
ZEND_FUNCTION(get_error_handler)
1340
5
{
1341
5
  ZEND_PARSE_PARAMETERS_NONE();
1342
1343
5
  if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
1344
0
    RETURN_COPY(&EG(user_error_handler));
1345
0
  }
1346
5
}
1347
1348
/* {{{ Sets a user-defined exception handler function. Returns the previously defined exception handler, or false on error */
1349
ZEND_FUNCTION(set_exception_handler)
1350
220
{
1351
220
  zend_fcall_info fci;
1352
220
  zend_fcall_info_cache fcc;
1353
1354
660
  ZEND_PARSE_PARAMETERS_START(1, 1)
1355
880
    Z_PARAM_FUNC_OR_NULL(fci, fcc)
1356
220
  ZEND_PARSE_PARAMETERS_END();
1357
1358
202
  if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
1359
89
    ZVAL_COPY(return_value, &EG(user_exception_handler));
1360
89
  }
1361
1362
202
  zend_stack_push(&EG(user_exception_handlers), &EG(user_exception_handler));
1363
1364
202
  if (!ZEND_FCI_INITIALIZED(fci)) { /* unset user-defined handler */
1365
30
    ZVAL_UNDEF(&EG(user_exception_handler));
1366
30
    return;
1367
30
  }
1368
1369
172
  ZVAL_COPY(&EG(user_exception_handler), &(fci.function_name));
1370
172
}
1371
/* }}} */
1372
1373
/* {{{ Restores the previously defined exception handler function */
1374
ZEND_FUNCTION(restore_exception_handler)
1375
22
{
1376
22
  ZEND_PARSE_PARAMETERS_NONE();
1377
1378
22
  if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
1379
11
    zval_ptr_dtor(&EG(user_exception_handler));
1380
11
  }
1381
22
  if (zend_stack_is_empty(&EG(user_exception_handlers))) {
1382
0
    ZVAL_UNDEF(&EG(user_exception_handler));
1383
22
  } else {
1384
22
    zval *tmp = zend_stack_top(&EG(user_exception_handlers));
1385
22
    ZVAL_COPY_VALUE(&EG(user_exception_handler), tmp);
1386
22
    zend_stack_del_top(&EG(user_exception_handlers));
1387
22
  }
1388
1389
  // TODO Change to void
1390
22
  RETURN_TRUE;
1391
22
}
1392
/* }}} */
1393
1394
ZEND_FUNCTION(get_exception_handler)
1395
76
{
1396
76
  ZEND_PARSE_PARAMETERS_NONE();
1397
1398
76
  if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
1399
60
    RETURN_COPY(&EG(user_exception_handler));
1400
60
  }
1401
76
}
1402
1403
static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int flags) /* {{{ */
1404
68
{
1405
68
  zend_string *key;
1406
68
  zval *zv;
1407
1408
68
  ZEND_PARSE_PARAMETERS_NONE();
1409
1410
68
  array_init(return_value);
1411
68
  zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
1412
68
  ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
1413
24.0k
    ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) {
1414
24.0k
      const zend_class_entry *ce = Z_PTR_P(zv);
1415
24.0k
      if ((ce->ce_flags & (ZEND_ACC_LINKED|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT)) == flags
1416
7.15k
       && key
1417
7.15k
       && ZSTR_VAL(key)[0] != 0) {
1418
7.15k
        ZEND_HASH_FILL_GROW();
1419
7.15k
        if (EXPECTED(Z_TYPE_P(zv) == IS_PTR)) {
1420
7.13k
          ZEND_HASH_FILL_SET_STR_COPY(ce->name);
1421
7.13k
        } else {
1422
12
          ZEND_ASSERT(Z_TYPE_P(zv) == IS_ALIAS_PTR);
1423
12
          ZEND_HASH_FILL_SET_STR_COPY(key);
1424
12
        }
1425
7.15k
        ZEND_HASH_FILL_NEXT();
1426
7.15k
      }
1427
24.0k
    } ZEND_HASH_FOREACH_END();
1428
68
  } ZEND_HASH_FILL_END();
1429
68
}
1430
/* {{{ */
1431
1432
/* {{{ Returns an array of all declared traits. */
1433
ZEND_FUNCTION(get_declared_traits)
1434
22
{
1435
22
  get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED | ZEND_ACC_TRAIT);
1436
22
}
1437
/* }}} */
1438
1439
/* {{{ Returns an array of all declared classes. */
1440
ZEND_FUNCTION(get_declared_classes)
1441
46
{
1442
46
  get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED);
1443
46
}
1444
/* }}} */
1445
1446
/* {{{ Returns an array of all declared interfaces. */
1447
ZEND_FUNCTION(get_declared_interfaces)
1448
0
{
1449
0
  get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED | ZEND_ACC_INTERFACE);
1450
0
}
1451
/* }}} */
1452
1453
/* {{{ Returns an array of all defined functions */
1454
ZEND_FUNCTION(get_defined_functions)
1455
66
{
1456
66
  zval internal, user;
1457
66
  zend_string *key;
1458
66
  zend_function *func;
1459
66
  bool exclude_disabled = true;
1460
1461
66
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &exclude_disabled) == FAILURE) {
1462
0
    RETURN_THROWS();
1463
0
  }
1464
1465
66
  if (ZEND_NUM_ARGS() == 1) {
1466
29
    zend_error(E_DEPRECATED,
1467
29
      "get_defined_functions(): The $exclude_disabled parameter has no effect since PHP 8.0");
1468
29
  }
1469
1470
66
  array_init(&internal);
1471
66
  array_init(&user);
1472
66
  array_init(return_value);
1473
1474
91.4k
  ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(function_table), key, func) {
1475
91.4k
    if (key && ZSTR_VAL(key)[0] != 0) {
1476
45.6k
      if (func->type == ZEND_INTERNAL_FUNCTION) {
1477
45.6k
        add_next_index_str(&internal, zend_string_copy(key));
1478
45.6k
      } else if (func->type == ZEND_USER_FUNCTION) {
1479
32
        add_next_index_str(&user, zend_string_copy(key));
1480
32
      }
1481
45.6k
    }
1482
91.4k
  } ZEND_HASH_FOREACH_END();
1483
1484
66
  zend_hash_str_add_new(Z_ARRVAL_P(return_value), "internal", sizeof("internal")-1, &internal);
1485
66
  zend_hash_add_new(Z_ARRVAL_P(return_value), ZSTR_KNOWN(ZEND_STR_USER), &user);
1486
66
}
1487
/* }}} */
1488
1489
/* {{{ Returns an associative array of names and values of all currently defined variable names (variables in the current scope) */
1490
ZEND_FUNCTION(get_defined_vars)
1491
94
{
1492
94
  zend_array *symbol_table;
1493
1494
94
  ZEND_PARSE_PARAMETERS_NONE();
1495
1496
92
  if (zend_forbid_dynamic_call() == FAILURE) {
1497
12
    return;
1498
12
  }
1499
1500
80
  symbol_table = zend_rebuild_symbol_table();
1501
80
  if (UNEXPECTED(symbol_table == NULL)) {
1502
0
    RETURN_EMPTY_ARRAY();
1503
0
  }
1504
1505
80
  RETURN_ARR(zend_array_dup(symbol_table));
1506
80
}
1507
/* }}} */
1508
1509
#if ZEND_DEBUG && defined(ZTS)
1510
ZEND_FUNCTION(zend_thread_id)
1511
{
1512
  ZEND_PARSE_PARAMETERS_NONE();
1513
1514
  RETURN_LONG((zend_long)tsrm_thread_id());
1515
}
1516
#endif
1517
1518
/* {{{ Get the resource type name for a given resource */
1519
ZEND_FUNCTION(get_resource_type)
1520
0
{
1521
0
  const char *resource_type;
1522
0
  zval *z_resource_type;
1523
1524
0
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_resource_type) == FAILURE) {
1525
0
    RETURN_THROWS();
1526
0
  }
1527
1528
0
  resource_type = zend_rsrc_list_get_rsrc_type(Z_RES_P(z_resource_type));
1529
0
  if (resource_type) {
1530
0
    RETURN_STRING(resource_type);
1531
0
  } else {
1532
0
    RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_UNKNOWN_CAPITALIZED));
1533
0
  }
1534
0
}
1535
/* }}} */
1536
1537
/* {{{ Get the resource ID for a given resource */
1538
ZEND_FUNCTION(get_resource_id)
1539
0
{
1540
0
  zval *resource;
1541
1542
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
1543
0
    Z_PARAM_RESOURCE(resource)
1544
0
  ZEND_PARSE_PARAMETERS_END();
1545
1546
0
  RETURN_LONG(Z_RES_HANDLE_P(resource));
1547
0
}
1548
/* }}} */
1549
1550
/* {{{ Get an array with all active resources */
1551
ZEND_FUNCTION(get_resources)
1552
0
{
1553
0
  zend_string *type = NULL;
1554
0
  zend_string *key;
1555
0
  zend_ulong index;
1556
0
  zval *val;
1557
1558
0
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!", &type) == FAILURE) {
1559
0
    RETURN_THROWS();
1560
0
  }
1561
1562
0
  if (!type) {
1563
0
    array_init(return_value);
1564
0
    ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
1565
0
      if (!key) {
1566
0
        Z_ADDREF_P(val);
1567
0
        zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
1568
0
      }
1569
0
    } ZEND_HASH_FOREACH_END();
1570
0
  } else if (zend_string_equals_literal(type, "Unknown")) {
1571
0
    array_init(return_value);
1572
0
    ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
1573
0
      if (!key && Z_RES_TYPE_P(val) <= 0) {
1574
0
        Z_ADDREF_P(val);
1575
0
        zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
1576
0
      }
1577
0
    } ZEND_HASH_FOREACH_END();
1578
0
  } else {
1579
0
    int id = zend_fetch_list_dtor_id(ZSTR_VAL(type));
1580
1581
0
    if (id <= 0) {
1582
0
      zend_argument_value_error(1, "must be a valid resource type");
1583
0
      RETURN_THROWS();
1584
0
    }
1585
1586
0
    array_init(return_value);
1587
0
    ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
1588
0
      if (!key && Z_RES_TYPE_P(val) == id) {
1589
0
        Z_ADDREF_P(val);
1590
0
        zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
1591
0
      }
1592
0
    } ZEND_HASH_FOREACH_END();
1593
0
  }
1594
0
}
1595
/* }}} */
1596
1597
static void add_zendext_info(const zend_extension *ext, void *arg) /* {{{ */
1598
0
{
1599
0
  zval *name_array = (zval *)arg;
1600
0
  add_next_index_string(name_array, ext->name);
1601
0
}
1602
/* }}} */
1603
1604
/* {{{ Return an array containing names of loaded extensions */
1605
ZEND_FUNCTION(get_loaded_extensions)
1606
0
{
1607
0
  bool zendext = false;
1608
1609
0
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &zendext) == FAILURE) {
1610
0
    RETURN_THROWS();
1611
0
  }
1612
1613
0
  array_init(return_value);
1614
1615
0
  if (zendext) {
1616
0
    zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) add_zendext_info, return_value);
1617
0
  } else {
1618
0
    zend_module_entry *module;
1619
1620
0
    ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) {
1621
0
      add_next_index_string(return_value, module->name);
1622
0
    } ZEND_HASH_FOREACH_END();
1623
0
  }
1624
0
}
1625
/* }}} */
1626
1627
/* {{{ Return an array containing the names and values of all defined constants */
1628
ZEND_FUNCTION(get_defined_constants)
1629
15
{
1630
15
  bool categorize = false;
1631
1632
15
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &categorize) == FAILURE) {
1633
0
    RETURN_THROWS();
1634
0
  }
1635
1636
15
  array_init(return_value);
1637
1638
15
  if (categorize) {
1639
7
    zend_constant *val;
1640
7
    int module_number;
1641
7
    zval *modules, const_val;
1642
7
    char **module_names;
1643
7
    zend_module_entry *module;
1644
7
    int i = 1;
1645
1646
7
    modules = ecalloc(zend_hash_num_elements(&module_registry) + 2, sizeof(zval));
1647
7
    module_names = emalloc((zend_hash_num_elements(&module_registry) + 2) * sizeof(char *));
1648
1649
7
    module_names[0] = "internal";
1650
196
    ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) {
1651
196
      module_names[module->module_number] = (char *)module->name;
1652
196
      i++;
1653
196
    } ZEND_HASH_FOREACH_END();
1654
7
    module_names[i] = "user";
1655
1656
7.70k
    ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), val) {
1657
7.70k
      if (!val->name) {
1658
        /* skip special constants */
1659
0
        continue;
1660
0
      }
1661
1662
3.84k
      if (ZEND_CONSTANT_MODULE_NUMBER(val) == PHP_USER_CONSTANT) {
1663
0
        module_number = i;
1664
3.84k
      } else if (ZEND_CONSTANT_MODULE_NUMBER(val) > i) {
1665
        /* should not happen */
1666
0
        continue;
1667
3.84k
      } else {
1668
3.84k
        module_number = ZEND_CONSTANT_MODULE_NUMBER(val);
1669
3.84k
      }
1670
1671
3.84k
      if (Z_TYPE(modules[module_number]) == IS_UNDEF) {
1672
56
        array_init(&modules[module_number]);
1673
56
        add_assoc_zval(return_value, module_names[module_number], &modules[module_number]);
1674
56
      }
1675
1676
3.84k
      ZVAL_COPY_OR_DUP(&const_val, &val->value);
1677
3.84k
      zend_hash_add_new(Z_ARRVAL(modules[module_number]), val->name, &const_val);
1678
3.84k
    } ZEND_HASH_FOREACH_END();
1679
1680
7
    efree(module_names);
1681
7
    efree(modules);
1682
8
  } else {
1683
8
    zend_constant *constant;
1684
8
    zval const_val;
1685
1686
8.80k
    ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), constant) {
1687
8.80k
      if (!constant->name) {
1688
        /* skip special constants */
1689
0
        continue;
1690
0
      }
1691
4.39k
      ZVAL_COPY_OR_DUP(&const_val, &constant->value);
1692
4.39k
      zend_hash_add_new(Z_ARRVAL_P(return_value), constant->name, &const_val);
1693
4.39k
    } ZEND_HASH_FOREACH_END();
1694
8
  }
1695
15
}
1696
/* }}} */
1697
1698
static bool backtrace_is_arg_sensitive(const zend_execute_data *call, uint32_t offset)
1699
960k
{
1700
960k
  const zend_attribute *attribute = zend_get_parameter_attribute_str(
1701
960k
    call->func->common.attributes,
1702
960k
    "sensitiveparameter",
1703
960k
    sizeof("sensitiveparameter") - 1,
1704
960k
    offset
1705
960k
  );
1706
1707
960k
  return attribute != NULL;
1708
960k
}
1709
1710
static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) /* {{{ */
1711
683k
{
1712
683k
  uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
1713
1714
683k
  if (num_args) {
1715
550k
    uint32_t i = 0;
1716
550k
    zval *p = ZEND_CALL_ARG(call, 1);
1717
1718
550k
    array_init_size(arg_array, num_args);
1719
550k
    zend_hash_real_init_packed(Z_ARRVAL_P(arg_array));
1720
550k
    ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(arg_array)) {
1721
550k
      if (call->func->type == ZEND_USER_FUNCTION) {
1722
35.5k
        uint32_t first_extra_arg = MIN(num_args, call->func->op_array.num_args);
1723
1724
35.5k
        if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_SYMBOL_TABLE)) {
1725
          /* In case of attached symbol_table, values on stack may be invalid
1726
           * and we have to access them through symbol_table
1727
           * See: https://bugs.php.net/bug.php?id=73156
1728
           */
1729
2.18k
          while (i < first_extra_arg) {
1730
1.19k
            zend_string *arg_name = call->func->op_array.vars[i];
1731
1.19k
            zval original_arg;
1732
1.19k
            zval *arg = zend_hash_find_ex_ind(call->symbol_table, arg_name, 1);
1733
1.19k
            bool is_sensitive = backtrace_is_arg_sensitive(call, i);
1734
1735
1.19k
            if (arg) {
1736
1.19k
              ZVAL_DEREF(arg);
1737
1.19k
              ZVAL_COPY_VALUE(&original_arg, arg);
1738
1.19k
            } else {
1739
0
              ZVAL_NULL(&original_arg);
1740
0
            }
1741
1742
1.19k
            if (is_sensitive) {
1743
4
              zval redacted_arg;
1744
4
              object_init_with_constructor(&redacted_arg, zend_ce_sensitive_parameter_value, 1, &original_arg, NULL);
1745
4
              ZEND_HASH_FILL_SET(&redacted_arg);
1746
1.19k
            } else {
1747
1.19k
              Z_TRY_ADDREF_P(&original_arg);
1748
1.19k
              ZEND_HASH_FILL_SET(&original_arg);
1749
1.19k
            }
1750
1751
1.19k
            ZEND_HASH_FILL_NEXT();
1752
1.19k
            i++;
1753
1.19k
          }
1754
34.6k
        } else {
1755
73.2k
          while (i < first_extra_arg) {
1756
38.6k
            zval original_arg;
1757
38.6k
            bool is_sensitive = backtrace_is_arg_sensitive(call, i);
1758
1759
38.6k
            if (EXPECTED(Z_TYPE_INFO_P(p) != IS_UNDEF)) {
1760
38.4k
              zval *arg = p;
1761
38.4k
              ZVAL_DEREF(arg);
1762
38.4k
              ZVAL_COPY_VALUE(&original_arg, arg);
1763
38.4k
            } else {
1764
267
              ZVAL_NULL(&original_arg);
1765
267
            }
1766
1767
38.6k
            if (is_sensitive) {
1768
231
              zval redacted_arg;
1769
231
              object_init_with_constructor(&redacted_arg, zend_ce_sensitive_parameter_value, 1, &original_arg, NULL);
1770
231
              ZEND_HASH_FILL_SET(&redacted_arg);
1771
38.4k
            } else {
1772
38.4k
              Z_TRY_ADDREF_P(&original_arg);
1773
38.4k
              ZEND_HASH_FILL_SET(&original_arg);
1774
38.4k
            }
1775
1776
38.6k
            ZEND_HASH_FILL_NEXT();
1777
38.6k
            p++;
1778
38.6k
            i++;
1779
38.6k
          }
1780
34.6k
        }
1781
35.5k
        p = ZEND_CALL_VAR_NUM(call, call->func->op_array.last_var + call->func->op_array.T);
1782
35.5k
      }
1783
1784
1.58M
      while (i < num_args) {
1785
1.03M
        zval original_arg;
1786
1.03M
        bool is_sensitive = 0;
1787
1788
1.03M
        if (i < call->func->common.num_args || call->func->common.fn_flags & ZEND_ACC_VARIADIC) {
1789
920k
          is_sensitive = backtrace_is_arg_sensitive(call, MIN(i, call->func->common.num_args));
1790
920k
        }
1791
1792
1.03M
        if (EXPECTED(Z_TYPE_INFO_P(p) != IS_UNDEF)) {
1793
1.03M
          zval *arg = p;
1794
1.03M
          ZVAL_DEREF(arg);
1795
1.03M
          ZVAL_COPY_VALUE(&original_arg, arg);
1796
1.03M
        } else {
1797
35
          ZVAL_NULL(&original_arg);
1798
35
        }
1799
1800
1.03M
        if (is_sensitive) {
1801
76
          zval redacted_arg;
1802
76
          object_init_with_constructor(&redacted_arg, zend_ce_sensitive_parameter_value, 1, &original_arg, NULL);
1803
76
          ZEND_HASH_FILL_SET(&redacted_arg);
1804
1.03M
        } else {
1805
1.03M
          Z_TRY_ADDREF_P(&original_arg);
1806
1.03M
          ZEND_HASH_FILL_SET(&original_arg);
1807
1.03M
        }
1808
1809
1.03M
        ZEND_HASH_FILL_NEXT();
1810
1.03M
        p++;
1811
1.03M
        i++;
1812
1.03M
      }
1813
550k
    } ZEND_HASH_FILL_END();
1814
550k
    Z_ARRVAL_P(arg_array)->nNumOfElements = num_args;
1815
550k
  } else {
1816
133k
    ZVAL_EMPTY_ARRAY(arg_array);
1817
133k
  }
1818
1819
683k
  if ((ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)
1820
   /* __call and __callStatic are non-variadic, potentially with
1821
    * HAS_EXTRA_NAMED_PARAMS set. Don't add extra args, as they're already
1822
    * contained in the 2nd param. */
1823
134
   && (call->func->common.fn_flags & ZEND_ACC_VARIADIC)) {
1824
103
    zend_string *name;
1825
103
    zval *arg;
1826
1827
103
    bool is_sensitive = backtrace_is_arg_sensitive(call, call->func->common.num_args);
1828
1829
103
    SEPARATE_ARRAY(arg_array);
1830
510
    ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(call->extra_named_params, name, arg) {
1831
510
      ZVAL_DEREF(arg);
1832
510
      if (is_sensitive) {
1833
14
        zval redacted_arg;
1834
14
        object_init_with_constructor(&redacted_arg, zend_ce_sensitive_parameter_value, 1, arg, NULL);
1835
14
        zend_hash_add_new(Z_ARRVAL_P(arg_array), name, &redacted_arg);
1836
138
      } else {
1837
138
        Z_TRY_ADDREF_P(arg);
1838
138
        zend_hash_add_new(Z_ARRVAL_P(arg_array), name, arg);
1839
138
      }
1840
510
    } ZEND_HASH_FOREACH_END();
1841
103
  }
1842
683k
}
1843
/* }}} */
1844
1845
/* {{{ */
1846
ZEND_FUNCTION(debug_print_backtrace)
1847
354
{
1848
354
  zend_long options = 0;
1849
354
  zend_long limit = 0;
1850
354
  zval backtrace;
1851
1852
354
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) {
1853
0
    RETURN_THROWS();
1854
0
  }
1855
1856
354
  zend_fetch_debug_backtrace(&backtrace, 1, options, limit);
1857
354
  ZEND_ASSERT(Z_TYPE(backtrace) == IS_ARRAY);
1858
1859
354
  zend_string *str = zend_trace_to_string(Z_ARRVAL(backtrace), /* include_main */ false);
1860
354
  ZEND_WRITE(ZSTR_VAL(str), ZSTR_LEN(str));
1861
354
  zend_string_release(str);
1862
354
  zval_ptr_dtor(&backtrace);
1863
354
}
1864
1865
/* }}} */
1866
1867
ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit) /* {{{ */
1868
676k
{
1869
676k
  zend_execute_data *call, *last_call = NULL;
1870
676k
  zend_object *object;
1871
676k
  bool fake_frame = false;
1872
676k
  int frameno = 0;
1873
676k
  zend_function *func;
1874
676k
  zend_string *filename;
1875
676k
  zend_string *include_filename = NULL;
1876
676k
  zval tmp;
1877
676k
  HashTable *stack_frame, *prev_stack_frame = NULL;
1878
1879
676k
  array_init(return_value);
1880
1881
676k
  call = EG(current_execute_data);
1882
676k
  if (!call) {
1883
5.39k
    return;
1884
5.39k
  }
1885
1886
670k
  if (EG(filename_override)) {
1887
    // Add the current execution point to the frame so we don't lose it
1888
176
    zend_string *filename_override = EG(filename_override);
1889
176
    zend_long lineno_override = EG(lineno_override);
1890
176
    EG(filename_override) = NULL;
1891
176
    EG(lineno_override) = -1;
1892
1893
176
    zend_string *executed_filename = zend_get_executed_filename_ex();
1894
176
    uint32_t lineno = zend_get_executed_lineno();
1895
176
    if (executed_filename && (!zend_string_equals(executed_filename, filename_override) || lineno != lineno_override)) {
1896
162
      stack_frame = zend_new_array(8);
1897
162
      zend_hash_real_init_mixed(stack_frame);
1898
162
      ZVAL_STR_COPY(&tmp, executed_filename);
1899
162
      _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FILE), &tmp, 1);
1900
162
      ZVAL_LONG(&tmp, lineno);
1901
162
      _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_LINE), &tmp, 1);
1902
162
      ZVAL_STR_COPY(&tmp, ZSTR_KNOWN(ZEND_STR_CONST_EXPR_PLACEHOLDER));
1903
162
      _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp, 1);
1904
162
      ZVAL_ARR(&tmp, stack_frame);
1905
162
      zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
1906
162
    }
1907
1908
176
    EG(filename_override) = filename_override;
1909
176
    EG(lineno_override) = lineno_override;
1910
176
  }
1911
1912
670k
  if (skip_last) {
1913
    /* skip debug_backtrace() */
1914
712
    last_call = call;
1915
712
    call = call->prev_execute_data;
1916
712
  }
1917
1918
2.66M
  while (call && (limit == 0 || frameno < limit)) {
1919
2.14M
    if (UNEXPECTED(!call->func)) {
1920
      /* This is the fake frame inserted for nested generators. Normally,
1921
       * this frame is preceded by the actual generator frame and then
1922
       * replaced by zend_generator_check_placeholder_frame() below.
1923
       * However, the frame is popped before cleaning the stack frame,
1924
       * which is observable by destructors. */
1925
13
      call = zend_generator_check_placeholder_frame(call);
1926
13
      ZEND_ASSERT(call->func);
1927
13
    }
1928
1929
2.14M
    zend_execute_data *prev = call->prev_execute_data;
1930
1931
2.14M
    if (!prev) {
1932
      /* add frame for a handler call without {main} code */
1933
670k
      if (EXPECTED((ZEND_CALL_INFO(call) & ZEND_CALL_TOP_FUNCTION) == 0)) {
1934
156k
        break;
1935
156k
      }
1936
1.47M
    } else if (UNEXPECTED((ZEND_CALL_INFO(call) & ZEND_CALL_GENERATOR) != 0)) {
1937
561
      prev = zend_generator_check_placeholder_frame(prev);
1938
561
    }
1939
1940
    /* For frameless calls we add an additional frame for the call itself. */
1941
1.99M
    if (ZEND_USER_CODE(call->func->type)) {
1942
1.47M
      const zend_op *opline = call->opline;
1943
1.47M
      if (!ZEND_OP_IS_FRAMELESS_ICALL(opline->opcode)) {
1944
1.47M
        goto not_frameless_call;
1945
1.47M
      }
1946
0
      int num_args = ZEND_FLF_NUM_ARGS(opline->opcode);
1947
      /* Check if any args were already freed. Skip the frame in that case. */
1948
0
      if (num_args >= 1) {
1949
0
        zval *arg = zend_get_zval_ptr(opline, opline->op1_type, &opline->op1, call);
1950
0
        if (Z_TYPE_P(arg) == IS_UNDEF) goto not_frameless_call;
1951
0
      }
1952
0
      if (num_args >= 2) {
1953
0
        zval *arg = zend_get_zval_ptr(opline, opline->op2_type, &opline->op2, call);
1954
0
        if (Z_TYPE_P(arg) == IS_UNDEF) goto not_frameless_call;
1955
0
      }
1956
0
      if (num_args >= 3) {
1957
0
        const zend_op *op_data = opline + 1;
1958
0
        zval *arg = zend_get_zval_ptr(op_data, op_data->op1_type, &op_data->op1, call);
1959
0
        if (Z_TYPE_P(arg) == IS_UNDEF) goto not_frameless_call;
1960
0
      }
1961
0
      zend_function *frameless_func = ZEND_FLF_FUNC(opline);
1962
      /* Assume frameless functions are not recursive with themselves.
1963
       * This condition may be true when observers are enabled:
1964
       * Observers will put a call frame on top of the frameless opcode. */
1965
0
      if (last_call && last_call->func == frameless_func) {
1966
0
        goto not_frameless_call;
1967
0
      }
1968
0
      stack_frame = zend_new_array(8);
1969
0
      zend_hash_real_init_mixed(stack_frame);
1970
0
      ZVAL_STR_COPY(&tmp, frameless_func->common.function_name);
1971
0
      _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp, 1);
1972
      /* Steal file and line from the previous frame. */
1973
0
      if (call->func && ZEND_USER_CODE(call->func->common.type)) {
1974
0
        uint32_t lineno;
1975
1976
0
        filename = call->func->op_array.filename;
1977
0
        if (call->opline->opcode == ZEND_HANDLE_EXCEPTION) {
1978
0
          if (EG(opline_before_exception)) {
1979
0
            lineno = EG(opline_before_exception)->lineno;
1980
0
          } else {
1981
0
            lineno = call->func->op_array.line_end;
1982
0
          }
1983
0
        } else {
1984
0
          lineno = call->opline->lineno;
1985
0
        }
1986
0
        ZVAL_STR_COPY(&tmp, filename);
1987
0
        _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FILE), &tmp, 1);
1988
0
        ZVAL_LONG(&tmp, lineno);
1989
0
        _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_LINE), &tmp, 1);
1990
0
        if (prev_stack_frame) {
1991
0
          zend_hash_del(prev_stack_frame, ZSTR_KNOWN(ZEND_STR_FILE));
1992
0
          zend_hash_del(prev_stack_frame, ZSTR_KNOWN(ZEND_STR_LINE));
1993
0
        }
1994
0
      }
1995
0
      if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
1996
0
        HashTable *args = zend_new_array(8);
1997
0
        zend_hash_real_init_mixed(args);
1998
0
        if (num_args >= 1) {
1999
0
          zval *arg = zend_get_zval_ptr(opline, opline->op1_type, &opline->op1, call);
2000
0
          Z_TRY_ADDREF_P(arg);
2001
0
          zend_hash_next_index_insert_new(args, arg);
2002
0
        }
2003
0
        if (num_args >= 2) {
2004
0
          zval *arg = zend_get_zval_ptr(opline, opline->op2_type, &opline->op2, call);
2005
0
          Z_TRY_ADDREF_P(arg);
2006
0
          zend_hash_next_index_insert_new(args, arg);
2007
0
        }
2008
0
        if (num_args >= 3) {
2009
0
          const zend_op *op_data = opline + 1;
2010
0
          zval *arg = zend_get_zval_ptr(op_data, op_data->op1_type, &op_data->op1, call);
2011
0
          Z_TRY_ADDREF_P(arg);
2012
0
          zend_hash_next_index_insert_new(args, arg);
2013
0
        }
2014
0
        ZVAL_ARR(&tmp, args);
2015
0
        _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_ARGS), &tmp, 1);
2016
0
      }
2017
0
      ZVAL_ARR(&tmp, stack_frame);
2018
0
      zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
2019
0
    }
2020
1.99M
not_frameless_call:
2021
2022
    /* We use _zend_hash_append*() and the array must be preallocated */
2023
1.99M
    stack_frame = zend_new_array(8);
2024
1.99M
    zend_hash_real_init_mixed(stack_frame);
2025
2026
1.99M
    if (prev && prev->func && ZEND_USER_CODE(prev->func->common.type)) {
2027
1.41M
      uint32_t lineno;
2028
2029
1.41M
      filename = prev->func->op_array.filename;
2030
1.41M
      if (prev->opline->opcode == ZEND_HANDLE_EXCEPTION) {
2031
0
        if (EG(opline_before_exception)) {
2032
0
          lineno = EG(opline_before_exception)->lineno;
2033
0
        } else {
2034
0
          lineno = prev->func->op_array.line_end;
2035
0
        }
2036
1.41M
      } else {
2037
1.41M
        lineno = prev->opline->lineno;
2038
1.41M
      }
2039
1.41M
      ZVAL_STR_COPY(&tmp, filename);
2040
1.41M
      _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FILE), &tmp, 1);
2041
1.41M
      ZVAL_LONG(&tmp, lineno);
2042
1.41M
      _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_LINE), &tmp, 1);
2043
2044
      /* try to fetch args only if an FCALL was just made - elsewise we're in the middle of a function
2045
       * and debug_backtrace() might have been called by the error_handler. in this case we don't
2046
       * want to pop anything of the argument-stack */
2047
1.41M
    } else {
2048
579k
      zend_execute_data *prev_call = prev;
2049
2050
579k
      while (prev_call) {
2051
64.8k
        zend_execute_data *prev;
2052
2053
64.8k
        if (prev_call &&
2054
64.8k
          prev_call->func &&
2055
64.8k
          !ZEND_USER_CODE(prev_call->func->common.type) &&
2056
64.8k
          !(prev_call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
2057
64.8k
          break;
2058
64.8k
        }
2059
2060
30
        prev = prev_call->prev_execute_data;
2061
30
        if (prev && prev->func && ZEND_USER_CODE(prev->func->common.type)) {
2062
30
          ZVAL_STR_COPY(&tmp, prev->func->op_array.filename);
2063
30
          _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FILE), &tmp, 1);
2064
30
          ZVAL_LONG(&tmp, prev->opline->lineno);
2065
30
          _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_LINE), &tmp, 1);
2066
30
          break;
2067
30
        }
2068
0
        prev_call = prev;
2069
0
      }
2070
579k
      filename = NULL;
2071
579k
    }
2072
2073
1.99M
    func = call->func;
2074
1.99M
    if (!fake_frame && func->common.function_name) {
2075
683k
      ZVAL_STR_COPY(&tmp, func->common.function_name);
2076
683k
      _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp, 1);
2077
2078
683k
      if (Z_TYPE(call->This) == IS_OBJECT) {
2079
470k
        object = Z_OBJ(call->This);
2080
        /* $this may be passed into regular internal functions */
2081
470k
        if (func->common.scope) {
2082
470k
          ZVAL_STR_COPY(&tmp, func->common.scope->name);
2083
470k
        } else if (object->handlers->get_class_name == zend_std_get_class_name) {
2084
0
          ZVAL_STR_COPY(&tmp, object->ce->name);
2085
0
        } else {
2086
0
          ZVAL_STR(&tmp, object->handlers->get_class_name(object));
2087
0
        }
2088
470k
        _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_CLASS), &tmp, 1);
2089
470k
        if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) {
2090
217
          ZVAL_OBJ_COPY(&tmp, object);
2091
217
          _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_OBJECT), &tmp, 1);
2092
217
        }
2093
2094
470k
        ZVAL_INTERNED_STR(&tmp, ZSTR_KNOWN(ZEND_STR_OBJECT_OPERATOR));
2095
470k
        _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_TYPE), &tmp, 1);
2096
470k
      } else if (func->common.scope) {
2097
852
        ZVAL_STR_COPY(&tmp, func->common.scope->name);
2098
852
        _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_CLASS), &tmp, 1);
2099
852
        ZVAL_INTERNED_STR(&tmp, ZSTR_KNOWN(ZEND_STR_PAAMAYIM_NEKUDOTAYIM));
2100
852
        _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_TYPE), &tmp, 1);
2101
852
      }
2102
2103
683k
      if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 &&
2104
683k
        func->type != ZEND_EVAL_CODE) {
2105
2106
683k
        debug_backtrace_get_args(call, &tmp);
2107
683k
        _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_ARGS), &tmp, 1);
2108
683k
      }
2109
1.30M
    } else {
2110
      /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
2111
1.30M
      bool build_filename_arg = true;
2112
1.30M
      zend_string *pseudo_function_name;
2113
1.30M
      uint32_t include_kind = 0;
2114
1.30M
      if (prev && prev->func && ZEND_USER_CODE(prev->func->common.type) && prev->opline->opcode == ZEND_INCLUDE_OR_EVAL) {
2115
838k
        include_kind = prev->opline->extended_value;
2116
838k
      }
2117
2118
1.30M
      switch (include_kind) {
2119
871
        case ZEND_EVAL:
2120
871
          pseudo_function_name = ZSTR_KNOWN(ZEND_STR_EVAL);
2121
871
          build_filename_arg = false;
2122
871
          break;
2123
90
        case ZEND_INCLUDE:
2124
90
          pseudo_function_name = ZSTR_KNOWN(ZEND_STR_INCLUDE);
2125
90
          break;
2126
837k
        case ZEND_REQUIRE:
2127
837k
          pseudo_function_name = ZSTR_KNOWN(ZEND_STR_REQUIRE);
2128
837k
          break;
2129
7
        case ZEND_INCLUDE_ONCE:
2130
7
          pseudo_function_name = ZSTR_KNOWN(ZEND_STR_INCLUDE_ONCE);
2131
7
          break;
2132
30
        case ZEND_REQUIRE_ONCE:
2133
30
          pseudo_function_name = ZSTR_KNOWN(ZEND_STR_REQUIRE_ONCE);
2134
30
          break;
2135
470k
        default:
2136
          /* Skip dummy frame unless it is needed to preserve filename/lineno info. */
2137
470k
          if (!filename) {
2138
470k
            zend_array_destroy(stack_frame);
2139
470k
            goto skip_frame;
2140
470k
          }
2141
2142
0
          pseudo_function_name = ZSTR_KNOWN(ZEND_STR_UNKNOWN);
2143
0
          build_filename_arg = false;
2144
0
          break;
2145
1.30M
      }
2146
2147
838k
      if (build_filename_arg && include_filename) {
2148
837k
        zval arg_array;
2149
2150
837k
        array_init(&arg_array);
2151
2152
        /* include_filename always points to the last filename of the last last called-function.
2153
           if we have called include in the frame above - this is the file we have included.
2154
         */
2155
2156
837k
        ZVAL_STR_COPY(&tmp, include_filename);
2157
837k
        zend_hash_next_index_insert_new(Z_ARRVAL(arg_array), &tmp);
2158
837k
        _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_ARGS), &arg_array, 1);
2159
837k
      }
2160
2161
838k
      ZVAL_INTERNED_STR(&tmp, pseudo_function_name);
2162
838k
      _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp, 1);
2163
838k
    }
2164
2165
1.52M
    ZVAL_ARR(&tmp, stack_frame);
2166
1.52M
    zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
2167
1.52M
    frameno++;
2168
1.52M
    prev_stack_frame = stack_frame;
2169
2170
1.99M
skip_frame:
2171
1.99M
    if (UNEXPECTED(ZEND_CALL_KIND(call) == ZEND_CALL_TOP_FUNCTION)
2172
222k
     && !fake_frame
2173
222k
     && prev
2174
178k
     && prev->func
2175
178k
     && ZEND_USER_CODE(prev->func->common.type)
2176
114k
     && prev->opline->opcode == ZEND_INCLUDE_OR_EVAL) {
2177
139
      fake_frame = true;
2178
1.99M
    } else {
2179
1.99M
      fake_frame = false;
2180
1.99M
      include_filename = filename;
2181
1.99M
      last_call = call;
2182
1.99M
      call = prev;
2183
1.99M
    }
2184
1.99M
  }
2185
670k
}
2186
/* }}} */
2187
2188
/* {{{ Return backtrace as array */
2189
ZEND_FUNCTION(debug_backtrace)
2190
358
{
2191
358
  zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
2192
358
  zend_long limit = 0;
2193
2194
358
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) {
2195
0
    RETURN_THROWS();
2196
0
  }
2197
2198
358
  zend_fetch_debug_backtrace(return_value, 1, options, limit);
2199
358
}
2200
/* }}} */
2201
2202
/* {{{ Returns true if the named extension is loaded */
2203
ZEND_FUNCTION(extension_loaded)
2204
0
{
2205
0
  zend_string *extension_name;
2206
0
  zend_string *lcname;
2207
2208
0
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &extension_name) == FAILURE) {
2209
0
    RETURN_THROWS();
2210
0
  }
2211
2212
0
  lcname = zend_string_tolower(extension_name);
2213
0
  RETVAL_BOOL(zend_hash_exists(&module_registry, lcname));
2214
0
  zend_string_release_ex(lcname, 0);
2215
0
}
2216
/* }}} */
2217
2218
/* {{{ Returns an array with the names of functions belonging to the named extension */
2219
ZEND_FUNCTION(get_extension_funcs)
2220
20
{
2221
20
  zend_string *extension_name;
2222
20
  zend_string *lcname;
2223
20
  bool array;
2224
20
  zend_module_entry *module;
2225
20
  zend_function *zif;
2226
2227
20
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &extension_name) == FAILURE) {
2228
0
    RETURN_THROWS();
2229
0
  }
2230
20
  if (strncasecmp(ZSTR_VAL(extension_name), "zend", sizeof("zend"))) {
2231
20
    lcname = zend_string_tolower(extension_name);
2232
20
    module = zend_hash_find_ptr(&module_registry, lcname);
2233
20
    zend_string_release_ex(lcname, 0);
2234
20
  } else {
2235
0
    module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core") - 1);
2236
0
  }
2237
2238
20
  if (!module) {
2239
13
    RETURN_FALSE;
2240
13
  }
2241
2242
7
  if (module->functions) {
2243
    /* avoid BC break, if functions list is empty, will return an empty array */
2244
7
    array_init(return_value);
2245
7
    array = true;
2246
7
  } else {
2247
0
    array = false;
2248
0
  }
2249
2250
9.68k
  ZEND_HASH_MAP_FOREACH_PTR(CG(function_table), zif) {
2251
9.68k
    if (zif->common.type == ZEND_INTERNAL_FUNCTION
2252
4.83k
      && zif->internal_function.module == module) {
2253
3.60k
      if (!array) {
2254
0
        array_init(return_value);
2255
0
        array = true;
2256
0
      }
2257
3.60k
      add_next_index_str(return_value, zend_string_copy(zif->common.function_name));
2258
3.60k
    }
2259
9.68k
  } ZEND_HASH_FOREACH_END();
2260
2261
7
  if (!array) {
2262
0
    RETURN_FALSE;
2263
0
  }
2264
7
}
2265
/* }}} */