Coverage Report

Created: 2025-06-13 06:43

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