Coverage Report

Created: 2025-06-13 06:43

/src/php-src/Zend/zend_compile.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
   |          Nikita Popov <nikic@php.net>                                |
18
   +----------------------------------------------------------------------+
19
*/
20
21
#include <zend_language_parser.h>
22
#include "zend.h"
23
#include "zend_ast.h"
24
#include "zend_attributes.h"
25
#include "zend_compile.h"
26
#include "zend_constants.h"
27
#include "zend_llist.h"
28
#include "zend_API.h"
29
#include "zend_exceptions.h"
30
#include "zend_interfaces.h"
31
#include "zend_virtual_cwd.h"
32
#include "zend_multibyte.h"
33
#include "zend_language_scanner.h"
34
#include "zend_inheritance.h"
35
#include "zend_vm.h"
36
#include "zend_enum.h"
37
#include "zend_observer.h"
38
#include "zend_call_stack.h"
39
#include "zend_frameless_function.h"
40
#include "zend_property_hooks.h"
41
42
6.87M
#define SET_NODE(target, src) do { \
43
6.87M
    target ## _type = (src)->op_type; \
44
6.87M
    if ((src)->op_type == IS_CONST) { \
45
1.44M
      target.constant = zend_add_literal(&(src)->u.constant); \
46
5.42M
    } else { \
47
5.42M
      target = (src)->u.op; \
48
5.42M
    } \
49
6.87M
  } while (0)
50
51
3.15M
#define GET_NODE(target, src) do { \
52
3.15M
    (target)->op_type = src ## _type; \
53
3.15M
    if ((target)->op_type == IS_CONST) { \
54
92
      ZVAL_COPY_VALUE(&(target)->u.constant, CT_CONSTANT(src)); \
55
3.15M
    } else { \
56
3.15M
      (target)->u.op = src; \
57
3.15M
    } \
58
3.15M
  } while (0)
59
60
7.27M
#define FC(member) (CG(file_context).member)
61
62
typedef struct _zend_loop_var {
63
  uint8_t opcode;
64
  uint8_t var_type;
65
  uint32_t   var_num;
66
  uint32_t   try_catch_offset;
67
} zend_loop_var;
68
69
879k
static inline uint32_t zend_alloc_cache_slots(unsigned count) {
70
879k
  if (count == 0) {
71
    /* Even if no cache slots are desired, the VM handler may still want to acquire
72
     * CACHE_ADDR() unconditionally. Returning zero makes sure that the address
73
     * calculation is still legal and ubsan does not complain. */
74
0
    return 0;
75
0
  }
76
77
879k
  zend_op_array *op_array = CG(active_op_array);
78
879k
  uint32_t ret = op_array->cache_size;
79
879k
  op_array->cache_size += count * sizeof(void*);
80
879k
  return ret;
81
879k
}
82
83
646k
static inline uint32_t zend_alloc_cache_slot(void) {
84
646k
  return zend_alloc_cache_slots(1);
85
646k
}
86
87
ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type);
88
ZEND_API zend_op_array *(*zend_compile_string)(zend_string *source_string, const char *filename, zend_compile_position position);
89
90
#ifndef ZTS
91
ZEND_API zend_compiler_globals compiler_globals;
92
ZEND_API zend_executor_globals executor_globals;
93
#endif
94
95
static zend_op *zend_emit_op(znode *result, uint8_t opcode, znode *op1, znode *op2);
96
static bool zend_try_ct_eval_array(zval *result, zend_ast *ast);
97
static void zend_eval_const_expr(zend_ast **ast_ptr);
98
99
static zend_op *zend_compile_var(znode *result, zend_ast *ast, uint32_t type, bool by_ref);
100
static zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type, bool by_ref);
101
static void zend_compile_expr(znode *result, zend_ast *ast);
102
static void zend_compile_stmt(zend_ast *ast);
103
static void zend_compile_assign(znode *result, zend_ast *ast);
104
105
#ifdef ZEND_CHECK_STACK_LIMIT
106
zend_never_inline static void zend_stack_limit_error(void)
107
0
{
108
0
  size_t max_stack_size = 0;
109
0
  if ((uintptr_t) EG(stack_base) > (uintptr_t) EG(stack_limit)) {
110
0
    max_stack_size = (size_t) ((uintptr_t) EG(stack_base) - (uintptr_t) EG(stack_limit));
111
0
  }
112
113
0
  zend_error_noreturn(E_COMPILE_ERROR,
114
0
    "Maximum call stack size of %zu bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached during compilation. Try splitting expression",
115
0
    max_stack_size);
116
0
}
117
118
static void zend_check_stack_limit(void)
119
9.79M
{
120
9.79M
  if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {
121
0
    zend_stack_limit_error();
122
0
  }
123
9.79M
}
124
#else /* ZEND_CHECK_STACK_LIMIT */
125
static void zend_check_stack_limit(void)
126
{
127
}
128
#endif /* ZEND_CHECK_STACK_LIMIT */
129
130
static void init_op(zend_op *op)
131
6.97M
{
132
6.97M
  MAKE_NOP(op);
133
6.97M
  op->extended_value = 0;
134
6.97M
  op->lineno = CG(zend_lineno);
135
#ifdef ZEND_VERIFY_TYPE_INFERENCE
136
  op->op1_use_type = 0;
137
  op->op2_use_type = 0;
138
  op->result_use_type = 0;
139
  op->op1_def_type = 0;
140
  op->op2_def_type = 0;
141
  op->result_def_type = 0;
142
#endif
143
6.97M
}
144
145
static zend_always_inline uint32_t get_next_op_number(void)
146
1.50M
{
147
1.50M
  return CG(active_op_array)->last;
148
1.50M
}
149
150
static zend_op *get_next_op(void)
151
6.69M
{
152
6.69M
  zend_op_array *op_array = CG(active_op_array);
153
6.69M
  uint32_t next_op_num = op_array->last++;
154
6.69M
  zend_op *next_op;
155
156
6.69M
  if (UNEXPECTED(next_op_num >= CG(context).opcodes_size)) {
157
13.2k
    CG(context).opcodes_size *= 4;
158
13.2k
    op_array->opcodes = erealloc(op_array->opcodes, CG(context).opcodes_size * sizeof(zend_op));
159
13.2k
  }
160
161
6.69M
  next_op = &(op_array->opcodes[next_op_num]);
162
163
6.69M
  init_op(next_op);
164
165
6.69M
  return next_op;
166
6.69M
}
167
168
static zend_brk_cont_element *get_next_brk_cont_element(void)
169
40.8k
{
170
40.8k
  CG(context).last_brk_cont++;
171
40.8k
  CG(context).brk_cont_array = erealloc(CG(context).brk_cont_array, sizeof(zend_brk_cont_element) * CG(context).last_brk_cont);
172
40.8k
  return &CG(context).brk_cont_array[CG(context).last_brk_cont-1];
173
40.8k
}
174
175
static zend_string *zend_build_runtime_definition_key(zend_string *name, uint32_t start_lineno) /* {{{ */
176
27.0k
{
177
27.0k
  zend_string *filename = CG(active_op_array)->filename;
178
27.0k
  zend_string *result = zend_strpprintf(0, "%c%s%s:%" PRIu32 "$%" PRIx32,
179
27.0k
    '\0', ZSTR_VAL(name), ZSTR_VAL(filename), start_lineno, CG(rtd_key_counter)++);
180
27.0k
  return zend_new_interned_string(result);
181
27.0k
}
182
/* }}} */
183
184
static bool zend_get_unqualified_name(const zend_string *name, const char **result, size_t *result_len) /* {{{ */
185
666k
{
186
666k
  const char *ns_separator = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
187
666k
  if (ns_separator != NULL) {
188
153k
    *result = ns_separator + 1;
189
153k
    *result_len = ZSTR_VAL(name) + ZSTR_LEN(name) - *result;
190
153k
    return 1;
191
153k
  }
192
193
512k
  return 0;
194
666k
}
195
/* }}} */
196
197
struct reserved_class_name {
198
  const char *name;
199
  size_t len;
200
};
201
static const struct reserved_class_name reserved_class_names[] = {
202
  {ZEND_STRL("bool")},
203
  {ZEND_STRL("false")},
204
  {ZEND_STRL("float")},
205
  {ZEND_STRL("int")},
206
  {ZEND_STRL("null")},
207
  {ZEND_STRL("parent")},
208
  {ZEND_STRL("self")},
209
  {ZEND_STRL("static")},
210
  {ZEND_STRL("string")},
211
  {ZEND_STRL("true")},
212
  {ZEND_STRL("void")},
213
  {ZEND_STRL("never")},
214
  {ZEND_STRL("iterable")},
215
  {ZEND_STRL("object")},
216
  {ZEND_STRL("mixed")},
217
  /* These are not usable as class names because they're proper tokens,
218
   * but they are here for class aliases. */
219
  {ZEND_STRL("array")},
220
  {ZEND_STRL("callable")},
221
  {NULL, 0}
222
};
223
224
static bool zend_is_reserved_class_name(const zend_string *name) /* {{{ */
225
100k
{
226
100k
  const struct reserved_class_name *reserved = reserved_class_names;
227
228
100k
  const char *uqname = ZSTR_VAL(name);
229
100k
  size_t uqname_len = ZSTR_LEN(name);
230
100k
  zend_get_unqualified_name(name, &uqname, &uqname_len);
231
232
1.80M
  for (; reserved->name; ++reserved) {
233
1.70M
    if (uqname_len == reserved->len
234
1.70M
      && zend_binary_strcasecmp(uqname, uqname_len, reserved->name, reserved->len) == 0
235
1.70M
    ) {
236
124
      return 1;
237
124
    }
238
1.70M
  }
239
240
100k
  return 0;
241
100k
}
242
/* }}} */
243
244
void zend_assert_valid_class_name(const zend_string *name, const char *type) /* {{{ */
245
98.4k
{
246
98.4k
  if (zend_is_reserved_class_name(name)) {
247
98
    zend_error_noreturn(E_COMPILE_ERROR,
248
98
      "Cannot use \"%s\" as %s as it is reserved", ZSTR_VAL(name), type);
249
98
  }
250
98.3k
  if (zend_string_equals_literal(name, "_")) {
251
250
    zend_error(E_DEPRECATED, "Using \"_\" as %s is deprecated since 8.4", type);
252
250
  }
253
98.3k
}
254
/* }}} */
255
256
typedef struct _builtin_type_info {
257
  const char* name;
258
  const size_t name_len;
259
  const uint8_t type;
260
} builtin_type_info;
261
262
static const builtin_type_info builtin_types[] = {
263
  {ZEND_STRL("null"), IS_NULL},
264
  {ZEND_STRL("true"), IS_TRUE},
265
  {ZEND_STRL("false"), IS_FALSE},
266
  {ZEND_STRL("int"), IS_LONG},
267
  {ZEND_STRL("float"), IS_DOUBLE},
268
  {ZEND_STRL("string"), IS_STRING},
269
  {ZEND_STRL("bool"), _IS_BOOL},
270
  {ZEND_STRL("void"), IS_VOID},
271
  {ZEND_STRL("never"), IS_NEVER},
272
  {ZEND_STRL("iterable"), IS_ITERABLE},
273
  {ZEND_STRL("object"), IS_OBJECT},
274
  {ZEND_STRL("mixed"), IS_MIXED},
275
  {NULL, 0, IS_UNDEF}
276
};
277
278
typedef struct {
279
  const char *name;
280
  size_t name_len;
281
  const char *correct_name;
282
} confusable_type_info;
283
284
static const confusable_type_info confusable_types[] = {
285
  {ZEND_STRL("boolean"), "bool"},
286
  {ZEND_STRL("integer"), "int"},
287
  {ZEND_STRL("double"), "float"},
288
  {ZEND_STRL("resource"), NULL},
289
  {NULL, 0, NULL},
290
};
291
292
static zend_always_inline uint8_t zend_lookup_builtin_type_by_name(const zend_string *name) /* {{{ */
293
69.4k
{
294
69.4k
  const builtin_type_info *info = &builtin_types[0];
295
296
734k
  for (; info->name; ++info) {
297
690k
    if (ZSTR_LEN(name) == info->name_len
298
690k
      && zend_binary_strcasecmp(ZSTR_VAL(name), ZSTR_LEN(name), info->name, info->name_len) == 0
299
690k
    ) {
300
26.0k
      return info->type;
301
26.0k
    }
302
690k
  }
303
304
43.4k
  return 0;
305
69.4k
}
306
/* }}} */
307
308
static zend_always_inline bool zend_is_confusable_type(const zend_string *name, const char **correct_name) /* {{{ */
309
43.0k
{
310
43.0k
  const confusable_type_info *info = confusable_types;
311
312
  /* Intentionally using case-sensitive comparison here, because "integer" is likely intended
313
   * as a scalar type, while "Integer" is likely a class type. */
314
214k
  for (; info->name; ++info) {
315
171k
    if (zend_string_equals_cstr(name, info->name, info->name_len)) {
316
519
      *correct_name = info->correct_name;
317
519
      return 1;
318
519
    }
319
171k
  }
320
321
42.5k
  return 0;
322
43.0k
}
323
/* }}} */
324
325
519
static bool zend_is_not_imported(zend_string *name) {
326
  /* Assuming "name" is unqualified here. */
327
519
  return !FC(imports) || zend_hash_find_ptr_lc(FC(imports), name) == NULL;
328
519
}
329
330
void zend_oparray_context_begin(zend_oparray_context *prev_context, zend_op_array *op_array) /* {{{ */
331
198k
{
332
198k
  *prev_context = CG(context);
333
198k
  CG(context).prev = CG(context).op_array ? prev_context : NULL;
334
198k
  CG(context).op_array = op_array;
335
198k
  CG(context).opcodes_size = INITIAL_OP_ARRAY_SIZE;
336
198k
  CG(context).vars_size = 0;
337
198k
  CG(context).literals_size = 0;
338
198k
  CG(context).fast_call_var = -1;
339
198k
  CG(context).try_catch_offset = -1;
340
198k
  CG(context).current_brk_cont = -1;
341
198k
  CG(context).last_brk_cont = 0;
342
198k
  CG(context).brk_cont_array = NULL;
343
198k
  CG(context).labels = NULL;
344
198k
  CG(context).in_jmp_frameless_branch = false;
345
198k
  CG(context).active_property_info_name = NULL;
346
198k
  CG(context).active_property_hook_kind = (zend_property_hook_kind)-1;
347
198k
}
348
/* }}} */
349
350
void zend_oparray_context_end(zend_oparray_context *prev_context) /* {{{ */
351
189k
{
352
189k
  if (CG(context).brk_cont_array) {
353
24.7k
    efree(CG(context).brk_cont_array);
354
24.7k
    CG(context).brk_cont_array = NULL;
355
24.7k
  }
356
189k
  if (CG(context).labels) {
357
785
    zend_hash_destroy(CG(context).labels);
358
785
    FREE_HASHTABLE(CG(context).labels);
359
785
    CG(context).labels = NULL;
360
785
  }
361
189k
  CG(context) = *prev_context;
362
189k
}
363
/* }}} */
364
365
static void zend_reset_import_tables(void) /* {{{ */
366
104k
{
367
104k
  if (FC(imports)) {
368
1.18k
    zend_hash_destroy(FC(imports));
369
1.18k
    efree(FC(imports));
370
1.18k
    FC(imports) = NULL;
371
1.18k
  }
372
373
104k
  if (FC(imports_function)) {
374
313
    zend_hash_destroy(FC(imports_function));
375
313
    efree(FC(imports_function));
376
313
    FC(imports_function) = NULL;
377
313
  }
378
379
104k
  if (FC(imports_const)) {
380
180
    zend_hash_destroy(FC(imports_const));
381
180
    efree(FC(imports_const));
382
180
    FC(imports_const) = NULL;
383
180
  }
384
385
104k
  zend_hash_clean(&FC(seen_symbols));
386
104k
}
387
/* }}} */
388
389
99.4k
static void zend_end_namespace(void) /* {{{ */ {
390
99.4k
  FC(in_namespace) = 0;
391
99.4k
  zend_reset_import_tables();
392
99.4k
  if (FC(current_namespace)) {
393
3.36k
    zend_string_release_ex(FC(current_namespace), 0);
394
3.36k
    FC(current_namespace) = NULL;
395
3.36k
  }
396
99.4k
}
397
/* }}} */
398
399
void zend_file_context_begin(zend_file_context *prev_context) /* {{{ */
400
103k
{
401
103k
  *prev_context = CG(file_context);
402
103k
  FC(imports) = NULL;
403
103k
  FC(imports_function) = NULL;
404
103k
  FC(imports_const) = NULL;
405
103k
  FC(current_namespace) = NULL;
406
103k
  FC(in_namespace) = 0;
407
103k
  FC(has_bracketed_namespaces) = 0;
408
103k
  FC(declarables).ticks = 0;
409
103k
  zend_hash_init(&FC(seen_symbols), 8, NULL, NULL, 0);
410
103k
}
411
/* }}} */
412
413
void zend_file_context_end(zend_file_context *prev_context) /* {{{ */
414
97.3k
{
415
97.3k
  zend_end_namespace();
416
97.3k
  zend_hash_destroy(&FC(seen_symbols));
417
97.3k
  CG(file_context) = *prev_context;
418
97.3k
}
419
/* }}} */
420
421
void zend_init_compiler_data_structures(void) /* {{{ */
422
306k
{
423
306k
  zend_stack_init(&CG(loop_var_stack), sizeof(zend_loop_var));
424
306k
  zend_stack_init(&CG(delayed_oplines_stack), sizeof(zend_op));
425
306k
  zend_stack_init(&CG(short_circuiting_opnums), sizeof(uint32_t));
426
306k
  CG(active_class_entry) = NULL;
427
306k
  CG(in_compilation) = 0;
428
306k
  CG(skip_shebang) = 0;
429
430
306k
  CG(encoding_declared) = 0;
431
306k
  CG(memoized_exprs) = NULL;
432
306k
  CG(memoize_mode) = ZEND_MEMOIZE_NONE;
433
306k
}
434
/* }}} */
435
436
117k
static void zend_register_seen_symbol(zend_string *name, uint32_t kind) {
437
117k
  zval *zv = zend_hash_find(&FC(seen_symbols), name);
438
117k
  if (zv) {
439
35.0k
    Z_LVAL_P(zv) |= kind;
440
82.2k
  } else {
441
82.2k
    zval tmp;
442
82.2k
    ZVAL_LONG(&tmp, kind);
443
82.2k
    zend_hash_add_new(&FC(seen_symbols), name, &tmp);
444
82.2k
  }
445
117k
}
446
447
2.72k
static bool zend_have_seen_symbol(zend_string *name, uint32_t kind) {
448
2.72k
  zval *zv = zend_hash_find(&FC(seen_symbols), name);
449
2.72k
  return zv && (Z_LVAL_P(zv) & kind) != 0;
450
2.72k
}
451
452
void init_compiler(void) /* {{{ */
453
300k
{
454
300k
  CG(arena) = zend_arena_create(64 * 1024);
455
300k
  CG(active_op_array) = NULL;
456
300k
  memset(&CG(context), 0, sizeof(CG(context)));
457
300k
  zend_init_compiler_data_structures();
458
300k
  zend_init_rsrc_list();
459
300k
  zend_stream_init();
460
300k
  CG(unclean_shutdown) = 0;
461
462
300k
  CG(delayed_variance_obligations) = NULL;
463
300k
  CG(delayed_autoloads) = NULL;
464
300k
  CG(unlinked_uses) = NULL;
465
300k
  CG(current_linking_class) = NULL;
466
300k
}
467
/* }}} */
468
469
void shutdown_compiler(void) /* {{{ */
470
306k
{
471
  /* Reset filename before destroying the arena, as file cache may use arena allocated strings. */
472
306k
  zend_restore_compiled_filename(NULL);
473
474
306k
  zend_stack_destroy(&CG(loop_var_stack));
475
306k
  zend_stack_destroy(&CG(delayed_oplines_stack));
476
306k
  zend_stack_destroy(&CG(short_circuiting_opnums));
477
478
306k
  if (CG(delayed_variance_obligations)) {
479
228
    zend_hash_destroy(CG(delayed_variance_obligations));
480
228
    FREE_HASHTABLE(CG(delayed_variance_obligations));
481
228
    CG(delayed_variance_obligations) = NULL;
482
228
  }
483
306k
  if (CG(delayed_autoloads)) {
484
230
    zend_hash_destroy(CG(delayed_autoloads));
485
230
    FREE_HASHTABLE(CG(delayed_autoloads));
486
230
    CG(delayed_autoloads) = NULL;
487
230
  }
488
306k
  if (CG(unlinked_uses)) {
489
251
    zend_hash_destroy(CG(unlinked_uses));
490
251
    FREE_HASHTABLE(CG(unlinked_uses));
491
251
    CG(unlinked_uses) = NULL;
492
251
  }
493
306k
  CG(current_linking_class) = NULL;
494
306k
}
495
/* }}} */
496
497
ZEND_API zend_string *zend_set_compiled_filename(zend_string *new_compiled_filename) /* {{{ */
498
171k
{
499
171k
  CG(compiled_filename) = zend_string_copy(new_compiled_filename);
500
171k
  return new_compiled_filename;
501
171k
}
502
/* }}} */
503
504
ZEND_API void zend_restore_compiled_filename(zend_string *original_compiled_filename) /* {{{ */
505
637k
{
506
637k
  if (CG(compiled_filename)) {
507
171k
    zend_string_release(CG(compiled_filename));
508
171k
    CG(compiled_filename) = NULL;
509
171k
  }
510
637k
  CG(compiled_filename) = original_compiled_filename;
511
637k
}
512
/* }}} */
513
514
ZEND_API zend_string *zend_get_compiled_filename(void) /* {{{ */
515
634k
{
516
634k
  return CG(compiled_filename);
517
634k
}
518
/* }}} */
519
520
ZEND_API int zend_get_compiled_lineno(void) /* {{{ */
521
221k
{
522
221k
  return CG(zend_lineno);
523
221k
}
524
/* }}} */
525
526
ZEND_API bool zend_is_compiling(void) /* {{{ */
527
3.93M
{
528
3.93M
  return CG(in_compilation);
529
3.93M
}
530
/* }}} */
531
532
static zend_always_inline uint32_t get_temporary_variable(void) /* {{{ */
533
3.41M
{
534
3.41M
  return (uint32_t)CG(active_op_array)->T++;
535
3.41M
}
536
/* }}} */
537
538
1.38M
static int lookup_cv(zend_string *name) /* {{{ */{
539
1.38M
  zend_op_array *op_array = CG(active_op_array);
540
1.38M
  int i = 0;
541
1.38M
  zend_ulong hash_value = zend_string_hash_val(name);
542
543
7.56M
  while (i < op_array->last_var) {
544
6.94M
    if (ZSTR_H(op_array->vars[i]) == hash_value
545
6.94M
     && zend_string_equals(op_array->vars[i], name)) {
546
760k
      return EX_NUM_TO_VAR(i);
547
760k
    }
548
6.18M
    i++;
549
6.18M
  }
550
621k
  i = op_array->last_var;
551
621k
  op_array->last_var++;
552
621k
  if (op_array->last_var > CG(context).vars_size) {
553
127k
    CG(context).vars_size += 16; /* FIXME */
554
127k
    op_array->vars = erealloc(op_array->vars, CG(context).vars_size * sizeof(zend_string*));
555
127k
  }
556
557
621k
  op_array->vars[i] = zend_string_copy(name);
558
621k
  return EX_NUM_TO_VAR(i);
559
1.38M
}
560
/* }}} */
561
562
zend_string *zval_make_interned_string(zval *zv)
563
3.55M
{
564
3.55M
  ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
565
3.55M
  Z_STR_P(zv) = zend_new_interned_string(Z_STR_P(zv));
566
3.55M
  if (ZSTR_IS_INTERNED(Z_STR_P(zv))) {
567
3.37M
    Z_TYPE_FLAGS_P(zv) = 0;
568
3.37M
  }
569
3.55M
  return Z_STR_P(zv);
570
3.55M
}
571
572
/* Common part of zend_add_literal and zend_append_individual_literal */
573
static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int literal_position) /* {{{ */
574
2.79M
{
575
2.79M
  zval *lit = CT_CONSTANT_EX(op_array, literal_position);
576
2.79M
  if (Z_TYPE_P(zv) == IS_STRING) {
577
2.33M
    zval_make_interned_string(zv);
578
2.33M
  }
579
2.79M
  ZVAL_COPY_VALUE(lit, zv);
580
2.79M
  Z_EXTRA_P(lit) = 0;
581
2.79M
}
582
/* }}} */
583
584
/* Is used while compiling a function, using the context to keep track
585
   of an approximate size to avoid to relocate to often.
586
   Literals are truncated to actual size in the second compiler pass (pass_two()). */
587
static int zend_add_literal(zval *zv) /* {{{ */
588
2.79M
{
589
2.79M
  zend_op_array *op_array = CG(active_op_array);
590
2.79M
  int i = op_array->last_literal;
591
2.79M
  op_array->last_literal++;
592
2.79M
  if (i >= CG(context).literals_size) {
593
608k
    while (i >= CG(context).literals_size) {
594
304k
      CG(context).literals_size += 16; /* FIXME */
595
304k
    }
596
304k
    op_array->literals = (zval*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zval));
597
304k
  }
598
2.79M
  zend_insert_literal(op_array, zv, i);
599
2.79M
  return i;
600
2.79M
}
601
/* }}} */
602
603
static inline int zend_add_literal_string(zend_string **str) /* {{{ */
604
1.32M
{
605
1.32M
  int ret;
606
1.32M
  zval zv;
607
1.32M
  ZVAL_STR(&zv, *str);
608
1.32M
  ret = zend_add_literal(&zv);
609
1.32M
  *str = Z_STR(zv);
610
1.32M
  return ret;
611
1.32M
}
612
/* }}} */
613
614
static int zend_add_func_name_literal(zend_string *name) /* {{{ */
615
109k
{
616
  /* Original name */
617
109k
  int ret = zend_add_literal_string(&name);
618
619
  /* Lowercased name */
620
109k
  zend_string *lc_name = zend_string_tolower(name);
621
109k
  zend_add_literal_string(&lc_name);
622
623
109k
  return ret;
624
109k
}
625
/* }}} */
626
627
static int zend_add_ns_func_name_literal(zend_string *name) /* {{{ */
628
16.5k
{
629
16.5k
  const char *unqualified_name;
630
16.5k
  size_t unqualified_name_len;
631
632
  /* Original name */
633
16.5k
  int ret = zend_add_literal_string(&name);
634
635
  /* Lowercased name */
636
16.5k
  zend_string *lc_name = zend_string_tolower(name);
637
16.5k
  zend_add_literal_string(&lc_name);
638
639
  /* Lowercased unqualified name */
640
16.5k
  if (zend_get_unqualified_name(name, &unqualified_name, &unqualified_name_len)) {
641
16.5k
    lc_name = zend_string_alloc(unqualified_name_len, 0);
642
16.5k
    zend_str_tolower_copy(ZSTR_VAL(lc_name), unqualified_name, unqualified_name_len);
643
16.5k
    zend_add_literal_string(&lc_name);
644
16.5k
  }
645
646
16.5k
  return ret;
647
16.5k
}
648
/* }}} */
649
650
static int zend_add_class_name_literal(zend_string *name) /* {{{ */
651
162k
{
652
  /* Original name */
653
162k
  int ret = zend_add_literal_string(&name);
654
655
  /* Lowercased name */
656
162k
  zend_string *lc_name = zend_string_tolower(name);
657
162k
  zend_add_literal_string(&lc_name);
658
659
162k
  return ret;
660
162k
}
661
/* }}} */
662
663
static int zend_add_const_name_literal(zend_string *name, bool unqualified) /* {{{ */
664
292k
{
665
292k
  zend_string *tmp_name;
666
667
292k
  int ret = zend_add_literal_string(&name);
668
669
292k
  size_t ns_len = 0, after_ns_len = ZSTR_LEN(name);
670
292k
  const char *after_ns = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
671
292k
  if (after_ns) {
672
82.4k
    after_ns += 1;
673
82.4k
    ns_len = after_ns - ZSTR_VAL(name) - 1;
674
82.4k
    after_ns_len = ZSTR_LEN(name) - ns_len - 1;
675
676
    /* lowercased namespace name & original constant name */
677
82.4k
    tmp_name = zend_string_init(ZSTR_VAL(name), ZSTR_LEN(name), 0);
678
82.4k
    zend_str_tolower(ZSTR_VAL(tmp_name), ns_len);
679
82.4k
    zend_add_literal_string(&tmp_name);
680
681
82.4k
    if (!unqualified) {
682
1.81k
      return ret;
683
1.81k
    }
684
209k
  } else {
685
209k
    after_ns = ZSTR_VAL(name);
686
209k
  }
687
688
  /* original unqualified constant name */
689
290k
  tmp_name = zend_string_init(after_ns, after_ns_len, 0);
690
290k
  zend_add_literal_string(&tmp_name);
691
692
290k
  return ret;
693
292k
}
694
/* }}} */
695
696
15.0k
#define LITERAL_STR(op, str) do { \
697
15.0k
    zval _c; \
698
15.0k
    ZVAL_STR(&_c, str); \
699
15.0k
    op.constant = zend_add_literal(&_c); \
700
15.0k
  } while (0)
701
702
void zend_stop_lexing(void)
703
60
{
704
60
  if (LANG_SCNG(on_event)) {
705
0
    LANG_SCNG(on_event)(ON_STOP, END, 0, NULL, 0, LANG_SCNG(on_event_context));
706
0
  }
707
708
60
  LANG_SCNG(yy_cursor) = LANG_SCNG(yy_limit);
709
60
}
710
711
static inline void zend_begin_loop(
712
    uint8_t free_opcode, const znode *loop_var, bool is_switch) /* {{{ */
713
40.8k
{
714
40.8k
  zend_brk_cont_element *brk_cont_element;
715
40.8k
  int parent = CG(context).current_brk_cont;
716
40.8k
  zend_loop_var info = {0};
717
718
40.8k
  CG(context).current_brk_cont = CG(context).last_brk_cont;
719
40.8k
  brk_cont_element = get_next_brk_cont_element();
720
40.8k
  brk_cont_element->parent = parent;
721
40.8k
  brk_cont_element->is_switch = is_switch;
722
723
40.8k
  if (loop_var && (loop_var->op_type & (IS_VAR|IS_TMP_VAR))) {
724
19.2k
    uint32_t start = get_next_op_number();
725
726
19.2k
    info.opcode = free_opcode;
727
19.2k
    info.var_type = loop_var->op_type;
728
19.2k
    info.var_num = loop_var->u.op.var;
729
19.2k
    brk_cont_element->start = start;
730
21.6k
  } else {
731
21.6k
    info.opcode = ZEND_NOP;
732
    /* The start field is used to free temporary variables in case of exceptions.
733
     * We won't try to free something of we don't have loop variable.  */
734
21.6k
    brk_cont_element->start = -1;
735
21.6k
  }
736
737
40.8k
  zend_stack_push(&CG(loop_var_stack), &info);
738
40.8k
}
739
/* }}} */
740
741
static inline void zend_end_loop(int cont_addr, const znode *var_node) /* {{{ */
742
40.6k
{
743
40.6k
  uint32_t end = get_next_op_number();
744
40.6k
  zend_brk_cont_element *brk_cont_element
745
40.6k
    = &CG(context).brk_cont_array[CG(context).current_brk_cont];
746
40.6k
  brk_cont_element->cont = cont_addr;
747
40.6k
  brk_cont_element->brk = end;
748
40.6k
  CG(context).current_brk_cont = brk_cont_element->parent;
749
750
40.6k
  zend_stack_del_top(&CG(loop_var_stack));
751
40.6k
}
752
/* }}} */
753
754
static void zend_do_free(znode *op1) /* {{{ */
755
650k
{
756
650k
  if (op1->op_type == IS_TMP_VAR) {
757
300k
    zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
758
759
327k
    while (opline->opcode == ZEND_END_SILENCE ||
760
327k
           opline->opcode == ZEND_OP_DATA) {
761
26.9k
      opline--;
762
26.9k
    }
763
764
300k
    if (opline->result_type == IS_TMP_VAR && opline->result.var == op1->u.op.var) {
765
297k
      switch (opline->opcode) {
766
1.26k
        case ZEND_BOOL:
767
6.45k
        case ZEND_BOOL_NOT:
768
          /* boolean results don't have to be freed */
769
6.45k
          return;
770
339
        case ZEND_POST_INC_STATIC_PROP:
771
444
        case ZEND_POST_DEC_STATIC_PROP:
772
885
        case ZEND_POST_INC_OBJ:
773
1.16k
        case ZEND_POST_DEC_OBJ:
774
6.02k
        case ZEND_POST_INC:
775
6.64k
        case ZEND_POST_DEC:
776
          /* convert $i++ to ++$i */
777
6.64k
          opline->opcode -= 2;
778
6.64k
          SET_UNUSED(opline->result);
779
6.64k
          return;
780
127k
        case ZEND_ASSIGN:
781
138k
        case ZEND_ASSIGN_DIM:
782
147k
        case ZEND_ASSIGN_OBJ:
783
148k
        case ZEND_ASSIGN_STATIC_PROP:
784
198k
        case ZEND_ASSIGN_OP:
785
200k
        case ZEND_ASSIGN_DIM_OP:
786
201k
        case ZEND_ASSIGN_OBJ_OP:
787
201k
        case ZEND_ASSIGN_STATIC_PROP_OP:
788
201k
        case ZEND_PRE_INC_STATIC_PROP:
789
201k
        case ZEND_PRE_DEC_STATIC_PROP:
790
202k
        case ZEND_PRE_INC_OBJ:
791
202k
        case ZEND_PRE_DEC_OBJ:
792
205k
        case ZEND_PRE_INC:
793
206k
        case ZEND_PRE_DEC:
794
206k
          SET_UNUSED(opline->result);
795
206k
          return;
796
297k
      }
797
297k
    }
798
799
81.5k
    zend_emit_op(NULL, ZEND_FREE, op1, NULL);
800
349k
  } else if (op1->op_type == IS_VAR) {
801
264k
    zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
802
267k
    while (opline->opcode == ZEND_END_SILENCE ||
803
267k
        opline->opcode == ZEND_EXT_FCALL_END ||
804
267k
        opline->opcode == ZEND_OP_DATA) {
805
2.78k
      opline--;
806
2.78k
    }
807
264k
    if (opline->result_type == IS_VAR
808
264k
      && opline->result.var == op1->u.op.var) {
809
242k
      if (opline->opcode == ZEND_FETCH_THIS) {
810
0
        opline->opcode = ZEND_NOP;
811
0
      }
812
242k
      if (!ZEND_OP_IS_FRAMELESS_ICALL(opline->opcode)) {
813
240k
        SET_UNUSED(opline->result);
814
240k
      } else {
815
        /* Frameless calls usually use the return value, so always emit a free. This should be
816
         * faster than checking RETURN_VALUE_USED inside the handler. */
817
        // FIXME: We may actually look at the function signature to determine whether a free
818
        // is necessary.
819
2.26k
        zend_emit_op(NULL, ZEND_FREE, op1, NULL);
820
2.26k
      }
821
242k
    } else {
822
75.6k
      while (opline >= CG(active_op_array)->opcodes) {
823
75.6k
        if ((opline->opcode == ZEND_FETCH_LIST_R ||
824
75.6k
             opline->opcode == ZEND_FETCH_LIST_W) &&
825
75.6k
            opline->op1_type == IS_VAR &&
826
75.6k
            opline->op1.var == op1->u.op.var) {
827
6.49k
          zend_emit_op(NULL, ZEND_FREE, op1, NULL);
828
6.49k
          return;
829
6.49k
        }
830
69.1k
        if (opline->result_type == IS_VAR
831
69.1k
          && opline->result.var == op1->u.op.var) {
832
14.8k
          if (opline->opcode == ZEND_NEW) {
833
14.8k
            zend_emit_op(NULL, ZEND_FREE, op1, NULL);
834
14.8k
          }
835
14.8k
          break;
836
14.8k
        }
837
54.3k
        opline--;
838
54.3k
      }
839
21.3k
    }
840
264k
  } else if (op1->op_type == IS_CONST) {
841
    /* Destroy value without using GC: When opcache moves arrays into SHM it will
842
     * free the zend_array structure, so references to it from outside the op array
843
     * become invalid. GC would cause such a reference in the root buffer. */
844
81.4k
    zval_ptr_dtor_nogc(&op1->u.constant);
845
81.4k
  }
846
650k
}
847
/* }}} */
848
849
850
static const char *zend_modifier_token_to_string(uint32_t token)
851
134
{
852
134
  switch (token) {
853
6
    case T_PUBLIC:
854
6
      return "public";
855
7
    case T_PROTECTED:
856
7
      return "protected";
857
3
    case T_PRIVATE:
858
3
      return "private";
859
26
    case T_STATIC:
860
26
      return "static";
861
33
    case T_FINAL:
862
33
      return "final";
863
35
    case T_READONLY:
864
35
      return "readonly";
865
16
    case T_ABSTRACT:
866
16
      return "abstract";
867
1
    case T_PUBLIC_SET:
868
1
      return "public(set)";
869
1
    case T_PROTECTED_SET:
870
1
      return "protected(set)";
871
6
    case T_PRIVATE_SET:
872
6
      return "private(set)";
873
134
    EMPTY_SWITCH_DEFAULT_CASE()
874
134
  }
875
134
}
876
877
uint32_t zend_modifier_token_to_flag(zend_modifier_target target, uint32_t token)
878
67.6k
{
879
67.6k
  switch (token) {
880
43.0k
    case T_PUBLIC:
881
43.0k
      if (target != ZEND_MODIFIER_TARGET_PROPERTY_HOOK) {
882
43.0k
        return ZEND_ACC_PUBLIC;
883
43.0k
      }
884
6
      break;
885
2.22k
    case T_PROTECTED:
886
2.22k
      if (target != ZEND_MODIFIER_TARGET_PROPERTY_HOOK) {
887
2.22k
        return ZEND_ACC_PROTECTED;
888
2.22k
      }
889
7
      break;
890
5.94k
    case T_PRIVATE:
891
5.94k
      if (target != ZEND_MODIFIER_TARGET_PROPERTY_HOOK) {
892
5.93k
        return ZEND_ACC_PRIVATE;
893
5.93k
      }
894
3
      break;
895
1.25k
    case T_READONLY:
896
1.25k
      if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
897
1.23k
        return ZEND_ACC_READONLY;
898
1.23k
      }
899
19
      break;
900
1.69k
    case T_ABSTRACT:
901
1.69k
      if (target == ZEND_MODIFIER_TARGET_METHOD || target == ZEND_MODIFIER_TARGET_PROPERTY) {
902
1.68k
        return ZEND_ACC_ABSTRACT;
903
1.68k
      }
904
4
      break;
905
1.72k
    case T_FINAL:
906
1.72k
      if (target == ZEND_MODIFIER_TARGET_METHOD
907
1.72k
        || target == ZEND_MODIFIER_TARGET_CONSTANT
908
1.72k
        || target == ZEND_MODIFIER_TARGET_PROPERTY
909
1.72k
        || target == ZEND_MODIFIER_TARGET_PROPERTY_HOOK) {
910
1.71k
        return ZEND_ACC_FINAL;
911
1.71k
      }
912
12
      break;
913
10.5k
    case T_STATIC:
914
10.5k
      if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_METHOD) {
915
10.5k
        return ZEND_ACC_STATIC;
916
10.5k
      }
917
12
      break;
918
243
    case T_PUBLIC_SET:
919
243
      if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
920
242
        return ZEND_ACC_PUBLIC_SET;
921
242
      }
922
1
      break;
923
366
    case T_PROTECTED_SET:
924
366
      if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
925
365
        return ZEND_ACC_PROTECTED_SET;
926
365
      }
927
1
      break;
928
568
    case T_PRIVATE_SET:
929
568
      if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
930
562
        return ZEND_ACC_PRIVATE_SET;
931
562
      }
932
6
      break;
933
67.6k
  }
934
935
71
  char *member;
936
71
  if (target == ZEND_MODIFIER_TARGET_PROPERTY) {
937
0
    member = "property";
938
71
  } else if (target == ZEND_MODIFIER_TARGET_METHOD) {
939
18
    member = "method";
940
53
  } else if (target == ZEND_MODIFIER_TARGET_CONSTANT) {
941
7
    member = "class constant";
942
46
  } else if (target == ZEND_MODIFIER_TARGET_CPP) {
943
20
    member = "parameter";
944
26
  } else if (target == ZEND_MODIFIER_TARGET_PROPERTY_HOOK) {
945
26
    member = "property hook";
946
26
  } else {
947
0
    ZEND_UNREACHABLE();
948
0
  }
949
950
71
  zend_throw_exception_ex(zend_ce_compile_error, 0,
951
71
    "Cannot use the %s modifier on a %s", zend_modifier_token_to_string(token), member);
952
71
  return 0;
953
71
}
954
955
uint32_t zend_modifier_list_to_flags(zend_modifier_target target, zend_ast *modifiers)
956
57.6k
{
957
57.6k
  uint32_t flags = 0;
958
57.6k
  zend_ast_list *modifier_list = zend_ast_get_list(modifiers);
959
960
124k
  for (uint32_t i = 0; i < modifier_list->children; i++) {
961
67.0k
    uint32_t token = (uint32_t) Z_LVAL_P(zend_ast_get_zval(modifier_list->child[i]));
962
67.0k
    uint32_t new_flag = zend_modifier_token_to_flag(target, token);
963
67.0k
    if (!new_flag) {
964
64
      return 0;
965
64
    }
966
    /* Don't error immediately for duplicate flags, we want to prioritize the errors from zend_add_member_modifier(). */
967
66.9k
    bool duplicate_flag = (flags & new_flag);
968
66.9k
    flags = zend_add_member_modifier(flags, new_flag, target);
969
66.9k
    if (!flags) {
970
81
      return 0;
971
81
    }
972
66.9k
    if (duplicate_flag) {
973
63
      zend_throw_exception_ex(zend_ce_compile_error, 0,
974
63
        "Multiple %s modifiers are not allowed", zend_modifier_token_to_string(token));
975
63
      return 0;
976
63
    }
977
66.9k
  }
978
979
57.4k
  return flags;
980
57.6k
}
981
982
uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
983
174
{
984
174
  uint32_t new_flags = flags | new_flag;
985
174
  if ((flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flag & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
986
5
    zend_throw_exception(zend_ce_compile_error,
987
5
      "Multiple abstract modifiers are not allowed", 0);
988
5
    return 0;
989
5
  }
990
169
  if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
991
7
    zend_throw_exception(zend_ce_compile_error, "Multiple final modifiers are not allowed", 0);
992
7
    return 0;
993
7
  }
994
162
  if ((flags & ZEND_ACC_READONLY_CLASS) && (new_flag & ZEND_ACC_READONLY_CLASS)) {
995
8
    zend_throw_exception(zend_ce_compile_error, "Multiple readonly modifiers are not allowed", 0);
996
8
    return 0;
997
8
  }
998
154
  if ((new_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flags & ZEND_ACC_FINAL)) {
999
7
    zend_throw_exception(zend_ce_compile_error,
1000
7
      "Cannot use the final modifier on an abstract class", 0);
1001
7
    return 0;
1002
7
  }
1003
147
  return new_flags;
1004
154
}
1005
/* }}} */
1006
1007
uint32_t zend_add_anonymous_class_modifier(uint32_t flags, uint32_t new_flag)
1008
72
{
1009
72
  uint32_t new_flags = flags | new_flag;
1010
72
  if (new_flag & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
1011
6
    zend_throw_exception(zend_ce_compile_error,
1012
6
      "Cannot use the abstract modifier on an anonymous class", 0);
1013
6
    return 0;
1014
6
  }
1015
66
  if (new_flag & ZEND_ACC_FINAL) {
1016
6
    zend_throw_exception(zend_ce_compile_error, "Cannot use the final modifier on an anonymous class", 0);
1017
6
    return 0;
1018
6
  }
1019
60
  if ((flags & ZEND_ACC_READONLY_CLASS) && (new_flag & ZEND_ACC_READONLY_CLASS)) {
1020
6
    zend_throw_exception(zend_ce_compile_error, "Multiple readonly modifiers are not allowed", 0);
1021
6
    return 0;
1022
6
  }
1023
54
  return new_flags;
1024
60
}
1025
1026
uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag, zend_modifier_target target) /* {{{ */
1027
66.9k
{
1028
66.9k
  uint32_t new_flags = flags | new_flag;
1029
66.9k
  if ((flags & ZEND_ACC_PPP_MASK) && (new_flag & ZEND_ACC_PPP_MASK)) {
1030
46
    zend_throw_exception(zend_ce_compile_error,
1031
46
      "Multiple access type modifiers are not allowed", 0);
1032
46
    return 0;
1033
46
  }
1034
66.9k
  if ((new_flags & ZEND_ACC_ABSTRACT) && (new_flags & ZEND_ACC_FINAL)) {
1035
12
    if (target == ZEND_MODIFIER_TARGET_METHOD) {
1036
6
      zend_throw_exception(zend_ce_compile_error,
1037
6
        "Cannot use the final modifier on an abstract method", 0);
1038
6
      return 0;
1039
6
    }
1040
6
    if (target == ZEND_MODIFIER_TARGET_PROPERTY) {
1041
6
      zend_throw_exception(zend_ce_compile_error,
1042
6
        "Cannot use the final modifier on an abstract property", 0);
1043
6
      return 0;
1044
6
    }
1045
6
  }
1046
66.9k
  if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
1047
32.7k
    if ((flags & ZEND_ACC_PPP_SET_MASK) && (new_flag & ZEND_ACC_PPP_SET_MASK)) {
1048
23
      zend_throw_exception(zend_ce_compile_error,
1049
23
        "Multiple access type modifiers are not allowed", 0);
1050
23
      return 0;
1051
23
    }
1052
32.7k
  }
1053
66.9k
  return new_flags;
1054
66.9k
}
1055
/* }}} */
1056
1057
18.5k
ZEND_API zend_string *zend_create_member_string(zend_string *class_name, zend_string *member_name) {
1058
18.5k
  return zend_string_concat3(
1059
18.5k
    ZSTR_VAL(class_name), ZSTR_LEN(class_name),
1060
18.5k
    "::", sizeof("::") - 1,
1061
18.5k
    ZSTR_VAL(member_name), ZSTR_LEN(member_name));
1062
18.5k
}
1063
1064
185k
static zend_string *zend_concat_names(char *name1, size_t name1_len, char *name2, size_t name2_len) {
1065
185k
  return zend_string_concat3(name1, name1_len, "\\", 1, name2, name2_len);
1066
185k
}
1067
1068
1.12M
static zend_string *zend_prefix_with_ns(zend_string *name) {
1069
1.12M
  if (FC(current_namespace)) {
1070
184k
    zend_string *ns = FC(current_namespace);
1071
184k
    return zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
1072
936k
  } else {
1073
936k
    return zend_string_copy(name);
1074
936k
  }
1075
1.12M
}
1076
1077
static zend_string *zend_resolve_non_class_name(
1078
  zend_string *name, uint32_t type, bool *is_fully_qualified,
1079
  bool case_sensitive, HashTable *current_import_sub
1080
786k
) {
1081
786k
  char *compound;
1082
786k
  *is_fully_qualified = 0;
1083
1084
786k
  if (ZSTR_VAL(name)[0] == '\\') {
1085
    /* Remove \ prefix (only relevant if this is a string rather than a label) */
1086
493
    *is_fully_qualified = 1;
1087
493
    return zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
1088
493
  }
1089
1090
786k
  if (type == ZEND_NAME_FQ) {
1091
14.0k
    *is_fully_qualified = 1;
1092
14.0k
    return zend_string_copy(name);
1093
14.0k
  }
1094
1095
772k
  if (type == ZEND_NAME_RELATIVE) {
1096
922
    *is_fully_qualified = 1;
1097
922
    return zend_prefix_with_ns(name);
1098
922
  }
1099
1100
771k
  if (current_import_sub) {
1101
    /* If an unqualified name is a function/const alias, replace it. */
1102
1.32k
    zend_string *import_name;
1103
1.32k
    if (case_sensitive) {
1104
853
      import_name = zend_hash_find_ptr(current_import_sub, name);
1105
853
    } else {
1106
472
      import_name = zend_hash_find_ptr_lc(current_import_sub, name);
1107
472
    }
1108
1109
1.32k
    if (import_name) {
1110
493
      *is_fully_qualified = 1;
1111
493
      return zend_string_copy(import_name);
1112
493
    }
1113
1.32k
  }
1114
1115
770k
  compound = memchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
1116
770k
  if (compound) {
1117
5.42k
    *is_fully_qualified = 1;
1118
5.42k
  }
1119
1120
770k
  if (compound && FC(imports)) {
1121
    /* If the first part of a qualified name is an alias, substitute it. */
1122
2.80k
    size_t len = compound - ZSTR_VAL(name);
1123
2.80k
    zend_string *import_name = zend_hash_str_find_ptr_lc(FC(imports), ZSTR_VAL(name), len);
1124
1125
2.80k
    if (import_name) {
1126
340
      return zend_concat_names(
1127
340
        ZSTR_VAL(import_name), ZSTR_LEN(import_name), ZSTR_VAL(name) + len + 1, ZSTR_LEN(name) - len - 1);
1128
340
    }
1129
2.80k
  }
1130
1131
770k
  return zend_prefix_with_ns(name);
1132
770k
}
1133
/* }}} */
1134
1135
static zend_string *zend_resolve_function_name(zend_string *name, uint32_t type, bool *is_fully_qualified)
1136
231k
{
1137
231k
  return zend_resolve_non_class_name(
1138
231k
    name, type, is_fully_qualified, 0, FC(imports_function));
1139
231k
}
1140
1141
static zend_string *zend_resolve_const_name(zend_string *name, uint32_t type, bool *is_fully_qualified)
1142
555k
{
1143
555k
  return zend_resolve_non_class_name(
1144
555k
    name, type, is_fully_qualified, 1, FC(imports_const));
1145
555k
}
1146
1147
static zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
1148
286k
{
1149
286k
  char *compound;
1150
1151
286k
  if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
1152
3.30k
    if (type == ZEND_NAME_FQ) {
1153
6
      zend_error_noreturn(E_COMPILE_ERROR,
1154
6
        "'\\%s' is an invalid class name", ZSTR_VAL(name));
1155
6
    }
1156
3.30k
    if (type == ZEND_NAME_RELATIVE) {
1157
1
      zend_error_noreturn(E_COMPILE_ERROR,
1158
1
        "'namespace\\%s' is an invalid class name", ZSTR_VAL(name));
1159
1
    }
1160
3.30k
    ZEND_ASSERT(type == ZEND_NAME_NOT_FQ);
1161
3.30k
    return zend_string_copy(name);
1162
3.30k
  }
1163
1164
283k
  if (type == ZEND_NAME_RELATIVE) {
1165
657
    return zend_prefix_with_ns(name);
1166
657
  }
1167
1168
282k
  if (type == ZEND_NAME_FQ) {
1169
10.8k
    if (ZSTR_VAL(name)[0] == '\\') {
1170
      /* Remove \ prefix (only relevant if this is a string rather than a label) */
1171
175
      name = zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
1172
175
      if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
1173
1
        zend_error_noreturn(E_COMPILE_ERROR,
1174
1
          "'\\%s' is an invalid class name", ZSTR_VAL(name));
1175
1
      }
1176
174
      return name;
1177
175
    }
1178
1179
10.6k
    return zend_string_copy(name);
1180
10.8k
  }
1181
1182
271k
  if (FC(imports)) {
1183
4.92k
    compound = memchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
1184
4.92k
    if (compound) {
1185
      /* If the first part of a qualified name is an alias, substitute it. */
1186
989
      size_t len = compound - ZSTR_VAL(name);
1187
989
      zend_string *import_name =
1188
989
        zend_hash_str_find_ptr_lc(FC(imports), ZSTR_VAL(name), len);
1189
1190
989
      if (import_name) {
1191
577
        return zend_concat_names(
1192
577
          ZSTR_VAL(import_name), ZSTR_LEN(import_name), ZSTR_VAL(name) + len + 1, ZSTR_LEN(name) - len - 1);
1193
577
      }
1194
3.93k
    } else {
1195
      /* If an unqualified name is an alias, replace it. */
1196
3.93k
      zend_string *import_name
1197
3.93k
        = zend_hash_find_ptr_lc(FC(imports), name);
1198
1199
3.93k
      if (import_name) {
1200
1.14k
        return zend_string_copy(import_name);
1201
1.14k
      }
1202
3.93k
    }
1203
4.92k
  }
1204
1205
  /* If not fully qualified and not an alias, prepend the current namespace */
1206
269k
  return zend_prefix_with_ns(name);
1207
271k
}
1208
/* }}} */
1209
1210
static zend_string *zend_resolve_class_name_ast(zend_ast *ast) /* {{{ */
1211
259k
{
1212
259k
  zval *class_name = zend_ast_get_zval(ast);
1213
259k
  if (Z_TYPE_P(class_name) != IS_STRING) {
1214
28
    zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
1215
28
  }
1216
259k
  return zend_resolve_class_name(Z_STR_P(class_name), ast->attr);
1217
259k
}
1218
/* }}} */
1219
1220
static void label_ptr_dtor(zval *zv) /* {{{ */
1221
1.10k
{
1222
1.10k
  efree_size(Z_PTR_P(zv), sizeof(zend_label));
1223
1.10k
}
1224
/* }}} */
1225
1226
2.35k
static void str_dtor(zval *zv)  /* {{{ */ {
1227
2.35k
  zend_string_release_ex(Z_STR_P(zv), 0);
1228
2.35k
}
1229
/* }}} */
1230
1231
static bool zend_is_call(zend_ast *ast);
1232
1233
static uint32_t zend_add_try_element(uint32_t try_op) /* {{{ */
1234
44.8k
{
1235
44.8k
  zend_op_array *op_array = CG(active_op_array);
1236
44.8k
  uint32_t try_catch_offset = op_array->last_try_catch++;
1237
44.8k
  zend_try_catch_element *elem;
1238
1239
44.8k
  op_array->try_catch_array = safe_erealloc(
1240
44.8k
    op_array->try_catch_array, sizeof(zend_try_catch_element), op_array->last_try_catch, 0);
1241
1242
44.8k
  elem = &op_array->try_catch_array[try_catch_offset];
1243
44.8k
  elem->try_op = try_op;
1244
44.8k
  elem->catch_op = 0;
1245
44.8k
  elem->finally_op = 0;
1246
44.8k
  elem->finally_end = 0;
1247
1248
44.8k
  return try_catch_offset;
1249
44.8k
}
1250
/* }}} */
1251
1252
ZEND_API void function_add_ref(zend_function *function) /* {{{ */
1253
1.57k
{
1254
1.57k
  if (function->type == ZEND_USER_FUNCTION) {
1255
1.57k
    zend_op_array *op_array = &function->op_array;
1256
1.57k
    if (op_array->refcount) {
1257
108
      (*op_array->refcount)++;
1258
108
    }
1259
1260
1.57k
    ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
1261
1.57k
    ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, NULL);
1262
1.57k
  }
1263
1264
1.57k
  if (function->common.function_name) {
1265
1.57k
    zend_string_addref(function->common.function_name);
1266
1.57k
  }
1267
1.57k
}
1268
/* }}} */
1269
1270
static zend_never_inline ZEND_COLD ZEND_NORETURN void do_bind_function_error(zend_string *lcname, zend_op_array *op_array, bool compile_time) /* {{{ */
1271
105
{
1272
105
  zval *zv = zend_hash_find_known_hash(compile_time ? CG(function_table) : EG(function_table), lcname);
1273
105
  int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
1274
105
  zend_function *old_function;
1275
1276
105
  ZEND_ASSERT(zv != NULL);
1277
105
  old_function = (zend_function*)Z_PTR_P(zv);
1278
105
  if (old_function->type == ZEND_USER_FUNCTION
1279
105
    && old_function->op_array.last > 0) {
1280
98
    zend_error_noreturn(error_level, "Cannot redeclare function %s() (previously declared in %s:%d)",
1281
98
          op_array ? ZSTR_VAL(op_array->function_name) : ZSTR_VAL(old_function->common.function_name),
1282
98
          ZSTR_VAL(old_function->op_array.filename),
1283
98
          old_function->op_array.line_start);
1284
98
  } else {
1285
7
    zend_error_noreturn(error_level, "Cannot redeclare function %s()",
1286
7
      op_array ? ZSTR_VAL(op_array->function_name) : ZSTR_VAL(old_function->common.function_name));
1287
7
  }
1288
105
}
1289
1290
ZEND_API zend_result do_bind_function(zend_function *func, zval *lcname) /* {{{ */
1291
81
{
1292
81
  zend_function *added_func = zend_hash_add_ptr(EG(function_table), Z_STR_P(lcname), func);
1293
81
  if (UNEXPECTED(!added_func)) {
1294
3
    do_bind_function_error(Z_STR_P(lcname), &func->op_array, 0);
1295
0
    return FAILURE;
1296
3
  }
1297
1298
78
  if (func->op_array.refcount) {
1299
19
    ++*func->op_array.refcount;
1300
19
  }
1301
78
  if (func->common.function_name) {
1302
78
    zend_string_addref(func->common.function_name);
1303
78
  }
1304
78
  zend_observer_function_declared_notify(&func->op_array, Z_STR_P(lcname));
1305
78
  return SUCCESS;
1306
81
}
1307
/* }}} */
1308
1309
ZEND_API zend_class_entry *zend_bind_class_in_slot(
1310
    zval *class_table_slot, zval *lcname, zend_string *lc_parent_name)
1311
6.51k
{
1312
6.51k
  zend_class_entry *ce = Z_PTR_P(class_table_slot);
1313
6.51k
  bool is_preloaded =
1314
6.51k
    (ce->ce_flags & ZEND_ACC_PRELOADED) && !(CG(compiler_options) & ZEND_COMPILE_PRELOAD);
1315
6.51k
  bool success;
1316
6.51k
  if (EXPECTED(!is_preloaded)) {
1317
6.51k
    success = zend_hash_set_bucket_key(EG(class_table), (Bucket*) class_table_slot, Z_STR_P(lcname)) != NULL;
1318
6.51k
  } else {
1319
    /* If preloading is used, don't replace the existing bucket, add a new one. */
1320
0
    success = zend_hash_add_ptr(EG(class_table), Z_STR_P(lcname), ce) != NULL;
1321
0
  }
1322
6.51k
  if (UNEXPECTED(!success)) {
1323
133
    zend_class_entry *old_class = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname));
1324
133
    ZEND_ASSERT(old_class);
1325
133
    zend_class_redeclaration_error(E_COMPILE_ERROR, old_class);
1326
133
    return NULL;
1327
133
  }
1328
1329
6.37k
  if (ce->ce_flags & ZEND_ACC_LINKED) {
1330
272
    zend_observer_class_linked_notify(ce, Z_STR_P(lcname));
1331
272
    return ce;
1332
272
  }
1333
1334
6.10k
  ce = zend_do_link_class(ce, lc_parent_name, Z_STR_P(lcname));
1335
6.10k
  if (ce) {
1336
4.81k
    ZEND_ASSERT(!EG(exception));
1337
4.81k
    zend_observer_class_linked_notify(ce, Z_STR_P(lcname));
1338
4.81k
    return ce;
1339
4.81k
  }
1340
1341
1.28k
  if (!is_preloaded) {
1342
    /* Reload bucket pointer, the hash table may have been reallocated */
1343
261
    zval *zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
1344
261
    zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1));
1345
1.02k
  } else {
1346
1.02k
    zend_hash_del(EG(class_table), Z_STR_P(lcname));
1347
1.02k
  }
1348
1.28k
  return NULL;
1349
6.10k
}
1350
1351
ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */
1352
5.88k
{
1353
5.88k
  zend_class_entry *ce;
1354
5.88k
  zval *rtd_key, *zv;
1355
1356
5.88k
  rtd_key = lcname + 1;
1357
1358
5.88k
  zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(rtd_key));
1359
1360
5.88k
  if (UNEXPECTED(!zv)) {
1361
11
    ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname));
1362
11
    ZEND_ASSERT(ce);
1363
11
    zend_class_redeclaration_error(E_COMPILE_ERROR, ce);
1364
11
    return FAILURE;
1365
11
  }
1366
1367
  /* Register the derived class */
1368
5.86k
  return zend_bind_class_in_slot(zv, lcname, lc_parent_name) ? SUCCESS : FAILURE;
1369
5.88k
}
1370
/* }}} */
1371
1372
20.0k
static zend_string *add_type_string(zend_string *type, zend_string *new_type, bool is_intersection) {
1373
20.0k
  zend_string *result;
1374
20.0k
  if (type == NULL) {
1375
14.2k
    return zend_string_copy(new_type);
1376
14.2k
  }
1377
1378
5.84k
  if (is_intersection) {
1379
3.00k
    result = zend_string_concat3(ZSTR_VAL(type), ZSTR_LEN(type),
1380
3.00k
      "&", 1, ZSTR_VAL(new_type), ZSTR_LEN(new_type));
1381
3.00k
    zend_string_release(type);
1382
3.00k
  } else {
1383
2.84k
    result = zend_string_concat3(
1384
2.84k
      ZSTR_VAL(type), ZSTR_LEN(type), "|", 1, ZSTR_VAL(new_type), ZSTR_LEN(new_type));
1385
2.84k
    zend_string_release(type);
1386
2.84k
  }
1387
5.84k
  return result;
1388
20.0k
}
1389
1390
3.71k
static zend_string *resolve_class_name(zend_string *name, zend_class_entry *scope) {
1391
3.71k
  if (scope) {
1392
2.45k
    if (zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_SELF))) {
1393
17
      name = scope->name;
1394
2.43k
    } else if (zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_PARENT)) && scope->parent) {
1395
0
      name = scope->parent->name;
1396
0
    }
1397
2.45k
  }
1398
1399
  /* The resolved name for anonymous classes contains null bytes. Cut off everything after the
1400
   * null byte here, to avoid larger parts of the type being omitted by printing code later. */
1401
3.71k
  size_t len = strlen(ZSTR_VAL(name));
1402
3.71k
  if (len != ZSTR_LEN(name)) {
1403
10
    ZEND_ASSERT(scope && "This should only happen with resolved types");
1404
10
    return zend_string_init(ZSTR_VAL(name), len, 0);
1405
10
  }
1406
3.70k
  return zend_string_copy(name);
1407
3.71k
}
1408
1409
static zend_string *add_intersection_type(zend_string *str,
1410
  const zend_type_list *intersection_type_list, zend_class_entry *scope,
1411
  bool is_bracketed)
1412
1.77k
{
1413
1.77k
  const zend_type *single_type;
1414
1.77k
  zend_string *intersection_str = NULL;
1415
1416
6.55k
  ZEND_TYPE_LIST_FOREACH(intersection_type_list, single_type) {
1417
6.55k
    ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*single_type));
1418
4.77k
    ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*single_type));
1419
1420
4.77k
    intersection_str = add_type_string(intersection_str, ZEND_TYPE_NAME(*single_type), /* is_intersection */ true);
1421
4.77k
  } ZEND_TYPE_LIST_FOREACH_END();
1422
1423
1.77k
  ZEND_ASSERT(intersection_str);
1424
1425
1.77k
  if (is_bracketed) {
1426
1.27k
    zend_string *result = zend_string_concat3("(", 1, ZSTR_VAL(intersection_str), ZSTR_LEN(intersection_str), ")", 1);
1427
1.27k
    zend_string_release(intersection_str);
1428
1.27k
    intersection_str = result;
1429
1.27k
  }
1430
1.77k
  str = add_type_string(str, intersection_str, /* is_intersection */ false);
1431
1.77k
  zend_string_release(intersection_str);
1432
1.77k
  return str;
1433
1.77k
}
1434
1435
14.9k
zend_string *zend_type_to_string_resolved(const zend_type type, zend_class_entry *scope) {
1436
14.9k
  zend_string *str = NULL;
1437
1438
  /* Pure intersection type */
1439
14.9k
  if (ZEND_TYPE_IS_INTERSECTION(type)) {
1440
502
    ZEND_ASSERT(!ZEND_TYPE_IS_UNION(type));
1441
502
    str = add_intersection_type(str, ZEND_TYPE_LIST(type), scope, /* is_bracketed */ false);
1442
14.4k
  } else if (ZEND_TYPE_HAS_LIST(type)) {
1443
    /* A union type might not be a list */
1444
623
    const zend_type *list_type;
1445
3.11k
    ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) {
1446
3.11k
      if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {
1447
1.27k
        str = add_intersection_type(str, ZEND_TYPE_LIST(*list_type), scope, /* is_bracketed */ true);
1448
1.27k
        continue;
1449
1.27k
      }
1450
1.21k
      ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
1451
1.21k
      ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*list_type));
1452
1453
1.21k
      zend_string *name = ZEND_TYPE_NAME(*list_type);
1454
1.21k
      zend_string *resolved = resolve_class_name(name, scope);
1455
1.21k
      str = add_type_string(str, resolved, /* is_intersection */ false);
1456
1.21k
      zend_string_release(resolved);
1457
1.21k
    } ZEND_TYPE_LIST_FOREACH_END();
1458
13.8k
  } else if (ZEND_TYPE_HAS_NAME(type)) {
1459
2.50k
    str = resolve_class_name(ZEND_TYPE_NAME(type), scope);
1460
2.50k
  }
1461
1462
14.9k
  uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
1463
1464
14.9k
  if (type_mask == MAY_BE_ANY) {
1465
108
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_MIXED), /* is_intersection */ false);
1466
1467
108
    return str;
1468
108
  }
1469
14.8k
  if (type_mask & MAY_BE_STATIC) {
1470
127
    zend_string *name = ZSTR_KNOWN(ZEND_STR_STATIC);
1471
    // During compilation of eval'd code the called scope refers to the scope calling the eval
1472
127
    if (scope && !zend_is_compiling()) {
1473
33
      zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
1474
33
      if (called_scope) {
1475
15
        name = called_scope->name;
1476
15
      }
1477
33
    }
1478
127
    str = add_type_string(str, name, /* is_intersection */ false);
1479
127
  }
1480
14.8k
  if (type_mask & MAY_BE_CALLABLE) {
1481
52
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_CALLABLE), /* is_intersection */ false);
1482
52
  }
1483
14.8k
  if (type_mask & MAY_BE_OBJECT) {
1484
174
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_OBJECT), /* is_intersection */ false);
1485
174
  }
1486
14.8k
  if (type_mask & MAY_BE_ARRAY) {
1487
1.20k
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_ARRAY), /* is_intersection */ false);
1488
1.20k
  }
1489
14.8k
  if (type_mask & MAY_BE_STRING) {
1490
6.06k
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_STRING), /* is_intersection */ false);
1491
6.06k
  }
1492
14.8k
  if (type_mask & MAY_BE_LONG) {
1493
3.51k
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_INT), /* is_intersection */ false);
1494
3.51k
  }
1495
14.8k
  if (type_mask & MAY_BE_DOUBLE) {
1496
268
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_FLOAT), /* is_intersection */ false);
1497
268
  }
1498
14.8k
  if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL) {
1499
349
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_BOOL), /* is_intersection */ false);
1500
14.4k
  } else if (type_mask & MAY_BE_FALSE) {
1501
121
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_FALSE), /* is_intersection */ false);
1502
14.3k
  } else if (type_mask & MAY_BE_TRUE) {
1503
46
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_TRUE), /* is_intersection */ false);
1504
46
  }
1505
14.8k
  if (type_mask & MAY_BE_VOID) {
1506
106
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_VOID), /* is_intersection */ false);
1507
106
  }
1508
14.8k
  if (type_mask & MAY_BE_NEVER) {
1509
19
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_NEVER), /* is_intersection */ false);
1510
19
  }
1511
1512
14.8k
  if (type_mask & MAY_BE_NULL) {
1513
1.52k
    bool is_union = !str || memchr(ZSTR_VAL(str), '|', ZSTR_LEN(str)) != NULL;
1514
1.52k
    bool has_intersection = !str || memchr(ZSTR_VAL(str), '&', ZSTR_LEN(str)) != NULL;
1515
1.52k
    if (!is_union && !has_intersection) {
1516
1.40k
      zend_string *nullable_str = zend_string_concat2("?", 1, ZSTR_VAL(str), ZSTR_LEN(str));
1517
1.40k
      zend_string_release(str);
1518
1.40k
      return nullable_str;
1519
1.40k
    }
1520
1521
124
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_NULL_LOWERCASE), /* is_intersection */ false);
1522
124
  }
1523
13.4k
  return str;
1524
14.8k
}
1525
1526
8.96k
ZEND_API zend_string *zend_type_to_string(zend_type type) {
1527
8.96k
  return zend_type_to_string_resolved(type, NULL);
1528
8.96k
}
1529
1530
946
static bool is_generator_compatible_class_type(const zend_string *name) {
1531
946
  return zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_TRAVERSABLE))
1532
946
    || zend_string_equals_literal_ci(name, "Iterator")
1533
946
    || zend_string_equals_literal_ci(name, "Generator");
1534
946
}
1535
1536
static void zend_mark_function_as_generator(void) /* {{{ */
1537
10.7k
{
1538
10.7k
  if (!CG(active_op_array)->function_name) {
1539
64
    zend_error_noreturn(E_COMPILE_ERROR,
1540
64
      "The \"yield\" expression can only be used inside a function");
1541
64
  }
1542
1543
10.6k
  if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
1544
888
    const zend_type return_type = CG(active_op_array)->arg_info[-1].type;
1545
888
    bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & MAY_BE_OBJECT) != 0;
1546
888
    if (!valid_type) {
1547
852
      const zend_type *single_type;
1548
1.80k
      ZEND_TYPE_FOREACH(return_type, single_type) {
1549
1.80k
        if (ZEND_TYPE_HAS_NAME(*single_type)
1550
952
            && is_generator_compatible_class_type(ZEND_TYPE_NAME(*single_type))) {
1551
800
          valid_type = 1;
1552
800
          break;
1553
800
        }
1554
1.80k
      } ZEND_TYPE_FOREACH_END();
1555
852
    }
1556
1557
888
    if (!valid_type) {
1558
52
      zend_string *str = zend_type_to_string(return_type);
1559
52
      zend_error_noreturn(E_COMPILE_ERROR,
1560
52
        "Generator return type must be a supertype of Generator, %s given",
1561
52
        ZSTR_VAL(str));
1562
52
    }
1563
888
  }
1564
1565
10.6k
  CG(active_op_array)->fn_flags |= ZEND_ACC_GENERATOR;
1566
10.6k
}
1567
/* }}} */
1568
1569
ZEND_API zend_string *zend_mangle_property_name(const char *src1, size_t src1_length, const char *src2, size_t src2_length, bool internal) /* {{{ */
1570
71.4k
{
1571
71.4k
  size_t prop_name_length = 1 + src1_length + 1 + src2_length;
1572
71.4k
  zend_string *prop_name = zend_string_alloc(prop_name_length, internal);
1573
1574
71.4k
  ZSTR_VAL(prop_name)[0] = '\0';
1575
71.4k
  memcpy(ZSTR_VAL(prop_name) + 1, src1, src1_length+1);
1576
71.4k
  memcpy(ZSTR_VAL(prop_name) + 1 + src1_length + 1, src2, src2_length+1);
1577
71.4k
  return prop_name;
1578
71.4k
}
1579
/* }}} */
1580
1581
ZEND_API zend_result zend_unmangle_property_name_ex(const zend_string *name, const char **class_name, const char **prop_name, size_t *prop_len) /* {{{ */
1582
1.62M
{
1583
1.62M
  size_t class_name_len;
1584
1.62M
  size_t anonclass_src_len;
1585
1586
1.62M
  *class_name = NULL;
1587
1588
1.62M
  if (!ZSTR_LEN(name) || ZSTR_VAL(name)[0] != '\0') {
1589
1.46M
    *prop_name = ZSTR_VAL(name);
1590
1.46M
    if (prop_len) {
1591
993k
      *prop_len = ZSTR_LEN(name);
1592
993k
    }
1593
1.46M
    return SUCCESS;
1594
1.46M
  }
1595
167k
  if (ZSTR_LEN(name) < 3 || ZSTR_VAL(name)[1] == '\0') {
1596
2.27k
    zend_error(E_NOTICE, "Illegal member variable name");
1597
2.27k
    *prop_name = ZSTR_VAL(name);
1598
2.27k
    if (prop_len) {
1599
2.16k
      *prop_len = ZSTR_LEN(name);
1600
2.16k
    }
1601
2.27k
    return FAILURE;
1602
2.27k
  }
1603
1604
165k
  class_name_len = zend_strnlen(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 2);
1605
165k
  if (class_name_len >= ZSTR_LEN(name) - 2 || ZSTR_VAL(name)[class_name_len + 1] != '\0') {
1606
691
    zend_error(E_NOTICE, "Corrupt member variable name");
1607
691
    *prop_name = ZSTR_VAL(name);
1608
691
    if (prop_len) {
1609
672
      *prop_len = ZSTR_LEN(name);
1610
672
    }
1611
691
    return FAILURE;
1612
691
  }
1613
1614
164k
  *class_name = ZSTR_VAL(name) + 1;
1615
164k
  anonclass_src_len = zend_strnlen(*class_name + class_name_len + 1, ZSTR_LEN(name) - class_name_len - 2);
1616
164k
  if (class_name_len + anonclass_src_len + 2 != ZSTR_LEN(name)) {
1617
34.9k
    class_name_len += anonclass_src_len + 1;
1618
34.9k
  }
1619
164k
  *prop_name = ZSTR_VAL(name) + class_name_len + 2;
1620
164k
  if (prop_len) {
1621
104k
    *prop_len = ZSTR_LEN(name) - class_name_len - 2;
1622
104k
  }
1623
164k
  return SUCCESS;
1624
165k
}
1625
/* }}} */
1626
1627
static bool array_is_const_ex(zend_array *array, uint32_t *max_checks)
1628
34
{
1629
34
  if (zend_hash_num_elements(array) > *max_checks) {
1630
0
    return false;
1631
0
  }
1632
34
  *max_checks -= zend_hash_num_elements(array);
1633
1634
34
  zval *element;
1635
72
  ZEND_HASH_FOREACH_VAL(array, element) {
1636
72
    if (Z_TYPE_P(element) < IS_ARRAY) {
1637
19
      continue;
1638
19
    } else if (Z_TYPE_P(element) == IS_ARRAY) {
1639
0
      if (!array_is_const_ex(array, max_checks)) {
1640
0
        return false;
1641
0
      }
1642
0
    } else {
1643
0
      return false;
1644
0
    }
1645
72
  } ZEND_HASH_FOREACH_END();
1646
1647
34
  return true;
1648
34
}
1649
1650
static bool array_is_const(zend_array *array)
1651
34
{
1652
34
  uint32_t max_checks = 50;
1653
34
  return array_is_const_ex(array, &max_checks);
1654
34
}
1655
1656
9.96k
static bool can_ct_eval_const(zend_constant *c) {
1657
9.96k
  if (ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED) {
1658
242
    return 0;
1659
242
  }
1660
9.72k
  if ((ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)
1661
9.72k
      && !(CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION)
1662
9.72k
      && !((ZEND_CONSTANT_FLAGS(c) & CONST_NO_FILE_CACHE)
1663
9.10k
        && (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) {
1664
9.10k
    return 1;
1665
9.10k
  }
1666
615
  if (Z_TYPE(c->value) < IS_ARRAY
1667
615
      && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
1668
13
    return 1;
1669
602
  } else if (Z_TYPE(c->value) == IS_ARRAY
1670
602
      && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)
1671
602
      && array_is_const(Z_ARR(c->value))) {
1672
0
    return 1;
1673
0
  }
1674
602
  return 0;
1675
615
}
1676
1677
static bool zend_try_ct_eval_const(zval *zv, zend_string *name, bool is_fully_qualified) /* {{{ */
1678
556k
{
1679
  /* Substitute true, false and null (including unqualified usage in namespaces)
1680
   * before looking up the possibly namespaced name. */
1681
556k
  const char *lookup_name = ZSTR_VAL(name);
1682
556k
  size_t lookup_len = ZSTR_LEN(name);
1683
1684
556k
  if (!is_fully_qualified) {
1685
547k
    zend_get_unqualified_name(name, &lookup_name, &lookup_len);
1686
547k
  }
1687
1688
556k
  zend_constant *c;
1689
556k
  if ((c = zend_get_special_const(lookup_name, lookup_len))) {
1690
22.1k
    ZVAL_COPY_VALUE(zv, &c->value);
1691
22.1k
    return 1;
1692
22.1k
  }
1693
534k
  c = zend_hash_find_ptr(EG(zend_constants), name);
1694
534k
  if (c && can_ct_eval_const(c)) {
1695
9.11k
    ZVAL_COPY_OR_DUP(zv, &c->value);
1696
9.11k
    return 1;
1697
9.11k
  }
1698
525k
  return 0;
1699
534k
}
1700
/* }}} */
1701
1702
static inline bool zend_is_scope_known(void) /* {{{ */
1703
12.9k
{
1704
12.9k
  if (!CG(active_op_array)) {
1705
    /* This can only happen when evaluating a default value string. */
1706
0
    return 0;
1707
0
  }
1708
1709
12.9k
  if (CG(active_op_array)->fn_flags & ZEND_ACC_CLOSURE) {
1710
    /* Closures can be rebound to a different scope */
1711
2.33k
    return 0;
1712
2.33k
  }
1713
1714
10.6k
  if (!CG(active_class_entry)) {
1715
    /* The scope is known if we're in a free function (no scope), but not if we're in
1716
     * a file/eval (which inherits including/eval'ing scope). */
1717
2.21k
    return CG(active_op_array)->function_name != NULL;
1718
2.21k
  }
1719
1720
  /* For traits self etc refers to the using class, not the trait itself */
1721
8.40k
  return (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == 0;
1722
10.6k
}
1723
/* }}} */
1724
1725
static inline bool class_name_refers_to_active_ce(zend_string *class_name, uint32_t fetch_type) /* {{{ */
1726
18.8k
{
1727
18.8k
  if (!CG(active_class_entry)) {
1728
13.6k
    return 0;
1729
13.6k
  }
1730
5.28k
  if (fetch_type == ZEND_FETCH_CLASS_SELF && zend_is_scope_known()) {
1731
1.16k
    return 1;
1732
1.16k
  }
1733
4.11k
  return fetch_type == ZEND_FETCH_CLASS_DEFAULT
1734
4.11k
    && zend_string_equals_ci(class_name, CG(active_class_entry)->name);
1735
5.28k
}
1736
/* }}} */
1737
1738
uint32_t zend_get_class_fetch_type(const zend_string *name) /* {{{ */
1739
546k
{
1740
546k
  if (zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_SELF))) {
1741
8.34k
    return ZEND_FETCH_CLASS_SELF;
1742
538k
  } else if (zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_PARENT))) {
1743
6.37k
    return ZEND_FETCH_CLASS_PARENT;
1744
532k
  } else if (zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_STATIC))) {
1745
2.55k
    return ZEND_FETCH_CLASS_STATIC;
1746
529k
  } else {
1747
529k
    return ZEND_FETCH_CLASS_DEFAULT;
1748
529k
  }
1749
546k
}
1750
/* }}} */
1751
1752
static uint32_t zend_get_class_fetch_type_ast(zend_ast *name_ast) /* {{{ */
1753
122k
{
1754
  /* Fully qualified names are always default refs */
1755
122k
  if (name_ast->attr == ZEND_NAME_FQ) {
1756
3.44k
    return ZEND_FETCH_CLASS_DEFAULT;
1757
3.44k
  }
1758
1759
118k
  return zend_get_class_fetch_type(zend_ast_get_str(name_ast));
1760
122k
}
1761
/* }}} */
1762
1763
static zend_string *zend_resolve_const_class_name_reference(zend_ast *ast, const char *type)
1764
26.1k
{
1765
26.1k
  zend_string *class_name = zend_ast_get_str(ast);
1766
26.1k
  if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type_ast(ast)) {
1767
25
    zend_error_noreturn(E_COMPILE_ERROR,
1768
25
      "Cannot use \"%s\" as %s, as it is reserved",
1769
25
      ZSTR_VAL(class_name), type);
1770
25
  }
1771
26.1k
  return zend_resolve_class_name(class_name, ast->attr);
1772
26.1k
}
1773
1774
static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
1775
11.4k
{
1776
11.4k
  if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && zend_is_scope_known()) {
1777
3.82k
    zend_class_entry *ce = CG(active_class_entry);
1778
3.82k
    if (!ce) {
1779
27
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"%s\" when no class scope is active",
1780
27
        fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
1781
27
        fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
1782
3.79k
    } else if (fetch_type == ZEND_FETCH_CLASS_PARENT && !ce->parent_name) {
1783
27
      zend_error_noreturn(E_COMPILE_ERROR,
1784
27
        "Cannot use \"parent\" when current class scope has no parent");
1785
27
    }
1786
3.82k
  }
1787
11.4k
}
1788
/* }}} */
1789
1790
static bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast) /* {{{ */
1791
6.95k
{
1792
6.95k
  uint32_t fetch_type;
1793
6.95k
  zval *class_name;
1794
1795
6.95k
  if (class_ast->kind != ZEND_AST_ZVAL) {
1796
1.75k
    return 0;
1797
1.75k
  }
1798
1799
5.20k
  class_name = zend_ast_get_zval(class_ast);
1800
1801
5.20k
  if (Z_TYPE_P(class_name) != IS_STRING) {
1802
6
    zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
1803
6
  }
1804
1805
5.19k
  fetch_type = zend_get_class_fetch_type(Z_STR_P(class_name));
1806
5.19k
  zend_ensure_valid_class_fetch_type(fetch_type);
1807
1808
5.19k
  switch (fetch_type) {
1809
433
    case ZEND_FETCH_CLASS_SELF:
1810
433
      if (CG(active_class_entry) && zend_is_scope_known()) {
1811
116
        ZVAL_STR_COPY(zv, CG(active_class_entry)->name);
1812
116
        return 1;
1813
116
      }
1814
317
      return 0;
1815
691
    case ZEND_FETCH_CLASS_PARENT:
1816
691
      if (CG(active_class_entry) && CG(active_class_entry)->parent_name
1817
691
          && zend_is_scope_known()) {
1818
143
        ZVAL_STR_COPY(zv, CG(active_class_entry)->parent_name);
1819
143
        return 1;
1820
143
      }
1821
548
      return 0;
1822
414
    case ZEND_FETCH_CLASS_STATIC:
1823
414
      return 0;
1824
3.64k
    case ZEND_FETCH_CLASS_DEFAULT:
1825
3.64k
      ZVAL_STR(zv, zend_resolve_class_name_ast(class_ast));
1826
3.64k
      return 1;
1827
5.19k
    EMPTY_SWITCH_DEFAULT_CASE()
1828
5.19k
  }
1829
5.19k
}
1830
/* }}} */
1831
1832
/* We don't use zend_verify_const_access because we need to deal with unlinked classes. */
1833
static bool zend_verify_ct_const_access(zend_class_constant *c, zend_class_entry *scope)
1834
792
{
1835
792
  if (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED) {
1836
20
    return 0;
1837
772
  } else if (c->ce->ce_flags & ZEND_ACC_TRAIT) {
1838
    /* This condition is only met on directly accessing trait constants,
1839
     * because the ce is replaced to the class entry of the composing class
1840
     * on binding. */
1841
0
    return 0;
1842
772
  } else if (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_PUBLIC) {
1843
626
    return 1;
1844
626
  } else if (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_PRIVATE) {
1845
146
    return c->ce == scope;
1846
146
  } else {
1847
0
    zend_class_entry *ce = c->ce;
1848
0
    while (1) {
1849
0
      if (ce == scope) {
1850
0
        return 1;
1851
0
      }
1852
0
      if (!ce->parent) {
1853
0
        break;
1854
0
      }
1855
0
      if (ce->ce_flags & ZEND_ACC_RESOLVED_PARENT) {
1856
0
        ce = ce->parent;
1857
0
      } else {
1858
0
        ce = zend_hash_find_ptr_lc(CG(class_table), ce->parent_name);
1859
0
        if (!ce) {
1860
0
          break;
1861
0
        }
1862
0
      }
1863
0
    }
1864
    /* Reverse case cannot be true during compilation */
1865
0
    return 0;
1866
0
  }
1867
792
}
1868
1869
static bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend_string *name) /* {{{ */
1870
18.8k
{
1871
18.8k
  uint32_t fetch_type = zend_get_class_fetch_type(class_name);
1872
18.8k
  zend_class_constant *cc;
1873
18.8k
  zval *c;
1874
1875
18.8k
  if (class_name_refers_to_active_ce(class_name, fetch_type)) {
1876
1.35k
    cc = zend_hash_find_ptr(&CG(active_class_entry)->constants_table, name);
1877
17.5k
  } else if (fetch_type == ZEND_FETCH_CLASS_DEFAULT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
1878
707
    zend_class_entry *ce = zend_hash_find_ptr_lc(CG(class_table), class_name);
1879
707
    if (ce) {
1880
230
      cc = zend_hash_find_ptr(&ce->constants_table, name);
1881
477
    } else {
1882
477
      return 0;
1883
477
    }
1884
16.8k
  } else {
1885
16.8k
    return 0;
1886
16.8k
  }
1887
1888
1.58k
  if (CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION) {
1889
521
    return 0;
1890
521
  }
1891
1892
1.06k
  if (!cc || !zend_verify_ct_const_access(cc, CG(active_class_entry))) {
1893
289
    return 0;
1894
289
  }
1895
1896
772
  c = &cc->value;
1897
1898
  /* Substitute case-sensitive (or lowercase) persistent class constants */
1899
772
  if (Z_TYPE_P(c) < IS_ARRAY) {
1900
527
    ZVAL_COPY_OR_DUP(zv, c);
1901
527
    return 1;
1902
527
  } else if (Z_TYPE_P(c) == IS_ARRAY && array_is_const(Z_ARR_P(c))) {
1903
34
    ZVAL_COPY_OR_DUP(zv, c);
1904
34
    return 1;
1905
34
  }
1906
1907
211
  return 0;
1908
772
}
1909
/* }}} */
1910
1911
static void zend_add_to_list(void *result, void *item) /* {{{ */
1912
3.48k
{
1913
3.48k
  void** list = *(void**)result;
1914
3.48k
  size_t n = 0;
1915
1916
3.48k
  if (list) {
1917
33.8k
    while (list[n]) {
1918
31.2k
      n++;
1919
31.2k
    }
1920
2.56k
  }
1921
1922
3.48k
  list = erealloc(list, sizeof(void*) * (n+2));
1923
1924
3.48k
  list[n]   = item;
1925
3.48k
  list[n+1] = NULL;
1926
1927
3.48k
  *(void**)result = list;
1928
3.48k
}
1929
/* }}} */
1930
1931
static void zend_do_extended_stmt(void) /* {{{ */
1932
111k
{
1933
111k
  zend_op *opline;
1934
1935
111k
  if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_STMT)) {
1936
111k
    return;
1937
111k
  }
1938
1939
0
  opline = get_next_op();
1940
1941
0
  opline->opcode = ZEND_EXT_STMT;
1942
0
}
1943
/* }}} */
1944
1945
static void zend_do_extended_fcall_begin(void) /* {{{ */
1946
381k
{
1947
381k
  zend_op *opline;
1948
1949
381k
  if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_FCALL)) {
1950
381k
    return;
1951
381k
  }
1952
1953
0
  opline = get_next_op();
1954
1955
0
  opline->opcode = ZEND_EXT_FCALL_BEGIN;
1956
0
}
1957
/* }}} */
1958
1959
static void zend_do_extended_fcall_end(void) /* {{{ */
1960
381k
{
1961
381k
  zend_op *opline;
1962
1963
381k
  if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_FCALL)) {
1964
381k
    return;
1965
381k
  }
1966
1967
0
  opline = get_next_op();
1968
1969
0
  opline->opcode = ZEND_EXT_FCALL_END;
1970
0
}
1971
/* }}} */
1972
1973
0
ZEND_API bool zend_is_auto_global_str(const char *name, size_t len) /* {{{ */ {
1974
0
  zend_auto_global *auto_global;
1975
1976
0
  if ((auto_global = zend_hash_str_find_ptr(CG(auto_globals), name, len)) != NULL) {
1977
0
    if (auto_global->armed) {
1978
0
      auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1979
0
    }
1980
0
    return 1;
1981
0
  }
1982
0
  return 0;
1983
0
}
1984
/* }}} */
1985
1986
ZEND_API bool zend_is_auto_global(zend_string *name) /* {{{ */
1987
1.39M
{
1988
1.39M
  zend_auto_global *auto_global;
1989
1990
1.39M
  if ((auto_global = zend_hash_find_ptr(CG(auto_globals), name)) != NULL) {
1991
4.01k
    if (auto_global->armed) {
1992
290
      auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1993
290
    }
1994
4.01k
    return 1;
1995
4.01k
  }
1996
1.38M
  return 0;
1997
1.39M
}
1998
/* }}} */
1999
2000
ZEND_API zend_result zend_register_auto_global(zend_string *name, bool jit, zend_auto_global_callback auto_global_callback) /* {{{ */
2001
128
{
2002
128
  zend_auto_global auto_global;
2003
128
  zend_result retval;
2004
2005
128
  auto_global.name = name;
2006
128
  auto_global.auto_global_callback = auto_global_callback;
2007
128
  auto_global.jit = jit;
2008
2009
128
  retval = zend_hash_add_mem(CG(auto_globals), auto_global.name, &auto_global, sizeof(zend_auto_global)) != NULL ? SUCCESS : FAILURE;
2010
2011
128
  return retval;
2012
128
}
2013
/* }}} */
2014
2015
ZEND_API void zend_activate_auto_globals(void) /* {{{ */
2016
300k
{
2017
300k
  zend_auto_global *auto_global;
2018
2019
5.40M
  ZEND_HASH_MAP_FOREACH_PTR(CG(auto_globals), auto_global) {
2020
5.40M
    if (auto_global->jit) {
2021
1.20M
      auto_global->armed = 1;
2022
1.20M
    } else if (auto_global->auto_global_callback) {
2023
1.20M
      auto_global->armed = auto_global->auto_global_callback(auto_global->name);
2024
1.20M
    } else {
2025
0
      auto_global->armed = 0;
2026
0
    }
2027
5.40M
  } ZEND_HASH_FOREACH_END();
2028
300k
}
2029
/* }}} */
2030
2031
int ZEND_FASTCALL zendlex(zend_parser_stack_elem *elem) /* {{{ */
2032
11.6M
{
2033
11.6M
  zval zv;
2034
11.6M
  int ret;
2035
2036
11.6M
  if (CG(increment_lineno)) {
2037
12.0k
    CG(zend_lineno)++;
2038
12.0k
    CG(increment_lineno) = 0;
2039
12.0k
  }
2040
2041
11.6M
  ret = lex_scan(&zv, elem);
2042
11.6M
  ZEND_ASSERT(!EG(exception) || ret == T_ERROR);
2043
11.6M
  return ret;
2044
2045
11.6M
}
2046
/* }}} */
2047
2048
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, bool nullify_handlers) /* {{{ */
2049
60.9k
{
2050
60.9k
  bool persistent_hashes = ce->type == ZEND_INTERNAL_CLASS;
2051
2052
60.9k
  ce->refcount = 1;
2053
60.9k
  ce->ce_flags = ZEND_ACC_CONSTANTS_UPDATED;
2054
2055
60.9k
  if (CG(compiler_options) & ZEND_COMPILE_GUARDS) {
2056
0
    ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2057
0
  }
2058
2059
60.9k
  ce->default_properties_table = NULL;
2060
60.9k
  ce->default_static_members_table = NULL;
2061
60.9k
  zend_hash_init(&ce->properties_info, 8, NULL, NULL, persistent_hashes);
2062
60.9k
  zend_hash_init(&ce->constants_table, 8, NULL, NULL, persistent_hashes);
2063
60.9k
  zend_hash_init(&ce->function_table, 8, NULL, ZEND_FUNCTION_DTOR, persistent_hashes);
2064
2065
60.9k
  ce->doc_comment = NULL;
2066
2067
60.9k
  ZEND_MAP_PTR_INIT(ce->static_members_table, NULL);
2068
60.9k
  ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
2069
2070
60.9k
  ce->default_object_handlers = &std_object_handlers;
2071
60.9k
  ce->default_properties_count = 0;
2072
60.9k
  ce->default_static_members_count = 0;
2073
60.9k
  ce->properties_info_table = NULL;
2074
60.9k
  ce->attributes = NULL;
2075
60.9k
  ce->enum_backing_type = IS_UNDEF;
2076
60.9k
  ce->backed_enum_table = NULL;
2077
2078
60.9k
  if (nullify_handlers) {
2079
58.3k
    ce->constructor = NULL;
2080
58.3k
    ce->destructor = NULL;
2081
58.3k
    ce->clone = NULL;
2082
58.3k
    ce->__get = NULL;
2083
58.3k
    ce->__set = NULL;
2084
58.3k
    ce->__unset = NULL;
2085
58.3k
    ce->__isset = NULL;
2086
58.3k
    ce->__call = NULL;
2087
58.3k
    ce->__callstatic = NULL;
2088
58.3k
    ce->__tostring = NULL;
2089
58.3k
    ce->__serialize = NULL;
2090
58.3k
    ce->__unserialize = NULL;
2091
58.3k
    ce->__debugInfo = NULL;
2092
58.3k
    ce->create_object = NULL;
2093
58.3k
    ce->get_iterator = NULL;
2094
58.3k
    ce->iterator_funcs_ptr = NULL;
2095
58.3k
    ce->arrayaccess_funcs_ptr = NULL;
2096
58.3k
    ce->get_static_method = NULL;
2097
58.3k
    ce->parent = NULL;
2098
58.3k
    ce->parent_name = NULL;
2099
58.3k
    ce->num_interfaces = 0;
2100
58.3k
    ce->interfaces = NULL;
2101
58.3k
    ce->num_traits = 0;
2102
58.3k
    ce->num_hooked_props = 0;
2103
58.3k
    ce->num_hooked_prop_variance_checks = 0;
2104
58.3k
    ce->trait_names = NULL;
2105
58.3k
    ce->trait_aliases = NULL;
2106
58.3k
    ce->trait_precedences = NULL;
2107
58.3k
    ce->serialize = NULL;
2108
58.3k
    ce->unserialize = NULL;
2109
58.3k
    if (ce->type == ZEND_INTERNAL_CLASS) {
2110
0
      ce->info.internal.module = NULL;
2111
0
      ce->info.internal.builtin_functions = NULL;
2112
0
    }
2113
58.3k
  }
2114
60.9k
}
2115
/* }}} */
2116
2117
ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, uint32_t var) /* {{{ */
2118
0
{
2119
0
  return op_array->vars[EX_VAR_TO_NUM(var)];
2120
0
}
2121
/* }}} */
2122
2123
zend_ast *zend_ast_append_str(zend_ast *left_ast, zend_ast *right_ast) /* {{{ */
2124
0
{
2125
0
  zval *left_zv = zend_ast_get_zval(left_ast);
2126
0
  zend_string *left = Z_STR_P(left_zv);
2127
0
  zend_string *right = zend_ast_get_str(right_ast);
2128
2129
0
  zend_string *result;
2130
0
  size_t left_len = ZSTR_LEN(left);
2131
0
  size_t len = left_len + ZSTR_LEN(right) + 1; /* left\right */
2132
2133
0
  result = zend_string_extend(left, len, 0);
2134
0
  ZSTR_VAL(result)[left_len] = '\\';
2135
0
  memcpy(&ZSTR_VAL(result)[left_len + 1], ZSTR_VAL(right), ZSTR_LEN(right));
2136
0
  ZSTR_VAL(result)[len] = '\0';
2137
0
  zend_string_release_ex(right, 0);
2138
2139
0
  ZVAL_STR(left_zv, result);
2140
0
  return left_ast;
2141
0
}
2142
/* }}} */
2143
2144
zend_ast *zend_negate_num_string(zend_ast *ast) /* {{{ */
2145
1.26k
{
2146
1.26k
  zval *zv = zend_ast_get_zval(ast);
2147
1.26k
  if (Z_TYPE_P(zv) == IS_LONG) {
2148
903
    if (Z_LVAL_P(zv) == 0) {
2149
388
      ZVAL_NEW_STR(zv, ZSTR_INIT_LITERAL("-0", 0));
2150
515
    } else {
2151
515
      ZEND_ASSERT(Z_LVAL_P(zv) > 0);
2152
515
      Z_LVAL_P(zv) *= -1;
2153
515
    }
2154
903
  } else if (Z_TYPE_P(zv) == IS_STRING) {
2155
362
    size_t orig_len = Z_STRLEN_P(zv);
2156
362
    Z_STR_P(zv) = zend_string_extend(Z_STR_P(zv), orig_len + 1, 0);
2157
362
    memmove(Z_STRVAL_P(zv) + 1, Z_STRVAL_P(zv), orig_len + 1);
2158
362
    Z_STRVAL_P(zv)[0] = '-';
2159
362
  } else {
2160
0
    ZEND_UNREACHABLE();
2161
0
  }
2162
1.26k
  return ast;
2163
1.26k
}
2164
/* }}} */
2165
2166
static void zend_verify_namespace(void) /* {{{ */
2167
551k
{
2168
551k
  if (FC(has_bracketed_namespaces) && !FC(in_namespace)) {
2169
45
    zend_error_noreturn(E_COMPILE_ERROR, "No code may exist outside of namespace {}");
2170
45
  }
2171
551k
}
2172
/* }}} */
2173
2174
/* {{{ zend_dirname
2175
   Returns directory name component of path */
2176
ZEND_API size_t zend_dirname(char *path, size_t len)
2177
2.39k
{
2178
2.39k
  char *end = path + len - 1;
2179
2.39k
  unsigned int len_adjust = 0;
2180
2181
#ifdef ZEND_WIN32
2182
  /* Note that on Win32 CWD is per drive (heritage from CP/M).
2183
   * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
2184
   */
2185
  if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
2186
    /* Skip over the drive spec (if any) so as not to change */
2187
    path += 2;
2188
    len_adjust += 2;
2189
    if (2 == len) {
2190
      /* Return "c:" on Win32 for dirname("c:").
2191
       * It would be more consistent to return "c:."
2192
       * but that would require making the string *longer*.
2193
       */
2194
      return len;
2195
    }
2196
  }
2197
#endif
2198
2199
2.39k
  if (len == 0) {
2200
    /* Illegal use of this function */
2201
0
    return 0;
2202
0
  }
2203
2204
  /* Strip trailing slashes */
2205
2.39k
  while (end >= path && IS_SLASH_P_EX(end, end == path)) {
2206
0
    end--;
2207
0
  }
2208
2.39k
  if (end < path) {
2209
    /* The path only contained slashes */
2210
0
    path[0] = DEFAULT_SLASH;
2211
0
    path[1] = '\0';
2212
0
    return 1 + len_adjust;
2213
0
  }
2214
2215
  /* Strip filename */
2216
26.3k
  while (end >= path && !IS_SLASH_P_EX(end, end == path)) {
2217
23.9k
    end--;
2218
23.9k
  }
2219
2.39k
  if (end < path) {
2220
    /* No slash found, therefore return '.' */
2221
1.82k
    path[0] = '.';
2222
1.82k
    path[1] = '\0';
2223
1.82k
    return 1 + len_adjust;
2224
1.82k
  }
2225
2226
  /* Strip slashes which came before the file name */
2227
1.12k
  while (end >= path && IS_SLASH_P_EX(end, end == path)) {
2228
563
    end--;
2229
563
  }
2230
563
  if (end < path) {
2231
5
    path[0] = DEFAULT_SLASH;
2232
5
    path[1] = '\0';
2233
5
    return 1 + len_adjust;
2234
5
  }
2235
558
  *(end+1) = '\0';
2236
2237
558
  return (size_t)(end + 1 - path) + len_adjust;
2238
563
}
2239
/* }}} */
2240
2241
static void zend_adjust_for_fetch_type(zend_op *opline, znode *result, uint32_t type) /* {{{ */
2242
408k
{
2243
408k
  uint_fast8_t factor = (opline->opcode == ZEND_FETCH_STATIC_PROP_R) ? 1 : 3;
2244
2245
408k
  switch (type) {
2246
230k
    case BP_VAR_R:
2247
230k
      opline->result_type = IS_TMP_VAR;
2248
230k
      result->op_type = IS_TMP_VAR;
2249
230k
      return;
2250
92.8k
    case BP_VAR_W:
2251
92.8k
      opline->opcode += 1 * factor;
2252
92.8k
      return;
2253
12.5k
    case BP_VAR_RW:
2254
12.5k
      opline->opcode += 2 * factor;
2255
12.5k
      return;
2256
61.2k
    case BP_VAR_IS:
2257
61.2k
      opline->result_type = IS_TMP_VAR;
2258
61.2k
      result->op_type = IS_TMP_VAR;
2259
61.2k
      opline->opcode += 3 * factor;
2260
61.2k
      return;
2261
7.51k
    case BP_VAR_FUNC_ARG:
2262
7.51k
      opline->opcode += 4 * factor;
2263
7.51k
      return;
2264
4.10k
    case BP_VAR_UNSET:
2265
4.10k
      opline->opcode += 5 * factor;
2266
4.10k
      return;
2267
408k
    EMPTY_SWITCH_DEFAULT_CASE()
2268
408k
  }
2269
408k
}
2270
/* }}} */
2271
2272
static inline void zend_make_var_result(znode *result, zend_op *opline) /* {{{ */
2273
971k
{
2274
971k
  opline->result_type = IS_VAR;
2275
971k
  opline->result.var = get_temporary_variable();
2276
971k
  GET_NODE(result, opline->result);
2277
971k
}
2278
/* }}} */
2279
2280
static inline void zend_make_tmp_result(znode *result, zend_op *opline) /* {{{ */
2281
2.17M
{
2282
2.17M
  opline->result_type = IS_TMP_VAR;
2283
2.17M
  opline->result.var = get_temporary_variable();
2284
2.17M
  GET_NODE(result, opline->result);
2285
2.17M
}
2286
/* }}} */
2287
2288
static zend_op *zend_emit_op(znode *result, uint8_t opcode, znode *op1, znode *op2) /* {{{ */
2289
3.57M
{
2290
3.57M
  zend_op *opline = get_next_op();
2291
3.57M
  opline->opcode = opcode;
2292
2293
3.57M
  if (op1 != NULL) {
2294
2.58M
    SET_NODE(opline->op1, op1);
2295
2.58M
  }
2296
2297
3.57M
  if (op2 != NULL) {
2298
288k
    SET_NODE(opline->op2, op2);
2299
288k
  }
2300
2301
3.57M
  if (result) {
2302
695k
    zend_make_var_result(result, opline);
2303
695k
  }
2304
3.57M
  return opline;
2305
3.57M
}
2306
/* }}} */
2307
2308
static zend_op *zend_emit_op_tmp(znode *result, uint8_t opcode, znode *op1, znode *op2) /* {{{ */
2309
2.14M
{
2310
2.14M
  zend_op *opline = get_next_op();
2311
2.14M
  opline->opcode = opcode;
2312
2313
2.14M
  if (op1 != NULL) {
2314
874k
    SET_NODE(opline->op1, op1);
2315
874k
  }
2316
2317
2.14M
  if (op2 != NULL) {
2318
716k
    SET_NODE(opline->op2, op2);
2319
716k
  }
2320
2321
2.14M
  if (result) {
2322
2.12M
    zend_make_tmp_result(result, opline);
2323
2.12M
  }
2324
2325
2.14M
  return opline;
2326
2.14M
}
2327
/* }}} */
2328
2329
static void zend_emit_tick(void) /* {{{ */
2330
1.54k
{
2331
1.54k
  zend_op *opline;
2332
2333
  /* This prevents a double TICK generated by the parser statement of "declare()" */
2334
1.54k
  if (CG(active_op_array)->last && CG(active_op_array)->opcodes[CG(active_op_array)->last - 1].opcode == ZEND_TICKS) {
2335
235
    return;
2336
235
  }
2337
2338
1.30k
  opline = get_next_op();
2339
2340
1.30k
  opline->opcode = ZEND_TICKS;
2341
1.30k
  opline->extended_value = FC(declarables).ticks;
2342
1.30k
}
2343
/* }}} */
2344
2345
static inline zend_op *zend_emit_op_data(znode *value) /* {{{ */
2346
39.9k
{
2347
39.9k
  return zend_emit_op(NULL, ZEND_OP_DATA, value, NULL);
2348
39.9k
}
2349
/* }}} */
2350
2351
static inline uint32_t zend_emit_jump(uint32_t opnum_target) /* {{{ */
2352
114k
{
2353
114k
  uint32_t opnum = get_next_op_number();
2354
114k
  zend_op *opline = zend_emit_op(NULL, ZEND_JMP, NULL, NULL);
2355
114k
  opline->op1.opline_num = opnum_target;
2356
114k
  return opnum;
2357
114k
}
2358
/* }}} */
2359
2360
ZEND_API bool zend_is_smart_branch(const zend_op *opline) /* {{{ */
2361
93.9k
{
2362
93.9k
  switch (opline->opcode) {
2363
1.94k
    case ZEND_IS_IDENTICAL:
2364
2.46k
    case ZEND_IS_NOT_IDENTICAL:
2365
18.5k
    case ZEND_IS_EQUAL:
2366
19.4k
    case ZEND_IS_NOT_EQUAL:
2367
26.3k
    case ZEND_IS_SMALLER:
2368
28.2k
    case ZEND_IS_SMALLER_OR_EQUAL:
2369
29.2k
    case ZEND_CASE:
2370
31.3k
    case ZEND_CASE_STRICT:
2371
31.5k
    case ZEND_ISSET_ISEMPTY_CV:
2372
31.6k
    case ZEND_ISSET_ISEMPTY_VAR:
2373
31.9k
    case ZEND_ISSET_ISEMPTY_DIM_OBJ:
2374
32.0k
    case ZEND_ISSET_ISEMPTY_PROP_OBJ:
2375
32.1k
    case ZEND_ISSET_ISEMPTY_STATIC_PROP:
2376
32.2k
    case ZEND_INSTANCEOF:
2377
32.8k
    case ZEND_TYPE_CHECK:
2378
32.9k
    case ZEND_DEFINED:
2379
33.0k
    case ZEND_IN_ARRAY:
2380
33.0k
    case ZEND_ARRAY_KEY_EXISTS:
2381
33.0k
      return 1;
2382
60.8k
    default:
2383
60.8k
      return 0;
2384
93.9k
  }
2385
93.9k
}
2386
/* }}} */
2387
2388
static inline uint32_t zend_emit_cond_jump(uint8_t opcode, znode *cond, uint32_t opnum_target) /* {{{ */
2389
54.3k
{
2390
54.3k
  uint32_t opnum = get_next_op_number();
2391
54.3k
  zend_op *opline;
2392
2393
54.3k
  if (cond->op_type == IS_TMP_VAR && opnum > 0) {
2394
46.2k
    opline = CG(active_op_array)->opcodes + opnum - 1;
2395
46.2k
    if (opline->result_type == IS_TMP_VAR
2396
46.2k
     && opline->result.var == cond->u.op.var
2397
46.2k
     && zend_is_smart_branch(opline)) {
2398
32.8k
      if (opcode == ZEND_JMPZ) {
2399
18.6k
        opline->result_type = IS_TMP_VAR | IS_SMART_BRANCH_JMPZ;
2400
18.6k
      } else {
2401
14.1k
        ZEND_ASSERT(opcode == ZEND_JMPNZ);
2402
14.1k
        opline->result_type = IS_TMP_VAR | IS_SMART_BRANCH_JMPNZ;
2403
14.1k
      }
2404
32.8k
    }
2405
46.2k
  }
2406
54.3k
  opline = zend_emit_op(NULL, opcode, cond, NULL);
2407
54.3k
  opline->op2.opline_num = opnum_target;
2408
54.3k
  return opnum;
2409
54.3k
}
2410
/* }}} */
2411
2412
static inline void zend_update_jump_target(uint32_t opnum_jump, uint32_t opnum_target) /* {{{ */
2413
148k
{
2414
148k
  zend_op *opline = &CG(active_op_array)->opcodes[opnum_jump];
2415
148k
  switch (opline->opcode) {
2416
97.8k
    case ZEND_JMP:
2417
97.8k
      opline->op1.opline_num = opnum_target;
2418
97.8k
      break;
2419
25.6k
    case ZEND_JMPZ:
2420
33.0k
    case ZEND_JMPNZ:
2421
36.5k
    case ZEND_JMPZ_EX:
2422
38.9k
    case ZEND_JMPNZ_EX:
2423
41.2k
    case ZEND_JMP_SET:
2424
50.0k
    case ZEND_COALESCE:
2425
50.0k
    case ZEND_JMP_NULL:
2426
50.4k
    case ZEND_BIND_INIT_STATIC_OR_JMP:
2427
50.4k
    case ZEND_JMP_FRAMELESS:
2428
50.4k
      opline->op2.opline_num = opnum_target;
2429
50.4k
      break;
2430
148k
    EMPTY_SWITCH_DEFAULT_CASE()
2431
148k
  }
2432
148k
}
2433
/* }}} */
2434
2435
static inline void zend_update_jump_target_to_next(uint32_t opnum_jump) /* {{{ */
2436
146k
{
2437
146k
  zend_update_jump_target(opnum_jump, get_next_op_number());
2438
146k
}
2439
/* }}} */
2440
2441
static inline zend_op *zend_delayed_emit_op(znode *result, uint8_t opcode, znode *op1, znode *op2) /* {{{ */
2442
278k
{
2443
278k
  zend_op tmp_opline;
2444
2445
278k
  init_op(&tmp_opline);
2446
2447
278k
  tmp_opline.opcode = opcode;
2448
278k
  if (op1 != NULL) {
2449
278k
    SET_NODE(tmp_opline.op1, op1);
2450
278k
  }
2451
278k
  if (op2 != NULL) {
2452
259k
    SET_NODE(tmp_opline.op2, op2);
2453
259k
  }
2454
278k
  if (result) {
2455
274k
    zend_make_var_result(result, &tmp_opline);
2456
274k
  }
2457
2458
278k
  zend_stack_push(&CG(delayed_oplines_stack), &tmp_opline);
2459
278k
  return zend_stack_top(&CG(delayed_oplines_stack));
2460
278k
}
2461
/* }}} */
2462
2463
static inline uint32_t zend_delayed_compile_begin(void) /* {{{ */
2464
613k
{
2465
613k
  return zend_stack_count(&CG(delayed_oplines_stack));
2466
613k
}
2467
/* }}} */
2468
2469
static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */
2470
611k
{
2471
611k
  zend_op *opline = NULL, *oplines = zend_stack_base(&CG(delayed_oplines_stack));
2472
611k
  uint32_t i, count = zend_stack_count(&CG(delayed_oplines_stack));
2473
2474
611k
  ZEND_ASSERT(count >= offset);
2475
889k
  for (i = offset; i < count; ++i) {
2476
277k
    if (EXPECTED(oplines[i].opcode != ZEND_NOP)) {
2477
274k
      opline = get_next_op();
2478
274k
      memcpy(opline, &oplines[i], sizeof(zend_op));
2479
274k
    } else {
2480
3.62k
      opline = CG(active_op_array)->opcodes + oplines[i].extended_value;
2481
3.62k
    }
2482
277k
  }
2483
2484
611k
  CG(delayed_oplines_stack).top = offset;
2485
611k
  return opline;
2486
611k
}
2487
/* }}} */
2488
2489
static bool zend_ast_kind_is_short_circuited(zend_ast_kind ast_kind)
2490
5.95M
{
2491
5.95M
  switch (ast_kind) {
2492
141k
    case ZEND_AST_DIM:
2493
218k
    case ZEND_AST_PROP:
2494
320k
    case ZEND_AST_NULLSAFE_PROP:
2495
339k
    case ZEND_AST_STATIC_PROP:
2496
435k
    case ZEND_AST_METHOD_CALL:
2497
442k
    case ZEND_AST_NULLSAFE_METHOD_CALL:
2498
476k
    case ZEND_AST_STATIC_CALL:
2499
476k
      return 1;
2500
5.47M
    default:
2501
5.47M
      return 0;
2502
5.95M
  }
2503
5.95M
}
2504
2505
static bool zend_ast_is_short_circuited(const zend_ast *ast)
2506
820k
{
2507
820k
  switch (ast->kind) {
2508
76.4k
    case ZEND_AST_DIM:
2509
109k
    case ZEND_AST_PROP:
2510
118k
    case ZEND_AST_STATIC_PROP:
2511
121k
    case ZEND_AST_METHOD_CALL:
2512
122k
    case ZEND_AST_STATIC_CALL:
2513
122k
      return zend_ast_is_short_circuited(ast->child[0]);
2514
618
    case ZEND_AST_NULLSAFE_PROP:
2515
830
    case ZEND_AST_NULLSAFE_METHOD_CALL:
2516
830
      return 1;
2517
697k
    default:
2518
697k
      return 0;
2519
820k
  }
2520
820k
}
2521
2522
static void zend_assert_not_short_circuited(const zend_ast *ast)
2523
18.5k
{
2524
18.5k
  if (zend_ast_is_short_circuited(ast)) {
2525
41
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot take reference of a nullsafe chain");
2526
41
  }
2527
18.5k
}
2528
2529
/* Mark nodes that are an inner part of a short-circuiting chain.
2530
 * We should not perform a "commit" on them, as it will be performed by the outer-most node.
2531
 * We do this to avoid passing down an argument in various compile functions. */
2532
2533
483k
#define ZEND_SHORT_CIRCUITING_INNER 0x8000
2534
2535
341k
static void zend_short_circuiting_mark_inner(zend_ast *ast) {
2536
341k
  if (zend_ast_kind_is_short_circuited(ast->kind)) {
2537
135k
    ast->attr |= ZEND_SHORT_CIRCUITING_INNER;
2538
135k
  }
2539
341k
}
2540
2541
static uint32_t zend_short_circuiting_checkpoint(void)
2542
5.68M
{
2543
5.68M
  return zend_stack_count(&CG(short_circuiting_opnums));
2544
5.68M
}
2545
2546
static void zend_short_circuiting_commit(uint32_t checkpoint, znode *result, zend_ast *ast)
2547
5.61M
{
2548
5.61M
  bool is_short_circuited = zend_ast_kind_is_short_circuited(ast->kind)
2549
5.61M
    || ast->kind == ZEND_AST_ISSET || ast->kind == ZEND_AST_EMPTY;
2550
5.61M
  if (!is_short_circuited) {
2551
5.26M
    ZEND_ASSERT(zend_stack_count(&CG(short_circuiting_opnums)) == checkpoint
2552
5.26M
      && "Short circuiting stack should be empty");
2553
5.26M
    return;
2554
5.26M
  }
2555
2556
347k
  if (ast->attr & ZEND_SHORT_CIRCUITING_INNER) {
2557
    /* Outer-most node will commit. */
2558
39.2k
    return;
2559
39.2k
  }
2560
2561
363k
  while (zend_stack_count(&CG(short_circuiting_opnums)) != checkpoint) {
2562
55.2k
    uint32_t opnum = *(uint32_t *) zend_stack_top(&CG(short_circuiting_opnums));
2563
55.2k
    zend_op *opline = &CG(active_op_array)->opcodes[opnum];
2564
55.2k
    opline->op2.opline_num = get_next_op_number();
2565
55.2k
    SET_NODE(opline->result, result);
2566
55.2k
    opline->extended_value |=
2567
55.2k
      ast->kind == ZEND_AST_ISSET ? ZEND_SHORT_CIRCUITING_CHAIN_ISSET :
2568
55.2k
      ast->kind == ZEND_AST_EMPTY ? ZEND_SHORT_CIRCUITING_CHAIN_EMPTY :
2569
54.9k
                                    ZEND_SHORT_CIRCUITING_CHAIN_EXPR;
2570
55.2k
    zend_stack_del_top(&CG(short_circuiting_opnums));
2571
55.2k
  }
2572
307k
}
2573
2574
static void zend_emit_jmp_null(znode *obj_node, uint32_t bp_type)
2575
55.3k
{
2576
55.3k
  uint32_t jmp_null_opnum = get_next_op_number();
2577
55.3k
  zend_op *opline = zend_emit_op(NULL, ZEND_JMP_NULL, obj_node, NULL);
2578
55.3k
  if (opline->op1_type == IS_CONST) {
2579
1.26k
    Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
2580
1.26k
  }
2581
55.3k
  if (bp_type == BP_VAR_IS) {
2582
737
    opline->extended_value |= ZEND_JMP_NULL_BP_VAR_IS;
2583
737
  }
2584
55.3k
  zend_stack_push(&CG(short_circuiting_opnums), &jmp_null_opnum);
2585
55.3k
}
2586
2587
static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */
2588
109k
{
2589
109k
  const zend_memoize_mode memoize_mode = CG(memoize_mode);
2590
109k
  if (memoize_mode == ZEND_MEMOIZE_COMPILE) {
2591
55.4k
    znode memoized_result;
2592
2593
    /* Go through normal compilation */
2594
55.4k
    CG(memoize_mode) = ZEND_MEMOIZE_NONE;
2595
55.4k
    zend_compile_expr(result, expr);
2596
55.4k
    CG(memoize_mode) = ZEND_MEMOIZE_COMPILE;
2597
2598
55.4k
    if (result->op_type == IS_VAR) {
2599
1.17k
      zend_emit_op(&memoized_result, ZEND_COPY_TMP, result, NULL);
2600
54.2k
    } else if (result->op_type == IS_TMP_VAR) {
2601
44.5k
      zend_emit_op_tmp(&memoized_result, ZEND_COPY_TMP, result, NULL);
2602
44.5k
    } else {
2603
9.68k
      if (result->op_type == IS_CONST) {
2604
8.94k
        Z_TRY_ADDREF(result->u.constant);
2605
8.94k
      }
2606
9.68k
      memoized_result = *result;
2607
9.68k
    }
2608
2609
55.4k
    zend_hash_index_update_mem(
2610
55.4k
      CG(memoized_exprs), (uintptr_t) expr, &memoized_result, sizeof(znode));
2611
55.4k
  } else if (memoize_mode == ZEND_MEMOIZE_FETCH) {
2612
53.6k
    znode *memoized_result = zend_hash_index_find_ptr(CG(memoized_exprs), (uintptr_t) expr);
2613
53.6k
    *result = *memoized_result;
2614
53.6k
    if (result->op_type == IS_CONST) {
2615
7.93k
      Z_TRY_ADDREF(result->u.constant);
2616
7.93k
    }
2617
53.6k
  } else {
2618
0
    ZEND_UNREACHABLE();
2619
0
  }
2620
109k
}
2621
/* }}} */
2622
2623
static void zend_emit_return_type_check(
2624
    znode *expr, zend_arg_info *return_info, bool implicit) /* {{{ */
2625
22.3k
{
2626
22.3k
  zend_type type = return_info->type;
2627
22.3k
  if (ZEND_TYPE_IS_SET(type)) {
2628
22.3k
    zend_op *opline;
2629
2630
    /* `return ...;` is illegal in a void function (but `return;` isn't) */
2631
22.3k
    if (ZEND_TYPE_CONTAINS_CODE(type, IS_VOID)) {
2632
4.60k
      if (expr) {
2633
18
        if (expr->op_type == IS_CONST && Z_TYPE(expr->u.constant) == IS_NULL) {
2634
6
          zend_error_noreturn(E_COMPILE_ERROR,
2635
6
            "A void %s must not return a value "
2636
6
            "(did you mean \"return;\" instead of \"return null;\"?)",
2637
6
            CG(active_class_entry) != NULL ? "method" : "function");
2638
12
        } else {
2639
12
          zend_error_noreturn(E_COMPILE_ERROR, "A void %s must not return a value",
2640
12
          CG(active_class_entry) != NULL ? "method" : "function");
2641
12
        }
2642
18
      }
2643
      /* we don't need run-time check */
2644
4.58k
      return;
2645
4.60k
    }
2646
2647
    /* `return` is illegal in a never-returning function */
2648
17.7k
    if (ZEND_TYPE_CONTAINS_CODE(type, IS_NEVER)) {
2649
      /* Implicit case handled separately using VERIFY_NEVER_TYPE opcode. */
2650
14
      ZEND_ASSERT(!implicit);
2651
14
      zend_error_noreturn(E_COMPILE_ERROR, "A never-returning %s must not return",
2652
14
        CG(active_class_entry) != NULL ? "method" : "function");
2653
0
      return;
2654
14
    }
2655
2656
17.6k
    if (!expr && !implicit) {
2657
12
      if (ZEND_TYPE_ALLOW_NULL(type)) {
2658
6
        zend_error_noreturn(E_COMPILE_ERROR,
2659
6
          "A %s with return type must return a value "
2660
6
          "(did you mean \"return null;\" instead of \"return;\"?)",
2661
6
          CG(active_class_entry) != NULL ? "method" : "function");
2662
6
      } else {
2663
6
        zend_error_noreturn(E_COMPILE_ERROR,
2664
6
          "A %s with return type must return a value",
2665
6
          CG(active_class_entry) != NULL ? "method" : "function");
2666
6
      }
2667
12
    }
2668
2669
17.6k
    if (expr && ZEND_TYPE_PURE_MASK(type) == MAY_BE_ANY) {
2670
      /* we don't need run-time check for mixed return type */
2671
470
      return;
2672
470
    }
2673
2674
17.2k
    if (expr && expr->op_type == IS_CONST && ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(expr->u.constant))) {
2675
      /* we don't need run-time check */
2676
1.08k
      return;
2677
1.08k
    }
2678
2679
16.1k
    opline = zend_emit_op(NULL, ZEND_VERIFY_RETURN_TYPE, expr, NULL);
2680
16.1k
    if (expr && expr->op_type == IS_CONST) {
2681
281
      opline->result_type = expr->op_type = IS_TMP_VAR;
2682
281
      opline->result.var = expr->u.op.var = get_temporary_variable();
2683
281
    }
2684
16.1k
  }
2685
22.3k
}
2686
/* }}} */
2687
2688
void zend_emit_final_return(bool return_one) /* {{{ */
2689
189k
{
2690
189k
  znode zn;
2691
189k
  zend_op *ret;
2692
189k
  bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
2693
2694
189k
  if ((CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)
2695
189k
      && !(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR)) {
2696
16.9k
    zend_arg_info *return_info = CG(active_op_array)->arg_info - 1;
2697
2698
16.9k
    if (ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_NEVER)) {
2699
457
      zend_emit_op(NULL, ZEND_VERIFY_NEVER_TYPE, NULL, NULL);
2700
457
      return;
2701
457
    }
2702
2703
16.5k
    zend_emit_return_type_check(NULL, return_info, 1);
2704
16.5k
  }
2705
2706
189k
  zn.op_type = IS_CONST;
2707
189k
  if (return_one) {
2708
94.4k
    ZVAL_LONG(&zn.u.constant, 1);
2709
94.7k
  } else {
2710
94.7k
    ZVAL_NULL(&zn.u.constant);
2711
94.7k
  }
2712
2713
189k
  ret = zend_emit_op(NULL, returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN, &zn, NULL);
2714
189k
  ret->extended_value = -1;
2715
189k
}
2716
/* }}} */
2717
2718
static inline bool zend_is_variable(zend_ast *ast) /* {{{ */
2719
414k
{
2720
414k
  return ast->kind == ZEND_AST_VAR
2721
414k
    || ast->kind == ZEND_AST_DIM
2722
414k
    || ast->kind == ZEND_AST_PROP
2723
414k
    || ast->kind == ZEND_AST_NULLSAFE_PROP
2724
414k
    || ast->kind == ZEND_AST_STATIC_PROP;
2725
414k
}
2726
/* }}} */
2727
2728
static inline bool zend_is_call(zend_ast *ast) /* {{{ */
2729
525k
{
2730
525k
  return ast->kind == ZEND_AST_CALL
2731
525k
    || ast->kind == ZEND_AST_METHOD_CALL
2732
525k
    || ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL
2733
525k
    || ast->kind == ZEND_AST_STATIC_CALL;
2734
525k
}
2735
/* }}} */
2736
2737
static inline bool zend_is_variable_or_call(zend_ast *ast) /* {{{ */
2738
31.3k
{
2739
31.3k
  return zend_is_variable(ast) || zend_is_call(ast);
2740
31.3k
}
2741
/* }}} */
2742
2743
static inline bool zend_is_unticked_stmt(zend_ast *ast) /* {{{ */
2744
2.42k
{
2745
2.42k
  return ast->kind == ZEND_AST_STMT_LIST || ast->kind == ZEND_AST_LABEL
2746
2.42k
    || ast->kind == ZEND_AST_PROP_DECL || ast->kind == ZEND_AST_CLASS_CONST_GROUP
2747
2.42k
    || ast->kind == ZEND_AST_USE_TRAIT || ast->kind == ZEND_AST_METHOD;
2748
2.42k
}
2749
/* }}} */
2750
2751
static inline bool zend_can_write_to_variable(zend_ast *ast) /* {{{ */
2752
28.5k
{
2753
28.5k
  while (
2754
31.2k
    ast->kind == ZEND_AST_DIM
2755
31.2k
    || ast->kind == ZEND_AST_PROP
2756
28.5k
  ) {
2757
2.73k
    ast = ast->child[0];
2758
2.73k
  }
2759
2760
28.5k
  return zend_is_variable_or_call(ast) && !zend_ast_is_short_circuited(ast);
2761
28.5k
}
2762
/* }}} */
2763
2764
static inline bool zend_is_const_default_class_ref(zend_ast *name_ast) /* {{{ */
2765
52.6k
{
2766
52.6k
  if (name_ast->kind != ZEND_AST_ZVAL) {
2767
0
    return 0;
2768
0
  }
2769
2770
52.6k
  return ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type_ast(name_ast);
2771
52.6k
}
2772
/* }}} */
2773
2774
static inline void zend_handle_numeric_op(znode *node) /* {{{ */
2775
5.18k
{
2776
5.18k
  if (node->op_type == IS_CONST && Z_TYPE(node->u.constant) == IS_STRING) {
2777
2.62k
    zend_ulong index;
2778
2779
2.62k
    if (ZEND_HANDLE_NUMERIC(Z_STR(node->u.constant), index)) {
2780
323
      zval_ptr_dtor(&node->u.constant);
2781
323
      ZVAL_LONG(&node->u.constant, index);
2782
323
    }
2783
2.62k
  }
2784
5.18k
}
2785
/* }}} */
2786
2787
static inline void zend_handle_numeric_dim(zend_op *opline, znode *dim_node) /* {{{ */
2788
42.0k
{
2789
42.0k
  if (Z_TYPE(dim_node->u.constant) == IS_STRING) {
2790
18.2k
    zend_ulong index;
2791
2792
18.2k
    if (ZEND_HANDLE_NUMERIC(Z_STR(dim_node->u.constant), index)) {
2793
      /* For numeric indexes we also keep the original value to use by ArrayAccess
2794
       * See bug #63217
2795
       */
2796
2.50k
      int c = zend_add_literal(&dim_node->u.constant);
2797
2.50k
      ZEND_ASSERT(opline->op2.constant + 1 == c);
2798
2.50k
      ZVAL_LONG(CT_CONSTANT(opline->op2), index);
2799
2.50k
      Z_EXTRA_P(CT_CONSTANT(opline->op2)) = ZEND_EXTRA_VALUE;
2800
2.50k
      return;
2801
2.50k
    }
2802
18.2k
  }
2803
42.0k
}
2804
/* }}} */
2805
2806
static inline void zend_set_class_name_op1(zend_op *opline, znode *class_node) /* {{{ */
2807
38.6k
{
2808
38.6k
  if (class_node->op_type == IS_CONST) {
2809
17.5k
    opline->op1_type = IS_CONST;
2810
17.5k
    opline->op1.constant = zend_add_class_name_literal(
2811
17.5k
      Z_STR(class_node->u.constant));
2812
21.0k
  } else {
2813
21.0k
    SET_NODE(opline->op1, class_node);
2814
21.0k
  }
2815
38.6k
}
2816
/* }}} */
2817
2818
static void zend_compile_class_ref(znode *result, zend_ast *name_ast, uint32_t fetch_flags) /* {{{ */
2819
137k
{
2820
137k
  uint32_t fetch_type;
2821
2822
137k
  if (name_ast->kind != ZEND_AST_ZVAL) {
2823
23.9k
    znode name_node;
2824
2825
23.9k
    zend_compile_expr(&name_node, name_ast);
2826
2827
23.9k
    if (name_node.op_type == IS_CONST) {
2828
829
      zend_string *name;
2829
2830
829
      if (Z_TYPE(name_node.u.constant) != IS_STRING) {
2831
8
        zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
2832
8
      }
2833
2834
821
      name = Z_STR(name_node.u.constant);
2835
821
      fetch_type = zend_get_class_fetch_type(name);
2836
2837
821
      if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
2838
554
        result->op_type = IS_CONST;
2839
554
        ZVAL_STR(&result->u.constant, zend_resolve_class_name(name, ZEND_NAME_FQ));
2840
554
      } else {
2841
267
        zend_ensure_valid_class_fetch_type(fetch_type);
2842
267
        result->op_type = IS_UNUSED;
2843
267
        result->u.op.num = fetch_type | fetch_flags;
2844
267
      }
2845
2846
821
      zend_string_release_ex(name, 0);
2847
23.1k
    } else {
2848
23.1k
      zend_op *opline = zend_emit_op(result, ZEND_FETCH_CLASS, NULL, &name_node);
2849
23.1k
      opline->op1.num = ZEND_FETCH_CLASS_DEFAULT | fetch_flags;
2850
23.1k
    }
2851
23.9k
    return;
2852
23.9k
  }
2853
2854
  /* Fully qualified names are always default refs */
2855
113k
  if (name_ast->attr == ZEND_NAME_FQ) {
2856
3.15k
    result->op_type = IS_CONST;
2857
3.15k
    ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast));
2858
3.15k
    return;
2859
3.15k
  }
2860
2861
109k
  fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
2862
109k
  if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
2863
105k
    result->op_type = IS_CONST;
2864
105k
    ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast));
2865
105k
  } else {
2866
4.49k
    zend_ensure_valid_class_fetch_type(fetch_type);
2867
4.49k
    result->op_type = IS_UNUSED;
2868
4.49k
    result->u.op.num = fetch_type | fetch_flags;
2869
4.49k
  }
2870
109k
}
2871
/* }}} */
2872
2873
static zend_result zend_try_compile_cv(znode *result, zend_ast *ast) /* {{{ */
2874
1.22M
{
2875
1.22M
  zend_ast *name_ast = ast->child[0];
2876
1.22M
  if (name_ast->kind == ZEND_AST_ZVAL) {
2877
1.09M
    zval *zv = zend_ast_get_zval(name_ast);
2878
1.09M
    zend_string *name;
2879
2880
1.09M
    if (EXPECTED(Z_TYPE_P(zv) == IS_STRING)) {
2881
1.08M
      name = zval_make_interned_string(zv);
2882
1.08M
    } else {
2883
5.63k
      name = zend_new_interned_string(zval_get_string_func(zv));
2884
5.63k
    }
2885
2886
1.09M
    if (zend_is_auto_global(name)) {
2887
875
      return FAILURE;
2888
875
    }
2889
2890
1.08M
    result->op_type = IS_CV;
2891
1.08M
    result->u.op.var = lookup_cv(name);
2892
2893
1.08M
    if (UNEXPECTED(Z_TYPE_P(zv) != IS_STRING)) {
2894
5.63k
      zend_string_release_ex(name, 0);
2895
5.63k
    }
2896
2897
1.08M
    return SUCCESS;
2898
1.09M
  }
2899
2900
131k
  return FAILURE;
2901
1.22M
}
2902
/* }}} */
2903
2904
static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint32_t type, bool delayed) /* {{{ */
2905
131k
{
2906
131k
  zend_ast *name_ast = ast->child[0];
2907
131k
  znode name_node;
2908
131k
  zend_op *opline;
2909
2910
131k
  zend_compile_expr(&name_node, name_ast);
2911
131k
  if (name_node.op_type == IS_CONST) {
2912
4.02k
    convert_to_string(&name_node.u.constant);
2913
4.02k
  }
2914
2915
131k
  if (delayed) {
2916
10.6k
    opline = zend_delayed_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
2917
120k
  } else {
2918
120k
    opline = zend_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
2919
120k
  }
2920
2921
131k
  if (name_node.op_type == IS_CONST &&
2922
131k
      zend_is_auto_global(Z_STR(name_node.u.constant))) {
2923
2924
856
    opline->extended_value = ZEND_FETCH_GLOBAL;
2925
130k
  } else {
2926
130k
    opline->extended_value = ZEND_FETCH_LOCAL;
2927
130k
  }
2928
2929
131k
  zend_adjust_for_fetch_type(opline, result, type);
2930
131k
  return opline;
2931
131k
}
2932
/* }}} */
2933
2934
static bool is_this_fetch(zend_ast *ast) /* {{{ */
2935
1.69M
{
2936
1.69M
  if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) {
2937
1.47M
    zval *name = zend_ast_get_zval(ast->child[0]);
2938
1.47M
    return Z_TYPE_P(name) == IS_STRING && zend_string_equals(Z_STR_P(name), ZSTR_KNOWN(ZEND_STR_THIS));
2939
1.47M
  }
2940
2941
223k
  return 0;
2942
1.69M
}
2943
/* }}} */
2944
2945
static bool is_globals_fetch(const zend_ast *ast)
2946
2.16M
{
2947
2.16M
  if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) {
2948
1.61M
    zval *name = zend_ast_get_zval(ast->child[0]);
2949
1.61M
    return Z_TYPE_P(name) == IS_STRING && zend_string_equals_literal(Z_STR_P(name), "GLOBALS");
2950
1.61M
  }
2951
2952
552k
  return 0;
2953
2.16M
}
2954
2955
static bool is_global_var_fetch(zend_ast *ast)
2956
498k
{
2957
498k
  return ast->kind == ZEND_AST_DIM && is_globals_fetch(ast->child[0]);
2958
498k
}
2959
2960
static bool this_guaranteed_exists(void) /* {{{ */
2961
9.69k
{
2962
9.69k
  zend_oparray_context *ctx = &CG(context);
2963
10.4k
  while (ctx) {
2964
    /* Instance methods always have a $this.
2965
     * This also includes closures that have a scope and use $this. */
2966
10.4k
    zend_op_array *op_array = ctx->op_array;
2967
10.4k
    if (op_array->fn_flags & ZEND_ACC_STATIC) {
2968
208
      return false;
2969
10.2k
    } else if (op_array->scope) {
2970
8.78k
      return true;
2971
8.78k
    } else if (!(op_array->fn_flags & ZEND_ACC_CLOSURE)) {
2972
701
      return false;
2973
701
    }
2974
742
    ctx = ctx->prev;
2975
742
  }
2976
0
  return false;
2977
9.69k
}
2978
/* }}} */
2979
2980
static zend_op *zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type, bool delayed) /* {{{ */
2981
1.11M
{
2982
1.11M
  if (is_this_fetch(ast)) {
2983
2.30k
    zend_op *opline = zend_emit_op(result, ZEND_FETCH_THIS, NULL, NULL);
2984
2.30k
    if ((type == BP_VAR_R) || (type == BP_VAR_IS)) {
2985
2.21k
      opline->result_type = IS_TMP_VAR;
2986
2.21k
      result->op_type = IS_TMP_VAR;
2987
2.21k
    }
2988
2.30k
    CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
2989
2.30k
    return opline;
2990
1.11M
  } else if (is_globals_fetch(ast)) {
2991
1.92k
    zend_op *opline = zend_emit_op(result, ZEND_FETCH_GLOBALS, NULL, NULL);
2992
1.92k
    if (type == BP_VAR_R || type == BP_VAR_IS) {
2993
1.72k
      opline->result_type = IS_TMP_VAR;
2994
1.72k
      result->op_type = IS_TMP_VAR;
2995
1.72k
    }
2996
1.92k
    return opline;
2997
1.11M
  } else if (zend_try_compile_cv(result, ast) == FAILURE) {
2998
130k
    return zend_compile_simple_var_no_cv(result, ast, type, delayed);
2999
130k
  }
3000
980k
  return NULL;
3001
1.11M
}
3002
/* }}} */
3003
3004
static void zend_separate_if_call_and_write(znode *node, zend_ast *ast, uint32_t type) /* {{{ */
3005
252k
{
3006
252k
  if (type != BP_VAR_R
3007
252k
   && type != BP_VAR_IS
3008
   /* Whether a FUNC_ARG is R may only be determined at runtime. */
3009
252k
   && type != BP_VAR_FUNC_ARG
3010
252k
   && zend_is_call(ast)) {
3011
2.94k
    if (node->op_type == IS_VAR) {
3012
2.93k
      zend_op *opline = zend_emit_op(NULL, ZEND_SEPARATE, node, NULL);
3013
2.93k
      opline->result_type = IS_VAR;
3014
2.93k
      opline->result.var = opline->op1.var;
3015
2.93k
    } else {
3016
14
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context");
3017
14
    }
3018
2.94k
  }
3019
252k
}
3020
/* }}} */
3021
3022
static inline void zend_emit_assign_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
3023
6.07k
{
3024
6.07k
  znode dummy_node;
3025
6.07k
  zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN, var_ast,
3026
6.07k
    zend_ast_create_znode(value_node));
3027
6.07k
  zend_compile_expr(&dummy_node, assign_ast);
3028
6.07k
  zend_do_free(&dummy_node);
3029
6.07k
}
3030
/* }}} */
3031
3032
static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t type, bool by_ref)
3033
142k
{
3034
142k
  zend_ast *var_ast = ast->child[0];
3035
142k
  zend_ast *dim_ast = ast->child[1];
3036
142k
  zend_op *opline;
3037
3038
142k
  znode var_node, dim_node;
3039
3040
142k
  if (is_globals_fetch(var_ast)) {
3041
2.77k
    if (dim_ast == NULL) {
3042
11
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot append to $GLOBALS");
3043
11
    }
3044
3045
2.76k
    zend_compile_expr(&dim_node, dim_ast);
3046
2.76k
    if (dim_node.op_type == IS_CONST) {
3047
2.41k
      convert_to_string(&dim_node.u.constant);
3048
2.41k
    }
3049
3050
2.76k
    opline = zend_delayed_emit_op(result, ZEND_FETCH_R, &dim_node, NULL);
3051
2.76k
    opline->extended_value = ZEND_FETCH_GLOBAL;
3052
2.76k
    zend_adjust_for_fetch_type(opline, result, type);
3053
2.76k
    return opline;
3054
140k
  } else {
3055
140k
    zend_short_circuiting_mark_inner(var_ast);
3056
140k
    opline = zend_delayed_compile_var(&var_node, var_ast, type, 0);
3057
140k
    if (opline) {
3058
92.7k
      if (type == BP_VAR_W && (opline->opcode == ZEND_FETCH_STATIC_PROP_W || opline->opcode == ZEND_FETCH_OBJ_W)) {
3059
1.99k
        opline->extended_value |= ZEND_FETCH_DIM_WRITE;
3060
90.7k
      } else if (opline->opcode == ZEND_FETCH_DIM_W
3061
90.7k
          || opline->opcode == ZEND_FETCH_DIM_RW
3062
90.7k
          || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG
3063
90.7k
          || opline->opcode == ZEND_FETCH_DIM_UNSET) {
3064
41.6k
        opline->extended_value = ZEND_FETCH_DIM_DIM;
3065
41.6k
      }
3066
92.7k
    }
3067
140k
  }
3068
3069
140k
  zend_separate_if_call_and_write(&var_node, var_ast, type);
3070
3071
140k
  if (dim_ast == NULL) {
3072
9.98k
    if (type == BP_VAR_R || type == BP_VAR_IS) {
3073
409
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
3074
409
    }
3075
9.57k
    if (type == BP_VAR_UNSET) {
3076
20
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting");
3077
20
    }
3078
9.55k
    dim_node.op_type = IS_UNUSED;
3079
130k
  } else {
3080
130k
    zend_compile_expr(&dim_node, dim_ast);
3081
130k
  }
3082
3083
139k
  opline = zend_delayed_emit_op(result, ZEND_FETCH_DIM_R, &var_node, &dim_node);
3084
139k
  zend_adjust_for_fetch_type(opline, result, type);
3085
139k
  if (by_ref) {
3086
5.21k
    opline->extended_value = ZEND_FETCH_DIM_REF;
3087
5.21k
  }
3088
3089
139k
  if (dim_node.op_type == IS_CONST) {
3090
27.5k
    zend_handle_numeric_dim(opline, &dim_node);
3091
27.5k
  }
3092
139k
  return opline;
3093
140k
}
3094
3095
static zend_op *zend_compile_dim(znode *result, zend_ast *ast, uint32_t type, bool by_ref) /* {{{ */
3096
40.4k
{
3097
40.4k
  uint32_t offset = zend_delayed_compile_begin();
3098
40.4k
  zend_delayed_compile_dim(result, ast, type, by_ref);
3099
40.4k
  return zend_delayed_compile_end(offset);
3100
40.4k
}
3101
/* }}} */
3102
3103
static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
3104
120k
{
3105
120k
  zend_ast *obj_ast = ast->child[0];
3106
120k
  zend_ast *prop_ast = ast->child[1];
3107
3108
120k
  znode obj_node, prop_node;
3109
120k
  zend_op *opline;
3110
120k
  bool nullsafe = ast->kind == ZEND_AST_NULLSAFE_PROP;
3111
3112
120k
  if (is_this_fetch(obj_ast)) {
3113
8.73k
    if (this_guaranteed_exists()) {
3114
7.95k
      obj_node.op_type = IS_UNUSED;
3115
7.95k
    } else {
3116
787
      zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL);
3117
787
    }
3118
8.73k
    CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
3119
3120
    /* We will throw if $this doesn't exist, so there's no need to emit a JMP_NULL
3121
     * check for a nullsafe access. */
3122
111k
  } else {
3123
111k
    zend_short_circuiting_mark_inner(obj_ast);
3124
111k
    opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0);
3125
111k
    if (opline && (opline->opcode == ZEND_FETCH_DIM_W
3126
22.6k
        || opline->opcode == ZEND_FETCH_DIM_RW
3127
22.6k
        || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG
3128
22.6k
        || opline->opcode == ZEND_FETCH_DIM_UNSET)) {
3129
1.19k
      opline->extended_value = ZEND_FETCH_DIM_OBJ;
3130
1.19k
    }
3131
3132
111k
    zend_separate_if_call_and_write(&obj_node, obj_ast, type);
3133
111k
    if (nullsafe) {
3134
52.0k
      if (obj_node.op_type == IS_TMP_VAR) {
3135
        /* Flush delayed oplines */
3136
4.11k
        zend_op *opline = NULL, *oplines = zend_stack_base(&CG(delayed_oplines_stack));
3137
4.11k
        uint32_t var = obj_node.u.op.var;
3138
4.11k
        uint32_t count = zend_stack_count(&CG(delayed_oplines_stack));
3139
4.11k
        uint32_t i = count;
3140
3141
482k
        while (i > 0 && oplines[i-1].result_type == IS_TMP_VAR && oplines[i-1].result.var == var) {
3142
479k
          i--;
3143
479k
          if (oplines[i].op1_type == IS_TMP_VAR) {
3144
478k
            var = oplines[i].op1.var;
3145
478k
          } else {
3146
507
            break;
3147
507
          }
3148
479k
        }
3149
483k
        for (; i < count; ++i) {
3150
479k
          if (oplines[i].opcode != ZEND_NOP) {
3151
3.67k
            opline = get_next_op();
3152
3.67k
            memcpy(opline, &oplines[i], sizeof(zend_op));
3153
3.67k
            oplines[i].opcode = ZEND_NOP;
3154
3.67k
            oplines[i].extended_value = opline - CG(active_op_array)->opcodes;
3155
3.67k
          }
3156
479k
        }
3157
4.11k
      }
3158
52.0k
      zend_emit_jmp_null(&obj_node, type);
3159
52.0k
    }
3160
111k
  }
3161
3162
120k
  zend_compile_expr(&prop_node, prop_ast);
3163
3164
120k
  opline = zend_delayed_emit_op(result, ZEND_FETCH_OBJ_R, &obj_node, &prop_node);
3165
120k
  if (opline->op2_type == IS_CONST) {
3166
117k
    convert_to_string(CT_CONSTANT(opline->op2));
3167
117k
    zend_string_hash_val(Z_STR_P(CT_CONSTANT(opline->op2)));
3168
117k
    opline->extended_value = zend_alloc_cache_slots(3);
3169
117k
  }
3170
3171
120k
  zend_adjust_for_fetch_type(opline, result, type);
3172
3173
120k
  return opline;
3174
120k
}
3175
/* }}} */
3176
3177
static zend_op *zend_compile_prop(znode *result, zend_ast *ast, uint32_t type, bool by_ref) /* {{{ */
3178
86.9k
{
3179
86.9k
  uint32_t offset = zend_delayed_compile_begin();
3180
86.9k
  zend_op *opline = zend_delayed_compile_prop(result, ast, type);
3181
86.9k
  if (by_ref) { /* shared with cache_slot */
3182
3.45k
    opline->extended_value |= ZEND_FETCH_REF;
3183
3.45k
  }
3184
86.9k
  return zend_delayed_compile_end(offset);
3185
86.9k
}
3186
/* }}} */
3187
3188
static zend_op *zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, bool by_ref, bool delayed) /* {{{ */
3189
15.5k
{
3190
15.5k
  zend_ast *class_ast = ast->child[0];
3191
15.5k
  zend_ast *prop_ast = ast->child[1];
3192
3193
15.5k
  znode class_node, prop_node;
3194
15.5k
  zend_op *opline;
3195
3196
15.5k
  zend_short_circuiting_mark_inner(class_ast);
3197
15.5k
  zend_compile_class_ref(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
3198
3199
15.5k
  zend_compile_expr(&prop_node, prop_ast);
3200
3201
15.5k
  if (delayed) {
3202
5.96k
    opline = zend_delayed_emit_op(result, ZEND_FETCH_STATIC_PROP_R, &prop_node, NULL);
3203
9.56k
  } else {
3204
9.56k
    opline = zend_emit_op(result, ZEND_FETCH_STATIC_PROP_R, &prop_node, NULL);
3205
9.56k
  }
3206
15.5k
  if (opline->op1_type == IS_CONST) {
3207
12.7k
    convert_to_string(CT_CONSTANT(opline->op1));
3208
12.7k
    opline->extended_value = zend_alloc_cache_slots(3);
3209
12.7k
  }
3210
15.5k
  if (class_node.op_type == IS_CONST) {
3211
10.6k
    opline->op2_type = IS_CONST;
3212
10.6k
    opline->op2.constant = zend_add_class_name_literal(
3213
10.6k
      Z_STR(class_node.u.constant));
3214
10.6k
    if (opline->op1_type != IS_CONST) {
3215
2.08k
      opline->extended_value = zend_alloc_cache_slot();
3216
2.08k
    }
3217
10.6k
  } else {
3218
4.92k
    SET_NODE(opline->op2, &class_node);
3219
4.92k
  }
3220
3221
15.5k
  if (by_ref && (type == BP_VAR_W || type == BP_VAR_FUNC_ARG)) { /* shared with cache_slot */
3222
1.48k
    opline->extended_value |= ZEND_FETCH_REF;
3223
1.48k
  }
3224
3225
15.5k
  zend_adjust_for_fetch_type(opline, result, type);
3226
15.5k
  return opline;
3227
15.5k
}
3228
/* }}} */
3229
3230
14.9k
static void zend_verify_list_assign_target(zend_ast *var_ast, zend_ast_attr array_style) /* {{{ */ {
3231
14.9k
  if (var_ast->kind == ZEND_AST_ARRAY) {
3232
3.24k
    if (var_ast->attr == ZEND_ARRAY_SYNTAX_LONG) {
3233
6
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot assign to array(), use [] instead");
3234
6
    }
3235
3.24k
    if (array_style != var_ast->attr) {
3236
6
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix [] and list()");
3237
6
    }
3238
11.6k
  } else if (!zend_can_write_to_variable(var_ast)) {
3239
131
    zend_error_noreturn(E_COMPILE_ERROR, "Assignments can only happen to writable values");
3240
131
  }
3241
14.9k
}
3242
/* }}} */
3243
3244
static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node);
3245
3246
/* Propagate refs used on leaf elements to the surrounding list() structures. */
3247
8.90k
static bool zend_propagate_list_refs(zend_ast *ast) { /* {{{ */
3248
8.90k
  zend_ast_list *list = zend_ast_get_list(ast);
3249
8.90k
  bool has_refs = 0;
3250
8.90k
  uint32_t i;
3251
3252
42.9k
  for (i = 0; i < list->children; ++i) {
3253
34.0k
    zend_ast *elem_ast = list->child[i];
3254
3255
34.0k
    if (elem_ast) {
3256
16.4k
      zend_ast *var_ast = elem_ast->child[0];
3257
16.4k
      if (var_ast->kind == ZEND_AST_ARRAY) {
3258
3.84k
        elem_ast->attr = zend_propagate_list_refs(var_ast);
3259
3.84k
      }
3260
16.4k
      has_refs |= elem_ast->attr;
3261
16.4k
    }
3262
34.0k
  }
3263
3264
8.90k
  return has_refs;
3265
8.90k
}
3266
/* }}} */
3267
3268
static bool list_is_keyed(zend_ast_list *list)
3269
8.18k
{
3270
9.72k
  for (uint32_t i = 0; i < list->children; i++) {
3271
9.67k
    zend_ast *child = list->child[i];
3272
9.67k
    if (child) {
3273
8.13k
      return child->kind == ZEND_AST_ARRAY_ELEM && child->child[1] != NULL;
3274
8.13k
    }
3275
9.67k
  }
3276
49
  return false;
3277
8.18k
}
3278
3279
static void zend_compile_list_assign(
3280
    znode *result, zend_ast *ast, znode *expr_node, zend_ast_attr array_style) /* {{{ */
3281
8.18k
{
3282
8.18k
  zend_ast_list *list = zend_ast_get_list(ast);
3283
8.18k
  uint32_t i;
3284
8.18k
  bool has_elems = 0;
3285
8.18k
  bool is_keyed = list_is_keyed(list);
3286
3287
8.18k
  if (list->children && expr_node->op_type == IS_CONST && Z_TYPE(expr_node->u.constant) == IS_STRING) {
3288
221
    zval_make_interned_string(&expr_node->u.constant);
3289
221
  }
3290
3291
24.7k
  for (i = 0; i < list->children; ++i) {
3292
16.5k
    zend_ast *elem_ast = list->child[i];
3293
16.5k
    zend_ast *var_ast, *key_ast;
3294
16.5k
    znode fetch_result, dim_node;
3295
16.5k
    zend_op *opline;
3296
3297
16.5k
    if (elem_ast == NULL) {
3298
1.57k
      if (is_keyed) {
3299
17
        zend_error(E_COMPILE_ERROR,
3300
17
          "Cannot use empty array entries in keyed array assignment");
3301
1.55k
      } else {
3302
1.55k
        continue;
3303
1.55k
      }
3304
1.57k
    }
3305
3306
14.9k
    if (elem_ast->kind == ZEND_AST_UNPACK) {
3307
17
      zend_error(E_COMPILE_ERROR,
3308
17
          "Spread operator is not supported in assignments");
3309
17
    }
3310
3311
14.9k
    var_ast = elem_ast->child[0];
3312
14.9k
    key_ast = elem_ast->child[1];
3313
14.9k
    has_elems = 1;
3314
3315
14.9k
    if (is_keyed) {
3316
6.52k
      if (key_ast == NULL) {
3317
14
        zend_error(E_COMPILE_ERROR,
3318
14
          "Cannot mix keyed and unkeyed array entries in assignments");
3319
14
      }
3320
3321
6.52k
      zend_compile_expr(&dim_node, key_ast);
3322
8.43k
    } else {
3323
8.43k
      if (key_ast != NULL) {
3324
6
        zend_error(E_COMPILE_ERROR,
3325
6
          "Cannot mix keyed and unkeyed array entries in assignments");
3326
6
      }
3327
3328
8.43k
      dim_node.op_type = IS_CONST;
3329
8.43k
      ZVAL_LONG(&dim_node.u.constant, i);
3330
8.43k
    }
3331
3332
14.9k
    if (expr_node->op_type == IS_CONST) {
3333
1.21k
      Z_TRY_ADDREF(expr_node->u.constant);
3334
1.21k
    }
3335
3336
14.9k
    zend_verify_list_assign_target(var_ast, array_style);
3337
3338
14.9k
    opline = zend_emit_op(&fetch_result,
3339
14.9k
      elem_ast->attr ? (expr_node->op_type == IS_CV ? ZEND_FETCH_DIM_W : ZEND_FETCH_LIST_W) : ZEND_FETCH_LIST_R, expr_node, &dim_node);
3340
3341
14.9k
    if (dim_node.op_type == IS_CONST) {
3342
14.5k
      zend_handle_numeric_dim(opline, &dim_node);
3343
14.5k
    }
3344
3345
14.9k
    if (elem_ast->attr) {
3346
9.79k
      zend_emit_op(&fetch_result, ZEND_MAKE_REF, &fetch_result, NULL);
3347
9.79k
    }
3348
14.9k
    if (var_ast->kind == ZEND_AST_ARRAY) {
3349
3.23k
      zend_compile_list_assign(NULL, var_ast, &fetch_result, var_ast->attr);
3350
11.7k
    } else if (elem_ast->attr) {
3351
7.04k
      zend_emit_assign_ref_znode(var_ast, &fetch_result);
3352
7.04k
    } else {
3353
4.67k
      zend_emit_assign_znode(var_ast, &fetch_result);
3354
4.67k
    }
3355
14.9k
  }
3356
3357
8.18k
  if (has_elems == 0) {
3358
49
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list");
3359
49
  }
3360
3361
8.13k
  if (result) {
3362
4.34k
    *result = *expr_node;
3363
4.34k
  } else {
3364
3.79k
    zend_do_free(expr_node);
3365
3.79k
  }
3366
8.13k
}
3367
/* }}} */
3368
3369
static void zend_ensure_writable_variable(const zend_ast *ast) /* {{{ */
3370
524k
{
3371
524k
  if (ast->kind == ZEND_AST_CALL) {
3372
91
    zend_error_noreturn(E_COMPILE_ERROR, "Can't use function return value in write context");
3373
91
  }
3374
523k
  if (
3375
523k
    ast->kind == ZEND_AST_METHOD_CALL
3376
523k
    || ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL
3377
523k
    || ast->kind == ZEND_AST_STATIC_CALL
3378
523k
  ) {
3379
20
    zend_error_noreturn(E_COMPILE_ERROR, "Can't use method return value in write context");
3380
20
  }
3381
523k
  if (zend_ast_is_short_circuited(ast)) {
3382
24
    zend_error_noreturn(E_COMPILE_ERROR, "Can't use nullsafe operator in write context");
3383
24
  }
3384
523k
  if (is_globals_fetch(ast)) {
3385
30
    zend_error_noreturn(E_COMPILE_ERROR,
3386
30
      "$GLOBALS can only be modified using the $GLOBALS[$name] = $value syntax");
3387
30
  }
3388
523k
}
3389
/* }}} */
3390
3391
/* Detects $a... = $a pattern */
3392
static bool zend_is_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast) /* {{{ */
3393
21.3k
{
3394
21.3k
  if (expr_ast->kind != ZEND_AST_VAR || expr_ast->child[0]->kind != ZEND_AST_ZVAL) {
3395
17.6k
    return 0;
3396
17.6k
  }
3397
3398
9.04k
  while (zend_is_variable(var_ast) && var_ast->kind != ZEND_AST_VAR) {
3399
5.34k
    var_ast = var_ast->child[0];
3400
5.34k
  }
3401
3402
3.69k
  if (var_ast->kind != ZEND_AST_VAR || var_ast->child[0]->kind != ZEND_AST_ZVAL) {
3403
413
    return 0;
3404
413
  }
3405
3406
3.27k
  {
3407
3.27k
    zend_string *name1 = zval_get_string(zend_ast_get_zval(var_ast->child[0]));
3408
3.27k
    zend_string *name2 = zval_get_string(zend_ast_get_zval(expr_ast->child[0]));
3409
3.27k
    bool result = zend_string_equals(name1, name2);
3410
3.27k
    zend_string_release_ex(name1, 0);
3411
3.27k
    zend_string_release_ex(name2, 0);
3412
3.27k
    return result;
3413
3.69k
  }
3414
3.69k
}
3415
/* }}} */
3416
3417
static void zend_compile_expr_with_potential_assign_to_self(
3418
21.3k
    znode *expr_node, zend_ast *expr_ast, zend_ast *var_ast) {
3419
21.3k
  if (zend_is_assign_to_self(var_ast, expr_ast) && !is_this_fetch(expr_ast)) {
3420
    /* $a[0] = $a should evaluate the right $a first */
3421
565
    znode cv_node;
3422
3423
565
    if (zend_try_compile_cv(&cv_node, expr_ast) == FAILURE) {
3424
114
      zend_compile_simple_var_no_cv(expr_node, expr_ast, BP_VAR_R, 0);
3425
451
    } else {
3426
451
      zend_emit_op_tmp(expr_node, ZEND_QM_ASSIGN, &cv_node, NULL);
3427
451
    }
3428
20.7k
  } else {
3429
20.7k
    zend_compile_expr(expr_node, expr_ast);
3430
20.7k
  }
3431
21.3k
}
3432
3433
static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
3434
273k
{
3435
273k
  zend_ast *var_ast = ast->child[0];
3436
273k
  zend_ast *expr_ast = ast->child[1];
3437
3438
273k
  znode var_node, expr_node;
3439
273k
  zend_op *opline;
3440
273k
  uint32_t offset;
3441
273k
  if (is_this_fetch(var_ast)) {
3442
11
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
3443
11
  }
3444
3445
273k
  zend_ensure_writable_variable(var_ast);
3446
3447
  /* Treat $GLOBALS['x'] assignment like assignment to variable. */
3448
273k
  zend_ast_kind kind = is_global_var_fetch(var_ast) ? ZEND_AST_VAR : var_ast->kind;
3449
273k
  switch (kind) {
3450
243k
    case ZEND_AST_VAR:
3451
243k
      offset = zend_delayed_compile_begin();
3452
243k
      zend_delayed_compile_var(&var_node, var_ast, BP_VAR_W, 0);
3453
243k
      zend_compile_expr(&expr_node, expr_ast);
3454
243k
      zend_delayed_compile_end(offset);
3455
243k
      CG(zend_lineno) = zend_ast_get_lineno(var_ast);
3456
243k
      zend_emit_op_tmp(result, ZEND_ASSIGN, &var_node, &expr_node);
3457
243k
      return;
3458
1.94k
    case ZEND_AST_STATIC_PROP:
3459
1.94k
      offset = zend_delayed_compile_begin();
3460
1.94k
      zend_delayed_compile_var(result, var_ast, BP_VAR_W, 0);
3461
1.94k
      zend_compile_expr(&expr_node, expr_ast);
3462
3463
1.94k
      opline = zend_delayed_compile_end(offset);
3464
1.94k
      opline->opcode = ZEND_ASSIGN_STATIC_PROP;
3465
1.94k
      opline->result_type = IS_TMP_VAR;
3466
1.94k
      result->op_type = IS_TMP_VAR;
3467
3468
1.94k
      zend_emit_op_data(&expr_node);
3469
1.94k
      return;
3470
12.6k
    case ZEND_AST_DIM:
3471
12.6k
      offset = zend_delayed_compile_begin();
3472
12.6k
      zend_delayed_compile_dim(result, var_ast, BP_VAR_W, /* by_ref */ false);
3473
12.6k
      zend_compile_expr_with_potential_assign_to_self(&expr_node, expr_ast, var_ast);
3474
3475
12.6k
      opline = zend_delayed_compile_end(offset);
3476
12.6k
      opline->opcode = ZEND_ASSIGN_DIM;
3477
12.6k
      opline->result_type = IS_TMP_VAR;
3478
12.6k
      result->op_type = IS_TMP_VAR;
3479
3480
12.6k
      opline = zend_emit_op_data(&expr_node);
3481
12.6k
      return;
3482
10.4k
    case ZEND_AST_PROP:
3483
10.4k
    case ZEND_AST_NULLSAFE_PROP:
3484
10.4k
      offset = zend_delayed_compile_begin();
3485
10.4k
      zend_delayed_compile_prop(result, var_ast, BP_VAR_W);
3486
10.4k
      zend_compile_expr(&expr_node, expr_ast);
3487
3488
10.4k
      opline = zend_delayed_compile_end(offset);
3489
10.4k
      opline->opcode = ZEND_ASSIGN_OBJ;
3490
10.4k
      opline->result_type = IS_TMP_VAR;
3491
10.4k
      result->op_type = IS_TMP_VAR;
3492
3493
10.4k
      zend_emit_op_data(&expr_node);
3494
10.4k
      return;
3495
4.71k
    case ZEND_AST_ARRAY:
3496
4.71k
      if (zend_propagate_list_refs(var_ast)) {
3497
2.85k
        if (!zend_is_variable_or_call(expr_ast)) {
3498
23
          zend_error_noreturn(E_COMPILE_ERROR,
3499
23
            "Cannot assign reference to non referenceable value");
3500
2.82k
        } else {
3501
2.82k
          zend_assert_not_short_circuited(expr_ast);
3502
2.82k
        }
3503
3504
2.82k
        zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1);
3505
        /* MAKE_REF is usually not necessary for CVs. However, if there are
3506
         * self-assignments, this forces the RHS to evaluate first. */
3507
2.82k
        zend_emit_op(&expr_node, ZEND_MAKE_REF, &expr_node, NULL);
3508
2.82k
      } else {
3509
1.86k
        if (expr_ast->kind == ZEND_AST_VAR) {
3510
          /* list($a, $b) = $a should evaluate the right $a first */
3511
533
          znode cv_node;
3512
3513
533
          if (zend_try_compile_cv(&cv_node, expr_ast) == FAILURE) {
3514
107
            zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, 0);
3515
426
          } else {
3516
426
            zend_emit_op_tmp(&expr_node, ZEND_QM_ASSIGN, &cv_node, NULL);
3517
426
          }
3518
1.32k
        } else {
3519
1.32k
          zend_compile_expr(&expr_node, expr_ast);
3520
1.32k
        }
3521
1.86k
      }
3522
3523
4.69k
      zend_compile_list_assign(result, var_ast, &expr_node, var_ast->attr);
3524
4.69k
      return;
3525
0
    EMPTY_SWITCH_DEFAULT_CASE();
3526
273k
  }
3527
273k
}
3528
/* }}} */
3529
3530
static void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
3531
13.5k
{
3532
13.5k
  zend_ast *target_ast = ast->child[0];
3533
13.5k
  zend_ast *source_ast = ast->child[1];
3534
3535
13.5k
  znode target_node, source_node;
3536
13.5k
  zend_op *opline;
3537
13.5k
  uint32_t offset, flags;
3538
3539
13.5k
  if (is_this_fetch(target_ast)) {
3540
6
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
3541
6
  }
3542
13.5k
  zend_ensure_writable_variable(target_ast);
3543
13.5k
  zend_assert_not_short_circuited(source_ast);
3544
13.5k
  if (is_globals_fetch(source_ast)) {
3545
12
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot acquire reference to $GLOBALS");
3546
12
  }
3547
3548
13.5k
  offset = zend_delayed_compile_begin();
3549
13.5k
  zend_delayed_compile_var(&target_node, target_ast, BP_VAR_W, 1);
3550
13.5k
  zend_compile_var(&source_node, source_ast, BP_VAR_W, 1);
3551
3552
13.5k
  if ((target_ast->kind != ZEND_AST_VAR
3553
13.5k
    || target_ast->child[0]->kind != ZEND_AST_ZVAL)
3554
13.5k
   && source_ast->kind != ZEND_AST_ZNODE
3555
13.5k
   && source_node.op_type != IS_CV) {
3556
    /* Both LHS and RHS expressions may modify the same data structure,
3557
     * and the modification during RHS evaluation may dangle the pointer
3558
     * to the result of the LHS evaluation.
3559
     * Use MAKE_REF instruction to replace direct pointer with REFERENCE.
3560
     * See: Bug #71539
3561
     */
3562
1.11k
    zend_emit_op(&source_node, ZEND_MAKE_REF, &source_node, NULL);
3563
1.11k
  }
3564
3565
13.5k
  opline = zend_delayed_compile_end(offset);
3566
3567
13.5k
  if (source_node.op_type != IS_VAR && zend_is_call(source_ast)) {
3568
6
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context");
3569
6
  }
3570
3571
13.5k
  flags = zend_is_call(source_ast) ? ZEND_RETURNS_FUNCTION : 0;
3572
3573
13.5k
  if (opline && opline->opcode == ZEND_FETCH_OBJ_W) {
3574
803
    opline->opcode = ZEND_ASSIGN_OBJ_REF;
3575
803
    opline->extended_value &= ~ZEND_FETCH_REF;
3576
803
    opline->extended_value |= flags;
3577
803
    zend_emit_op_data(&source_node);
3578
803
    *result = target_node;
3579
12.7k
  } else if (opline && opline->opcode == ZEND_FETCH_STATIC_PROP_W) {
3580
477
    opline->opcode = ZEND_ASSIGN_STATIC_PROP_REF;
3581
477
    opline->extended_value &= ~ZEND_FETCH_REF;
3582
477
    opline->extended_value |= flags;
3583
477
    zend_emit_op_data(&source_node);
3584
477
    *result = target_node;
3585
12.2k
  } else {
3586
12.2k
    opline = zend_emit_op(result, ZEND_ASSIGN_REF, &target_node, &source_node);
3587
12.2k
    opline->extended_value = flags;
3588
12.2k
  }
3589
13.5k
}
3590
/* }}} */
3591
3592
static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
3593
8.15k
{
3594
8.15k
  znode dummy_node;
3595
8.15k
  zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN_REF, var_ast,
3596
8.15k
    zend_ast_create_znode(value_node));
3597
8.15k
  zend_compile_expr(&dummy_node, assign_ast);
3598
8.15k
  zend_do_free(&dummy_node);
3599
8.15k
}
3600
/* }}} */
3601
3602
static void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
3603
203k
{
3604
203k
  zend_ast *var_ast = ast->child[0];
3605
203k
  zend_ast *expr_ast = ast->child[1];
3606
203k
  uint32_t opcode = ast->attr;
3607
3608
203k
  znode var_node, expr_node;
3609
203k
  zend_op *opline;
3610
203k
  uint32_t offset, cache_slot;
3611
3612
203k
  zend_ensure_writable_variable(var_ast);
3613
3614
  /* Treat $GLOBALS['x'] assignment like assignment to variable. */
3615
203k
  zend_ast_kind kind = is_global_var_fetch(var_ast) ? ZEND_AST_VAR : var_ast->kind;
3616
203k
  switch (kind) {
3617
199k
    case ZEND_AST_VAR:
3618
199k
      offset = zend_delayed_compile_begin();
3619
199k
      zend_delayed_compile_var(&var_node, var_ast, BP_VAR_RW, 0);
3620
199k
      zend_compile_expr(&expr_node, expr_ast);
3621
199k
      zend_delayed_compile_end(offset);
3622
199k
      opline = zend_emit_op_tmp(result, ZEND_ASSIGN_OP, &var_node, &expr_node);
3623
199k
      opline->extended_value = opcode;
3624
199k
      return;
3625
511
    case ZEND_AST_STATIC_PROP:
3626
511
      offset = zend_delayed_compile_begin();
3627
511
      zend_delayed_compile_var(result, var_ast, BP_VAR_RW, 0);
3628
511
      zend_compile_expr(&expr_node, expr_ast);
3629
3630
511
      opline = zend_delayed_compile_end(offset);
3631
511
      cache_slot = opline->extended_value;
3632
511
      opline->opcode = ZEND_ASSIGN_STATIC_PROP_OP;
3633
511
      opline->extended_value = opcode;
3634
511
      opline->result_type = IS_TMP_VAR;
3635
511
      result->op_type = IS_TMP_VAR;
3636
3637
511
      opline = zend_emit_op_data(&expr_node);
3638
511
      opline->extended_value = cache_slot;
3639
511
      return;
3640
2.59k
    case ZEND_AST_DIM:
3641
2.59k
      offset = zend_delayed_compile_begin();
3642
2.59k
      zend_delayed_compile_dim(result, var_ast, BP_VAR_RW, /* by_ref */ false);
3643
2.59k
      zend_compile_expr_with_potential_assign_to_self(&expr_node, expr_ast, var_ast);
3644
3645
2.59k
      opline = zend_delayed_compile_end(offset);
3646
2.59k
      opline->opcode = ZEND_ASSIGN_DIM_OP;
3647
2.59k
      opline->extended_value = opcode;
3648
2.59k
      opline->result_type = IS_TMP_VAR;
3649
2.59k
      result->op_type = IS_TMP_VAR;
3650
3651
2.59k
      zend_emit_op_data(&expr_node);
3652
2.59k
      return;
3653
874
    case ZEND_AST_PROP:
3654
874
    case ZEND_AST_NULLSAFE_PROP:
3655
874
      offset = zend_delayed_compile_begin();
3656
874
      zend_delayed_compile_prop(result, var_ast, BP_VAR_RW);
3657
874
      zend_compile_expr(&expr_node, expr_ast);
3658
3659
874
      opline = zend_delayed_compile_end(offset);
3660
874
      cache_slot = opline->extended_value;
3661
874
      opline->opcode = ZEND_ASSIGN_OBJ_OP;
3662
874
      opline->extended_value = opcode;
3663
874
      opline->result_type = IS_TMP_VAR;
3664
874
      result->op_type = IS_TMP_VAR;
3665
3666
874
      opline = zend_emit_op_data(&expr_node);
3667
874
      opline->extended_value = cache_slot;
3668
874
      return;
3669
203k
    EMPTY_SWITCH_DEFAULT_CASE()
3670
203k
  }
3671
203k
}
3672
/* }}} */
3673
3674
7.32k
static uint32_t zend_get_arg_num(zend_function *fn, zend_string *arg_name) {
3675
  // TODO: Caching?
3676
7.32k
  if (fn->type == ZEND_USER_FUNCTION) {
3677
7.75k
    for (uint32_t i = 0; i < fn->common.num_args; i++) {
3678
7.20k
      zend_arg_info *arg_info = &fn->op_array.arg_info[i];
3679
7.20k
      if (zend_string_equals(arg_info->name, arg_name)) {
3680
1.22k
        return i + 1;
3681
1.22k
      }
3682
7.20k
    }
3683
5.55k
  } else {
3684
5.55k
    ZEND_ASSERT(fn->common.num_args == 0 || fn->internal_function.arg_info);
3685
16.9k
    for (uint32_t i = 0; i < fn->common.num_args; i++) {
3686
12.4k
      zend_internal_arg_info *arg_info = &fn->internal_function.arg_info[i];
3687
12.4k
      size_t len = strlen(arg_info->name);
3688
12.4k
      if (zend_string_equals_cstr(arg_name, arg_info->name, len)) {
3689
1.11k
        return i + 1;
3690
1.11k
      }
3691
12.4k
    }
3692
5.55k
  }
3693
3694
  /* Either an invalid argument name, or collected into a variadic argument. */
3695
4.99k
  return (uint32_t) -1;
3696
7.32k
}
3697
3698
static uint32_t zend_compile_args(
3699
    zend_ast *ast, zend_function *fbc, bool *may_have_extra_named_args) /* {{{ */
3700
375k
{
3701
375k
  zend_ast_list *args = zend_ast_get_list(ast);
3702
375k
  uint32_t i;
3703
375k
  bool uses_arg_unpack = 0;
3704
375k
  uint32_t arg_count = 0; /* number of arguments not including unpacks */
3705
3706
  /* Whether named arguments are used syntactically, to enforce language level limitations.
3707
   * May not actually use named argument passing. */
3708
375k
  bool uses_named_args = 0;
3709
  /* Whether there may be any undef arguments due to the use of named arguments. */
3710
375k
  bool may_have_undef = 0;
3711
  /* Whether there may be any extra named arguments collected into a variadic. */
3712
375k
  *may_have_extra_named_args = 0;
3713
3714
790k
  for (i = 0; i < args->children; ++i) {
3715
414k
    zend_ast *arg = args->child[i];
3716
414k
    zend_string *arg_name = NULL;
3717
414k
    uint32_t arg_num = i + 1;
3718
3719
414k
    znode arg_node;
3720
414k
    zend_op *opline;
3721
414k
    uint8_t opcode;
3722
3723
414k
    if (arg->kind == ZEND_AST_UNPACK) {
3724
1.80k
      if (uses_named_args) {
3725
6
        zend_error_noreturn(E_COMPILE_ERROR,
3726
6
          "Cannot use argument unpacking after named arguments");
3727
6
      }
3728
3729
      /* Unpack may contain named arguments. */
3730
1.79k
      may_have_undef = 1;
3731
1.79k
      if (!fbc || (fbc->common.fn_flags & ZEND_ACC_VARIADIC)) {
3732
1.23k
        *may_have_extra_named_args = 1;
3733
1.23k
      }
3734
3735
1.79k
      uses_arg_unpack = 1;
3736
1.79k
      fbc = NULL;
3737
3738
1.79k
      zend_compile_expr(&arg_node, arg->child[0]);
3739
1.79k
      opline = zend_emit_op(NULL, ZEND_SEND_UNPACK, &arg_node, NULL);
3740
1.79k
      opline->op2.num = arg_count;
3741
1.79k
      opline->result.var = EX_NUM_TO_VAR(arg_count - 1);
3742
3743
1.79k
      continue;
3744
1.80k
    }
3745
3746
412k
    if (arg->kind == ZEND_AST_NAMED_ARG) {
3747
10.8k
      uses_named_args = 1;
3748
10.8k
      arg_name = zval_make_interned_string(zend_ast_get_zval(arg->child[0]));
3749
10.8k
      arg = arg->child[1];
3750
3751
10.8k
      if (fbc && !uses_arg_unpack) {
3752
7.32k
        arg_num = zend_get_arg_num(fbc, arg_name);
3753
7.32k
        if (arg_num == arg_count + 1 && !may_have_undef) {
3754
          /* Using named arguments, but passing in order. */
3755
769
          arg_name = NULL;
3756
769
          arg_count++;
3757
6.55k
        } else {
3758
          // TODO: We could track which arguments were passed, even if out of order.
3759
6.55k
          may_have_undef = 1;
3760
6.55k
          if (arg_num == (uint32_t) -1 && (fbc->common.fn_flags & ZEND_ACC_VARIADIC)) {
3761
470
            *may_have_extra_named_args = 1;
3762
470
          }
3763
6.55k
        }
3764
7.32k
      } else {
3765
3.56k
        arg_num = (uint32_t) -1;
3766
3.56k
        may_have_undef = 1;
3767
3.56k
        *may_have_extra_named_args = 1;
3768
3.56k
      }
3769
401k
    } else {
3770
401k
      if (uses_arg_unpack) {
3771
16
        zend_error_noreturn(E_COMPILE_ERROR,
3772
16
          "Cannot use positional argument after argument unpacking");
3773
16
      }
3774
3775
401k
      if (uses_named_args) {
3776
40
        zend_error_noreturn(E_COMPILE_ERROR,
3777
40
          "Cannot use positional argument after named argument");
3778
40
      }
3779
3780
401k
      arg_count++;
3781
401k
    }
3782
3783
    /* Treat passing of $GLOBALS the same as passing a call.
3784
     * This will error at runtime if the argument is by-ref. */
3785
412k
    if (zend_is_call(arg) || is_globals_fetch(arg)) {
3786
71.4k
      zend_compile_var(&arg_node, arg, BP_VAR_R, 0);
3787
71.4k
      if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) {
3788
        /* Function call was converted into builtin instruction */
3789
4.98k
        if (!fbc || ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3790
2.12k
          opcode = ZEND_SEND_VAL_EX;
3791
2.86k
        } else {
3792
2.86k
          opcode = ZEND_SEND_VAL;
3793
2.86k
        }
3794
66.4k
      } else {
3795
66.4k
        if (fbc && arg_num != (uint32_t) -1) {
3796
47.0k
          if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3797
690
            opcode = ZEND_SEND_VAR_NO_REF;
3798
46.3k
          } else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) {
3799
            /* For IS_VAR operands, SEND_VAL will pass through the operand without
3800
             * dereferencing, so it will use a by-ref pass if the call returned by-ref
3801
             * and a by-value pass if it returned by-value. */
3802
72
            opcode = ZEND_SEND_VAL;
3803
46.3k
          } else {
3804
46.3k
            opcode = ZEND_SEND_VAR;
3805
46.3k
          }
3806
47.0k
        } else {
3807
19.3k
          opcode = ZEND_SEND_VAR_NO_REF_EX;
3808
19.3k
        }
3809
66.4k
      }
3810
341k
    } else if (zend_is_variable(arg) && !zend_ast_is_short_circuited(arg)) {
3811
124k
      if (fbc && arg_num != (uint32_t) -1) {
3812
32.8k
        if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) {
3813
2.47k
          zend_compile_var(&arg_node, arg, BP_VAR_W, 1);
3814
2.47k
          opcode = ZEND_SEND_REF;
3815
30.3k
        } else {
3816
30.3k
          zend_compile_var(&arg_node, arg, BP_VAR_R, 0);
3817
30.3k
          opcode = (arg_node.op_type == IS_TMP_VAR) ? ZEND_SEND_VAL : ZEND_SEND_VAR;
3818
30.3k
        }
3819
92.0k
      } else {
3820
92.0k
        do {
3821
92.0k
          if (arg->kind == ZEND_AST_VAR) {
3822
86.1k
            CG(zend_lineno) = zend_ast_get_lineno(ast);
3823
86.1k
            if (is_this_fetch(arg)) {
3824
104
              zend_emit_op(&arg_node, ZEND_FETCH_THIS, NULL, NULL);
3825
104
              opcode = ZEND_SEND_VAR_EX;
3826
104
              CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
3827
104
              break;
3828
86.0k
            } else if (zend_try_compile_cv(&arg_node, arg) == SUCCESS) {
3829
85.4k
              opcode = ZEND_SEND_VAR_EX;
3830
85.4k
              break;
3831
85.4k
            }
3832
86.1k
          }
3833
6.46k
          opline = zend_emit_op(NULL, ZEND_CHECK_FUNC_ARG, NULL, NULL);
3834
6.46k
          if (arg_name) {
3835
2.68k
            opline->op2_type = IS_CONST;
3836
2.68k
            zend_string_addref(arg_name);
3837
2.68k
            opline->op2.constant = zend_add_literal_string(&arg_name);
3838
2.68k
            opline->result.num = zend_alloc_cache_slots(2);
3839
3.77k
          } else {
3840
3.77k
            opline->op2.num = arg_num;
3841
3.77k
          }
3842
6.46k
          zend_compile_var(&arg_node, arg, BP_VAR_FUNC_ARG, 1);
3843
6.46k
          opcode = ZEND_SEND_FUNC_ARG;
3844
6.46k
        } while (0);
3845
92.0k
      }
3846
216k
    } else {
3847
216k
      zend_compile_expr(&arg_node, arg);
3848
216k
      if (arg_node.op_type == IS_VAR) {
3849
        /* pass ++$a or something similar */
3850
8.12k
        if (fbc && arg_num != (uint32_t) -1) {
3851
3.54k
          if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3852
198
            opcode = ZEND_SEND_VAR_NO_REF;
3853
3.34k
          } else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) {
3854
67
            opcode = ZEND_SEND_VAL;
3855
3.28k
          } else {
3856
3.28k
            opcode = ZEND_SEND_VAR;
3857
3.28k
          }
3858
4.57k
        } else {
3859
4.57k
          opcode = ZEND_SEND_VAR_NO_REF_EX;
3860
4.57k
        }
3861
208k
      } else if (arg_node.op_type == IS_CV) {
3862
0
        if (fbc && arg_num != (uint32_t) -1) {
3863
0
          if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) {
3864
0
            opcode = ZEND_SEND_REF;
3865
0
          } else {
3866
0
            opcode = ZEND_SEND_VAR;
3867
0
          }
3868
0
        } else {
3869
0
          opcode = ZEND_SEND_VAR_EX;
3870
0
        }
3871
208k
      } else {
3872
        /* Delay "Only variables can be passed by reference" error to execution */
3873
208k
        if (fbc && arg_num != (uint32_t) -1 && !ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3874
120k
          opcode = ZEND_SEND_VAL;
3875
120k
        } else {
3876
87.7k
          opcode = ZEND_SEND_VAL_EX;
3877
87.7k
        }
3878
208k
      }
3879
216k
    }
3880
3881
0
    opline = zend_emit_op(NULL, opcode, &arg_node, NULL);
3882
412k
    if (arg_name) {
3883
10.1k
      opline->op2_type = IS_CONST;
3884
10.1k
      zend_string_addref(arg_name);
3885
10.1k
      opline->op2.constant = zend_add_literal_string(&arg_name);
3886
10.1k
      opline->result.num = zend_alloc_cache_slots(2);
3887
402k
    } else {
3888
402k
      opline->op2.opline_num = arg_num;
3889
402k
      opline->result.var = EX_NUM_TO_VAR(arg_num - 1);
3890
402k
    }
3891
412k
  }
3892
3893
375k
  if (may_have_undef) {
3894
6.15k
    zend_emit_op(NULL, ZEND_CHECK_UNDEF_ARGS, NULL, NULL);
3895
6.15k
  }
3896
3897
375k
  return arg_count;
3898
375k
}
3899
/* }}} */
3900
3901
ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, zend_function *fbc, bool result_used) /* {{{ */
3902
489k
{
3903
489k
  uint32_t no_discard = result_used ? 0 : ZEND_ACC_NODISCARD;
3904
3905
489k
  if (fbc && init_op->opcode != ZEND_NEW) {
3906
265k
    ZEND_ASSERT(!(fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE));
3907
265k
    if (fbc->type == ZEND_INTERNAL_FUNCTION && !(CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS)) {
3908
218k
      if (init_op->opcode == ZEND_INIT_FCALL && !zend_execute_internal) {
3909
32.9k
        if (!(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) {
3910
32.8k
          return ZEND_DO_ICALL;
3911
32.8k
        } else {
3912
66
          return ZEND_DO_FCALL_BY_NAME;
3913
66
        }
3914
32.9k
      }
3915
218k
    } else if (!(CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS)){
3916
46.6k
      if (zend_execute_ex == execute_ex) {
3917
22.4k
        if (!(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) {
3918
22.1k
          return ZEND_DO_UCALL;
3919
22.1k
        } else {
3920
280
          return ZEND_DO_FCALL_BY_NAME;
3921
280
        }
3922
22.4k
      }
3923
46.6k
    }
3924
265k
  } else if (zend_execute_ex == execute_ex &&
3925
224k
             !zend_execute_internal &&
3926
224k
             (init_op->opcode == ZEND_INIT_FCALL_BY_NAME ||
3927
81.0k
              init_op->opcode == ZEND_INIT_NS_FCALL_BY_NAME)) {
3928
50.1k
    return ZEND_DO_FCALL_BY_NAME;
3929
50.1k
  }
3930
384k
  return ZEND_DO_FCALL;
3931
489k
}
3932
/* }}} */
3933
3934
static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc, uint32_t lineno) /* {{{ */
3935
377k
{
3936
377k
  zend_op *opline;
3937
377k
  uint32_t opnum_init = get_next_op_number() - 1;
3938
3939
377k
  if (args_ast->kind == ZEND_AST_CALLABLE_CONVERT) {
3940
1.45k
    opline = &CG(active_op_array)->opcodes[opnum_init];
3941
1.45k
    opline->extended_value = 0;
3942
3943
1.45k
    if (opline->opcode == ZEND_NEW) {
3944
21
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot create Closure for new expression");
3945
21
    }
3946
3947
1.43k
    if (opline->opcode == ZEND_INIT_FCALL) {
3948
426
      opline->op1.num = zend_vm_calc_used_stack(0, fbc);
3949
426
    }
3950
3951
1.43k
    zend_emit_op_tmp(result, ZEND_CALLABLE_CONVERT, NULL, NULL);
3952
1.43k
    return true;
3953
1.45k
  }
3954
3955
375k
  bool may_have_extra_named_args;
3956
375k
  uint32_t arg_count = zend_compile_args(args_ast, fbc, &may_have_extra_named_args);
3957
3958
375k
  zend_do_extended_fcall_begin();
3959
3960
375k
  opline = &CG(active_op_array)->opcodes[opnum_init];
3961
375k
  opline->extended_value = arg_count;
3962
3963
375k
  if (opline->opcode == ZEND_INIT_FCALL) {
3964
146k
    opline->op1.num = zend_vm_calc_used_stack(arg_count, fbc);
3965
146k
  }
3966
3967
375k
  uint8_t call_op = zend_get_call_op(
3968
375k
    opline,
3969
375k
    fbc,
3970
    /* result_used: At this point we do not yet reliably
3971
     * know if the result is used. Deoptimize #[\NoDiscard]
3972
     * calls to be sure. The optimizer will fix this up.
3973
     */
3974
375k
    false
3975
375k
  );
3976
375k
  opline = zend_emit_op(result, call_op, NULL, NULL);
3977
375k
  if (may_have_extra_named_args) {
3978
3.58k
    opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS;
3979
3.58k
  }
3980
375k
  opline->lineno = lineno;
3981
375k
  zend_do_extended_fcall_end();
3982
375k
  return false;
3983
377k
}
3984
/* }}} */
3985
3986
static bool zend_compile_function_name(znode *name_node, zend_ast *name_ast) /* {{{ */
3987
229k
{
3988
229k
  zend_string *orig_name = zend_ast_get_str(name_ast);
3989
229k
  bool is_fully_qualified;
3990
3991
229k
  name_node->op_type = IS_CONST;
3992
229k
  ZVAL_STR(&name_node->u.constant, zend_resolve_function_name(
3993
229k
    orig_name, name_ast->attr, &is_fully_qualified));
3994
3995
229k
  return !is_fully_qualified && FC(current_namespace);
3996
229k
}
3997
/* }}} */
3998
3999
static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno) /* {{{ */
4000
57.9k
{
4001
57.9k
  if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) {
4002
44.4k
    const char *colon;
4003
44.4k
    zend_string *str = Z_STR(name_node->u.constant);
4004
44.4k
    if ((colon = zend_memrchr(ZSTR_VAL(str), ':', ZSTR_LEN(str))) != NULL && colon > ZSTR_VAL(str) && *(colon - 1) == ':') {
4005
256
      zend_string *class = zend_string_init(ZSTR_VAL(str), colon - ZSTR_VAL(str) - 1, 0);
4006
256
      zend_string *method = zend_string_init(colon + 1, ZSTR_LEN(str) - (colon - ZSTR_VAL(str)) - 1, 0);
4007
256
      zend_op *opline = get_next_op();
4008
4009
256
      opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
4010
256
      opline->op1_type = IS_CONST;
4011
256
      opline->op1.constant = zend_add_class_name_literal(class);
4012
256
      opline->op2_type = IS_CONST;
4013
256
      opline->op2.constant = zend_add_func_name_literal(method);
4014
      /* 2 slots, for class and method */
4015
256
      opline->result.num = zend_alloc_cache_slots(2);
4016
256
      zval_ptr_dtor(&name_node->u.constant);
4017
44.1k
    } else {
4018
44.1k
      zend_op *opline = get_next_op();
4019
4020
44.1k
      opline->opcode = ZEND_INIT_FCALL_BY_NAME;
4021
44.1k
      opline->op2_type = IS_CONST;
4022
44.1k
      opline->op2.constant = zend_add_func_name_literal(str);
4023
44.1k
      opline->result.num = zend_alloc_cache_slot();
4024
44.1k
    }
4025
44.4k
  } else {
4026
13.4k
    zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, name_node);
4027
13.4k
  }
4028
4029
57.9k
  zend_compile_call_common(result, args_ast, NULL, lineno);
4030
57.9k
}
4031
/* }}} */
4032
4033
static inline bool zend_args_contain_unpack_or_named(zend_ast_list *args) /* {{{ */
4034
139k
{
4035
139k
  uint32_t i;
4036
332k
  for (i = 0; i < args->children; ++i) {
4037
195k
    zend_ast *arg = args->child[i];
4038
195k
    if (arg->kind == ZEND_AST_UNPACK || arg->kind == ZEND_AST_NAMED_ARG) {
4039
2.23k
      return 1;
4040
2.23k
    }
4041
195k
  }
4042
137k
  return 0;
4043
139k
}
4044
/* }}} */
4045
4046
static zend_result zend_compile_func_strlen(znode *result, zend_ast_list *args) /* {{{ */
4047
1.23k
{
4048
1.23k
  znode arg_node;
4049
4050
1.23k
  if (args->children != 1) {
4051
206
    return FAILURE;
4052
206
  }
4053
4054
1.03k
  zend_compile_expr(&arg_node, args->child[0]);
4055
1.03k
  if (arg_node.op_type == IS_CONST && Z_TYPE(arg_node.u.constant) == IS_STRING) {
4056
295
    result->op_type = IS_CONST;
4057
295
    ZVAL_LONG(&result->u.constant, Z_STRLEN(arg_node.u.constant));
4058
295
    zval_ptr_dtor_str(&arg_node.u.constant);
4059
737
  } else {
4060
737
    zend_emit_op_tmp(result, ZEND_STRLEN, &arg_node, NULL);
4061
737
  }
4062
1.03k
  return SUCCESS;
4063
1.23k
}
4064
/* }}} */
4065
4066
static zend_result zend_compile_func_typecheck(znode *result, zend_ast_list *args, uint32_t type) /* {{{ */
4067
2.66k
{
4068
2.66k
  znode arg_node;
4069
2.66k
  zend_op *opline;
4070
4071
2.66k
  if (args->children != 1) {
4072
1.14k
    return FAILURE;
4073
1.14k
  }
4074
4075
1.52k
  zend_compile_expr(&arg_node, args->child[0]);
4076
1.52k
  opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL);
4077
1.52k
  if (type != _IS_BOOL) {
4078
1.44k
    opline->extended_value = (1 << type);
4079
1.44k
  } else {
4080
80
    opline->extended_value = (1 << IS_FALSE) | (1 << IS_TRUE);
4081
80
  }
4082
1.52k
  return SUCCESS;
4083
2.66k
}
4084
/* }}} */
4085
4086
static zend_result zend_compile_func_is_scalar(znode *result, zend_ast_list *args) /* {{{ */
4087
323
{
4088
323
  znode arg_node;
4089
323
  zend_op *opline;
4090
4091
323
  if (args->children != 1) {
4092
69
    return FAILURE;
4093
69
  }
4094
4095
254
  zend_compile_expr(&arg_node, args->child[0]);
4096
254
  opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL);
4097
254
  opline->extended_value = (1 << IS_FALSE | 1 << IS_TRUE | 1 << IS_DOUBLE | 1 << IS_LONG | 1 << IS_STRING);
4098
254
  return SUCCESS;
4099
323
}
4100
4101
static zend_result zend_compile_func_cast(znode *result, zend_ast_list *args, uint32_t type) /* {{{ */
4102
1.70k
{
4103
1.70k
  znode arg_node;
4104
1.70k
  zend_op *opline;
4105
4106
1.70k
  if (args->children != 1) {
4107
305
    return FAILURE;
4108
305
  }
4109
4110
1.40k
  zend_compile_expr(&arg_node, args->child[0]);
4111
1.40k
  if (type == _IS_BOOL) {
4112
212
    opline = zend_emit_op_tmp(result, ZEND_BOOL, &arg_node, NULL);
4113
1.19k
  } else {
4114
1.19k
    opline = zend_emit_op_tmp(result, ZEND_CAST, &arg_node, NULL);
4115
1.19k
    opline->extended_value = type;
4116
1.19k
  }
4117
1.40k
  return SUCCESS;
4118
1.70k
}
4119
/* }}} */
4120
4121
static zend_result zend_compile_func_defined(znode *result, zend_ast_list *args) /* {{{ */
4122
1.53k
{
4123
1.53k
  zend_string *name;
4124
1.53k
  zend_op *opline;
4125
4126
1.53k
  if (args->children != 1 || args->child[0]->kind != ZEND_AST_ZVAL) {
4127
430
    return FAILURE;
4128
430
  }
4129
4130
1.10k
  name = zval_get_string(zend_ast_get_zval(args->child[0]));
4131
1.10k
  if (zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name)) || zend_memrchr(ZSTR_VAL(name), ':', ZSTR_LEN(name))) {
4132
187
    zend_string_release_ex(name, 0);
4133
187
    return FAILURE;
4134
187
  }
4135
4136
918
  if (zend_try_ct_eval_const(&result->u.constant, name, 0)) {
4137
296
    zend_string_release_ex(name, 0);
4138
296
    zval_ptr_dtor(&result->u.constant);
4139
296
    ZVAL_TRUE(&result->u.constant);
4140
296
    result->op_type = IS_CONST;
4141
296
    return SUCCESS;
4142
296
  }
4143
4144
622
  opline = zend_emit_op_tmp(result, ZEND_DEFINED, NULL, NULL);
4145
622
  opline->op1_type = IS_CONST;
4146
622
  LITERAL_STR(opline->op1, name);
4147
622
  opline->extended_value = zend_alloc_cache_slot();
4148
4149
622
  return SUCCESS;
4150
918
}
4151
/* }}} */
4152
4153
static zend_result zend_compile_func_chr(znode *result, zend_ast_list *args) /* {{{ */
4154
1.14k
{
4155
4156
1.14k
  if (args->children == 1 &&
4157
1.14k
      args->child[0]->kind == ZEND_AST_ZVAL &&
4158
1.14k
      Z_TYPE_P(zend_ast_get_zval(args->child[0])) == IS_LONG) {
4159
4160
573
    zend_long c = Z_LVAL_P(zend_ast_get_zval(args->child[0])) & 0xff;
4161
4162
573
    result->op_type = IS_CONST;
4163
573
    ZVAL_CHAR(&result->u.constant, c);
4164
573
    return SUCCESS;
4165
576
  } else {
4166
576
    return FAILURE;
4167
576
  }
4168
1.14k
}
4169
/* }}} */
4170
4171
static zend_result zend_compile_func_ord(znode *result, zend_ast_list *args) /* {{{ */
4172
614
{
4173
614
  if (args->children == 1 &&
4174
614
      args->child[0]->kind == ZEND_AST_ZVAL &&
4175
614
      Z_TYPE_P(zend_ast_get_zval(args->child[0])) == IS_STRING) {
4176
4177
66
    result->op_type = IS_CONST;
4178
66
    ZVAL_LONG(&result->u.constant, (unsigned char)Z_STRVAL_P(zend_ast_get_zval(args->child[0]))[0]);
4179
66
    return SUCCESS;
4180
548
  } else {
4181
548
    return FAILURE;
4182
548
  }
4183
614
}
4184
/* }}} */
4185
4186
/* We can only calculate the stack size for functions that have been fully compiled, otherwise
4187
 * additional CV or TMP slots may still be added. This prevents the use of INIT_FCALL for
4188
 * directly or indirectly recursive function calls. */
4189
168k
static bool fbc_is_finalized(zend_function *fbc) {
4190
168k
  return !ZEND_USER_CODE(fbc->type) || (fbc->common.fn_flags & ZEND_ACC_DONE_PASS_TWO);
4191
168k
}
4192
4193
static bool zend_compile_ignore_class(zend_class_entry *ce, zend_string *filename)
4194
15.5k
{
4195
15.5k
  if (ce->type == ZEND_INTERNAL_CLASS) {
4196
3.28k
    return CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES;
4197
12.3k
  } else {
4198
12.3k
    return (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES)
4199
12.3k
      && ce->info.user.filename != filename;
4200
12.3k
  }
4201
15.5k
}
4202
4203
static bool zend_compile_ignore_function(zend_function *fbc, zend_string *filename)
4204
145k
{
4205
145k
  if (fbc->type == ZEND_INTERNAL_FUNCTION) {
4206
123k
    return CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS;
4207
123k
  } else {
4208
21.8k
    return (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS)
4209
21.8k
      || ((CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES)
4210
21.8k
        && fbc->op_array.filename != filename);
4211
21.8k
  }
4212
145k
}
4213
4214
static zend_result zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t num_args) /* {{{ */
4215
3.61k
{
4216
3.61k
  zend_string *name, *lcname;
4217
3.61k
  zend_function *fbc;
4218
3.61k
  zend_op *opline;
4219
4220
3.61k
  if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
4221
2.23k
    return FAILURE;
4222
2.23k
  }
4223
4224
1.37k
  name = zend_ast_get_str(name_ast);
4225
1.37k
  lcname = zend_string_tolower(name);
4226
4227
1.37k
  fbc = zend_hash_find_ptr(CG(function_table), lcname);
4228
1.37k
  if (!fbc
4229
1.37k
   || !fbc_is_finalized(fbc)
4230
1.37k
   || zend_compile_ignore_function(fbc, CG(active_op_array)->filename)) {
4231
729
    zend_string_release_ex(lcname, 0);
4232
729
    return FAILURE;
4233
729
  }
4234
4235
650
  opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, NULL);
4236
650
  opline->extended_value = num_args;
4237
650
  opline->op1.num = zend_vm_calc_used_stack(num_args, fbc);
4238
650
  opline->op2_type = IS_CONST;
4239
650
  LITERAL_STR(opline->op2, lcname);
4240
650
  opline->result.num = zend_alloc_cache_slot();
4241
4242
650
  return SUCCESS;
4243
1.37k
}
4244
/* }}} */
4245
4246
static void zend_compile_init_user_func(zend_ast *name_ast, uint32_t num_args, zend_string *orig_func_name) /* {{{ */
4247
3.61k
{
4248
3.61k
  zend_op *opline;
4249
3.61k
  znode name_node;
4250
4251
3.61k
  if (zend_try_compile_ct_bound_init_user_func(name_ast, num_args) == SUCCESS) {
4252
650
    return;
4253
650
  }
4254
4255
2.96k
  zend_compile_expr(&name_node, name_ast);
4256
4257
2.96k
  opline = zend_emit_op(NULL, ZEND_INIT_USER_CALL, NULL, &name_node);
4258
2.96k
  opline->op1_type = IS_CONST;
4259
2.96k
  LITERAL_STR(opline->op1, zend_string_copy(orig_func_name));
4260
2.96k
  opline->extended_value = num_args;
4261
2.96k
}
4262
/* }}} */
4263
4264
/* cufa = call_user_func_array */
4265
static zend_result zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
4266
1.90k
{
4267
1.90k
  znode arg_node;
4268
1.90k
  zend_op *opline;
4269
4270
1.90k
  if (args->children != 2) {
4271
75
    return FAILURE;
4272
75
  }
4273
4274
1.82k
  zend_compile_init_user_func(args->child[0], 0, lcname);
4275
1.82k
  if (args->child[1]->kind == ZEND_AST_CALL
4276
1.82k
   && args->child[1]->child[0]->kind == ZEND_AST_ZVAL
4277
1.82k
   && Z_TYPE_P(zend_ast_get_zval(args->child[1]->child[0])) == IS_STRING
4278
1.82k
   && args->child[1]->child[1]->kind == ZEND_AST_ARG_LIST) {
4279
932
    zend_string *orig_name = zend_ast_get_str(args->child[1]->child[0]);
4280
932
    zend_ast_list *list = zend_ast_get_list(args->child[1]->child[1]);
4281
932
    bool is_fully_qualified;
4282
932
    zend_string *name = zend_resolve_function_name(orig_name, args->child[1]->child[0]->attr, &is_fully_qualified);
4283
4284
932
    if (zend_string_equals_literal_ci(name, "array_slice")
4285
932
       && !zend_args_contain_unpack_or_named(list)
4286
932
     && list->children == 3
4287
932
     && list->child[1]->kind == ZEND_AST_ZVAL) {
4288
429
      zval *zv = zend_ast_get_zval(list->child[1]);
4289
4290
429
      if (Z_TYPE_P(zv) == IS_LONG
4291
429
       && Z_LVAL_P(zv) >= 0
4292
429
       && Z_LVAL_P(zv) <= 0x7fffffff) {
4293
262
        zend_op *opline;
4294
262
        znode len_node;
4295
4296
262
        zend_compile_expr(&arg_node, list->child[0]);
4297
262
        zend_compile_expr(&len_node, list->child[2]);
4298
262
        opline = zend_emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, &len_node);
4299
262
        opline->extended_value = Z_LVAL_P(zv);
4300
262
        zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
4301
262
        zend_string_release_ex(name, 0);
4302
262
        return SUCCESS;
4303
262
      }
4304
429
    }
4305
670
    zend_string_release_ex(name, 0);
4306
670
  }
4307
1.56k
  zend_compile_expr(&arg_node, args->child[1]);
4308
1.56k
  zend_emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, NULL);
4309
1.56k
  zend_emit_op(NULL, ZEND_CHECK_UNDEF_ARGS, NULL, NULL);
4310
1.56k
  opline = zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
4311
1.56k
  opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS;
4312
4313
1.56k
  return SUCCESS;
4314
1.82k
}
4315
/* }}} */
4316
4317
/* cuf = call_user_func */
4318
static zend_result zend_compile_func_cuf(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
4319
1.85k
{
4320
1.85k
  uint32_t i;
4321
4322
1.85k
  if (args->children < 1) {
4323
66
    return FAILURE;
4324
66
  }
4325
4326
1.78k
  zend_compile_init_user_func(args->child[0], args->children - 1, lcname);
4327
4.99k
  for (i = 1; i < args->children; ++i) {
4328
3.20k
    zend_ast *arg_ast = args->child[i];
4329
3.20k
    znode arg_node;
4330
3.20k
    zend_op *opline;
4331
4332
3.20k
    zend_compile_expr(&arg_node, arg_ast);
4333
4334
3.20k
    opline = zend_emit_op(NULL, ZEND_SEND_USER, &arg_node, NULL);
4335
3.20k
    opline->op2.num = i;
4336
3.20k
    opline->result.var = EX_NUM_TO_VAR(i - 1);
4337
3.20k
  }
4338
1.78k
  zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
4339
4340
1.78k
  return SUCCESS;
4341
1.85k
}
4342
/* }}} */
4343
4344
static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, zend_function *fbc, uint32_t lineno) /* {{{ */
4345
24.1k
{
4346
24.1k
  if (EG(assertions) >= 0) {
4347
24.1k
    znode name_node;
4348
24.1k
    zend_op *opline;
4349
24.1k
    uint32_t check_op_number = get_next_op_number();
4350
4351
24.1k
    zend_emit_op(NULL, ZEND_ASSERT_CHECK, NULL, NULL);
4352
4353
24.1k
    if (fbc && fbc_is_finalized(fbc)) {
4354
22.9k
      name_node.op_type = IS_CONST;
4355
22.9k
      ZVAL_STR_COPY(&name_node.u.constant, name);
4356
4357
22.9k
      opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
4358
22.9k
    } else {
4359
1.12k
      opline = zend_emit_op(NULL, ZEND_INIT_NS_FCALL_BY_NAME, NULL, NULL);
4360
1.12k
      opline->op2_type = IS_CONST;
4361
1.12k
      opline->op2.constant = zend_add_ns_func_name_literal(name);
4362
1.12k
    }
4363
24.1k
    opline->result.num = zend_alloc_cache_slot();
4364
4365
24.1k
    if (args->children == 1) {
4366
      /* add "assert(condition) as assertion message */
4367
23.8k
      zend_ast *arg = zend_ast_create_zval_from_str(
4368
23.8k
        zend_ast_export("assert(", args->child[0], ")"));
4369
23.8k
      if (args->child[0]->kind == ZEND_AST_NAMED_ARG) {
4370
        /* If the original argument was named, add the new argument as named as well,
4371
         * as mixing named and positional is not allowed. */
4372
248
        zend_ast *name = zend_ast_create_zval_from_str(
4373
248
          ZSTR_INIT_LITERAL("description", 0));
4374
248
        arg = zend_ast_create(ZEND_AST_NAMED_ARG, name, arg);
4375
248
      }
4376
23.8k
      zend_ast_list_add((zend_ast *) args, arg);
4377
23.8k
    }
4378
4379
24.1k
    zend_compile_call_common(result, (zend_ast*)args, fbc, lineno);
4380
4381
24.1k
    opline = &CG(active_op_array)->opcodes[check_op_number];
4382
24.1k
    opline->op2.opline_num = get_next_op_number();
4383
24.1k
    SET_NODE(opline->result, result);
4384
24.1k
  } else {
4385
0
    if (!fbc) {
4386
0
      zend_string_release_ex(name, 0);
4387
0
    }
4388
0
    result->op_type = IS_CONST;
4389
0
    ZVAL_TRUE(&result->u.constant);
4390
0
  }
4391
24.1k
}
4392
/* }}} */
4393
4394
static zend_result zend_compile_func_in_array(znode *result, zend_ast_list *args) /* {{{ */
4395
3.87k
{
4396
3.87k
  bool strict = 0;
4397
3.87k
  znode array, needly;
4398
3.87k
  zend_op *opline;
4399
4400
3.87k
  if (args->children == 3) {
4401
1.73k
    if (args->child[2]->kind == ZEND_AST_ZVAL) {
4402
902
      strict = zend_is_true(zend_ast_get_zval(args->child[2]));
4403
902
    } else if (args->child[2]->kind == ZEND_AST_CONST) {
4404
763
      zval value;
4405
763
      zend_ast *name_ast = args->child[2]->child[0];
4406
763
      bool is_fully_qualified;
4407
763
      zend_string *resolved_name = zend_resolve_const_name(
4408
763
        zend_ast_get_str(name_ast), name_ast->attr, &is_fully_qualified);
4409
4410
763
      if (!zend_try_ct_eval_const(&value, resolved_name, is_fully_qualified)) {
4411
609
        zend_string_release_ex(resolved_name, 0);
4412
609
        return FAILURE;
4413
609
      }
4414
4415
154
      zend_string_release_ex(resolved_name, 0);
4416
154
      strict = zend_is_true(&value);
4417
154
      zval_ptr_dtor(&value);
4418
154
    } else {
4419
74
      return FAILURE;
4420
74
    }
4421
2.13k
  } else if (args->children != 2) {
4422
366
    return FAILURE;
4423
366
  }
4424
4425
2.82k
  if (args->child[1]->kind != ZEND_AST_ARRAY
4426
2.82k
   || !zend_try_ct_eval_array(&array.u.constant, args->child[1])) {
4427
753
    return FAILURE;
4428
753
  }
4429
4430
2.07k
  if (zend_hash_num_elements(Z_ARRVAL(array.u.constant)) > 0) {
4431
1.74k
    bool ok = 1;
4432
1.74k
    zval *val, tmp;
4433
1.74k
    HashTable *src = Z_ARRVAL(array.u.constant);
4434
1.74k
    HashTable *dst = zend_new_array(zend_hash_num_elements(src));
4435
4436
1.74k
    ZVAL_TRUE(&tmp);
4437
4438
1.74k
    if (strict) {
4439
4.21k
      ZEND_HASH_FOREACH_VAL(src, val) {
4440
4.21k
        if (Z_TYPE_P(val) == IS_STRING) {
4441
66
          zend_hash_add(dst, Z_STR_P(val), &tmp);
4442
1.20k
        } else if (Z_TYPE_P(val) == IS_LONG) {
4443
1.05k
          zend_hash_index_add(dst, Z_LVAL_P(val), &tmp);
4444
1.05k
        } else {
4445
147
          zend_array_destroy(dst);
4446
147
          ok = 0;
4447
147
          break;
4448
147
        }
4449
4.21k
      } ZEND_HASH_FOREACH_END();
4450
1.03k
    } else {
4451
5.35k
      ZEND_HASH_FOREACH_VAL(src, val) {
4452
5.35k
        if (Z_TYPE_P(val) != IS_STRING
4453
1.56k
         || is_numeric_string(Z_STRVAL_P(val), Z_STRLEN_P(val), NULL, NULL, 0)) {
4454
926
          zend_array_destroy(dst);
4455
926
          ok = 0;
4456
926
          break;
4457
926
        }
4458
635
        zend_hash_add(dst, Z_STR_P(val), &tmp);
4459
635
      } ZEND_HASH_FOREACH_END();
4460
1.03k
    }
4461
4462
1.74k
    zend_array_destroy(src);
4463
1.74k
    if (!ok) {
4464
1.07k
      return FAILURE;
4465
1.07k
    }
4466
672
    Z_ARRVAL(array.u.constant) = dst;
4467
672
  }
4468
1.00k
  array.op_type = IS_CONST;
4469
4470
1.00k
  zend_compile_expr(&needly, args->child[0]);
4471
4472
1.00k
  opline = zend_emit_op_tmp(result, ZEND_IN_ARRAY, &needly, &array);
4473
1.00k
  opline->extended_value = strict;
4474
4475
1.00k
  return SUCCESS;
4476
2.07k
}
4477
/* }}} */
4478
4479
static zend_result zend_compile_func_count(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
4480
1.10k
{
4481
1.10k
  znode arg_node;
4482
1.10k
  zend_op *opline;
4483
4484
1.10k
  if (args->children != 1) {
4485
138
    return FAILURE;
4486
138
  }
4487
4488
964
  zend_compile_expr(&arg_node, args->child[0]);
4489
964
  opline = zend_emit_op_tmp(result, ZEND_COUNT, &arg_node, NULL);
4490
964
  opline->extended_value = zend_string_equals_literal(lcname, "sizeof");
4491
4492
964
  return SUCCESS;
4493
1.10k
}
4494
/* }}} */
4495
4496
static zend_result zend_compile_func_get_class(znode *result, zend_ast_list *args) /* {{{ */
4497
1.52k
{
4498
1.52k
  if (args->children == 0) {
4499
245
    zend_emit_op_tmp(result, ZEND_GET_CLASS, NULL, NULL);
4500
1.27k
  } else {
4501
1.27k
    znode arg_node;
4502
4503
1.27k
    if (args->children != 1) {
4504
66
      return FAILURE;
4505
66
    }
4506
4507
1.21k
    zend_compile_expr(&arg_node, args->child[0]);
4508
1.21k
    zend_emit_op_tmp(result, ZEND_GET_CLASS, &arg_node, NULL);
4509
1.21k
  }
4510
1.45k
  return SUCCESS;
4511
1.52k
}
4512
/* }}} */
4513
4514
static zend_result zend_compile_func_get_called_class(znode *result, zend_ast_list *args) /* {{{ */
4515
213
{
4516
213
  if (args->children != 0) {
4517
72
    return FAILURE;
4518
72
  }
4519
4520
141
  zend_emit_op_tmp(result, ZEND_GET_CALLED_CLASS, NULL, NULL);
4521
141
  return SUCCESS;
4522
213
}
4523
/* }}} */
4524
4525
static zend_result zend_compile_func_gettype(znode *result, zend_ast_list *args) /* {{{ */
4526
1.33k
{
4527
1.33k
  znode arg_node;
4528
4529
1.33k
  if (args->children != 1) {
4530
70
    return FAILURE;
4531
70
  }
4532
4533
1.26k
  zend_compile_expr(&arg_node, args->child[0]);
4534
1.26k
  zend_emit_op_tmp(result, ZEND_GET_TYPE, &arg_node, NULL);
4535
1.26k
  return SUCCESS;
4536
1.33k
}
4537
/* }}} */
4538
4539
static zend_result zend_compile_func_num_args(znode *result, zend_ast_list *args) /* {{{ */
4540
610
{
4541
610
  if (CG(active_op_array)->function_name && args->children == 0) {
4542
85
    zend_emit_op_tmp(result, ZEND_FUNC_NUM_ARGS, NULL, NULL);
4543
85
    return SUCCESS;
4544
525
  } else {
4545
525
    return FAILURE;
4546
525
  }
4547
610
}
4548
/* }}} */
4549
4550
static zend_result zend_compile_func_get_args(znode *result, zend_ast_list *args) /* {{{ */
4551
548
{
4552
548
  if (CG(active_op_array)->function_name && args->children == 0) {
4553
269
    zend_emit_op_tmp(result, ZEND_FUNC_GET_ARGS, NULL, NULL);
4554
269
    return SUCCESS;
4555
279
  } else {
4556
279
    return FAILURE;
4557
279
  }
4558
548
}
4559
/* }}} */
4560
4561
static zend_result zend_compile_func_array_key_exists(znode *result, zend_ast_list *args) /* {{{ */
4562
353
{
4563
353
  znode subject, needle;
4564
4565
353
  if (args->children != 2) {
4566
196
    return FAILURE;
4567
196
  }
4568
4569
157
  zend_compile_expr(&needle, args->child[0]);
4570
157
  zend_compile_expr(&subject, args->child[1]);
4571
4572
157
  zend_emit_op_tmp(result, ZEND_ARRAY_KEY_EXISTS, &needle, &subject);
4573
157
  return SUCCESS;
4574
353
}
4575
/* }}} */
4576
4577
static zend_result zend_compile_func_array_slice(znode *result, zend_ast_list *args) /* {{{ */
4578
1.64k
{
4579
1.64k
  if (CG(active_op_array)->function_name
4580
1.64k
   && args->children == 2
4581
1.64k
   && args->child[0]->kind == ZEND_AST_CALL
4582
1.64k
   && args->child[0]->child[0]->kind == ZEND_AST_ZVAL
4583
1.64k
   && Z_TYPE_P(zend_ast_get_zval(args->child[0]->child[0])) == IS_STRING
4584
1.64k
   && args->child[0]->child[1]->kind == ZEND_AST_ARG_LIST
4585
1.64k
   && args->child[1]->kind == ZEND_AST_ZVAL) {
4586
4587
511
    zend_string *orig_name = zend_ast_get_str(args->child[0]->child[0]);
4588
511
    bool is_fully_qualified;
4589
511
    zend_string *name = zend_resolve_function_name(orig_name, args->child[0]->child[0]->attr, &is_fully_qualified);
4590
511
    zend_ast_list *list = zend_ast_get_list(args->child[0]->child[1]);
4591
511
    zval *zv = zend_ast_get_zval(args->child[1]);
4592
511
    znode first;
4593
4594
511
    if (zend_string_equals_literal_ci(name, "func_get_args")
4595
511
     && list->children == 0
4596
511
     && Z_TYPE_P(zv) == IS_LONG
4597
511
     && Z_LVAL_P(zv) >= 0) {
4598
160
      first.op_type = IS_CONST;
4599
160
      ZVAL_LONG(&first.u.constant, Z_LVAL_P(zv));
4600
160
      zend_emit_op_tmp(result, ZEND_FUNC_GET_ARGS, &first, NULL);
4601
160
      zend_string_release_ex(name, 0);
4602
160
      return SUCCESS;
4603
160
    }
4604
351
    zend_string_release_ex(name, 0);
4605
351
  }
4606
1.48k
  return FAILURE;
4607
1.64k
}
4608
/* }}} */
4609
4610
static uint32_t find_frameless_function_offset(uint32_t arity, void *handler)
4611
10.8k
{
4612
10.8k
  void **handlers = zend_flf_handlers;
4613
10.8k
  void **current = handlers;
4614
81.5k
  while (current) {
4615
81.5k
    if (*current == handler) {
4616
10.8k
      return current - handlers;
4617
10.8k
    }
4618
70.6k
    current++;
4619
70.6k
  }
4620
4621
0
  return (uint32_t)-1;
4622
10.8k
}
4623
4624
static const zend_frameless_function_info *find_frameless_function_info(zend_ast_list *args, zend_function *fbc, uint32_t type)
4625
112k
{
4626
112k
  if (zend_execute_internal) {
4627
93.4k
    return NULL;
4628
93.4k
  }
4629
4630
19.4k
  if (type != BP_VAR_R) {
4631
1.25k
    return NULL;
4632
1.25k
  }
4633
4634
18.2k
  if (ZEND_USER_CODE(fbc->type)) {
4635
34
    return NULL;
4636
34
  }
4637
4638
18.1k
  const zend_frameless_function_info *frameless_function_info = fbc->internal_function.frameless_function_infos;
4639
18.1k
  if (!frameless_function_info) {
4640
11.0k
    return NULL;
4641
11.0k
  }
4642
4643
7.09k
  if (args->children > 3) {
4644
416
    return NULL;
4645
416
  }
4646
4647
10.1k
  while (frameless_function_info->handler) {
4648
8.89k
    if (frameless_function_info->num_args >= args->children
4649
8.89k
     && fbc->common.required_num_args <= args->children
4650
8.89k
     && (!(fbc->common.fn_flags & ZEND_ACC_VARIADIC)
4651
5.69k
      || frameless_function_info->num_args == args->children)) {
4652
5.42k
      uint32_t num_args = frameless_function_info->num_args;
4653
5.42k
      uint32_t offset = find_frameless_function_offset(num_args, frameless_function_info->handler);
4654
5.42k
      if (offset == (uint32_t)-1) {
4655
0
        continue;
4656
0
      }
4657
5.42k
      return frameless_function_info;
4658
5.42k
    }
4659
3.46k
    frameless_function_info++;
4660
3.46k
  }
4661
4662
1.25k
  return NULL;
4663
6.67k
}
4664
4665
static uint32_t zend_compile_frameless_icall_ex(znode *result, zend_ast_list *args, zend_function *fbc, const zend_frameless_function_info *frameless_function_info, uint32_t type)
4666
5.42k
{
4667
5.42k
  int lineno = CG(zend_lineno);
4668
5.42k
  uint32_t num_args = frameless_function_info->num_args;
4669
5.42k
  uint32_t offset = find_frameless_function_offset(num_args, frameless_function_info->handler);
4670
5.42k
  znode arg_zvs[3];
4671
17.0k
  for (uint32_t i = 0; i < num_args; i++) {
4672
11.6k
    if (i < args->children) {
4673
11.6k
      zend_compile_expr(&arg_zvs[i], args->child[i]);
4674
11.6k
    } else {
4675
0
      zend_internal_arg_info *arg_info = (zend_internal_arg_info *)&fbc->common.arg_info[i];
4676
0
      arg_zvs[i].op_type = IS_CONST;
4677
0
      if (zend_get_default_from_internal_arg_info(&arg_zvs[i].u.constant, arg_info) == FAILURE) {
4678
0
        ZEND_UNREACHABLE();
4679
0
      }
4680
0
    }
4681
11.6k
  }
4682
5.42k
  uint8_t opcode = ZEND_FRAMELESS_ICALL_0 + num_args;
4683
5.42k
  uint32_t opnum = get_next_op_number();
4684
5.42k
  zend_op *opline = zend_emit_op_tmp(result, opcode, NULL, NULL);
4685
5.42k
  opline->extended_value = offset;
4686
5.42k
  opline->lineno = lineno;
4687
5.42k
  if (num_args >= 1) {
4688
5.41k
    SET_NODE(opline->op1, &arg_zvs[0]);
4689
5.41k
  }
4690
5.42k
  if (num_args >= 2) {
4691
4.85k
    SET_NODE(opline->op2, &arg_zvs[1]);
4692
4.85k
  }
4693
5.42k
  if (num_args >= 3) {
4694
1.38k
    zend_emit_op_data(&arg_zvs[2]);
4695
1.38k
  }
4696
5.42k
  return opnum;
4697
5.42k
}
4698
4699
static uint32_t zend_compile_frameless_icall(znode *result, zend_ast_list *args, zend_function *fbc, uint32_t type)
4700
106k
{
4701
106k
  const zend_frameless_function_info *frameless_function_info = find_frameless_function_info(args, fbc, type);
4702
106k
  if (!frameless_function_info) {
4703
102k
    return (uint32_t)-1;
4704
102k
  }
4705
4706
3.08k
  return zend_compile_frameless_icall_ex(result, args, fbc, frameless_function_info, type);
4707
106k
}
4708
4709
static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno, uint32_t type) /* {{{ */
4710
15.4k
{
4711
15.4k
  int name_constants = zend_add_ns_func_name_literal(Z_STR(name_node->u.constant));
4712
4713
  /* Find frameless function with same name. */
4714
15.4k
  zend_function *frameless_function = NULL;
4715
15.4k
  if (args_ast->kind != ZEND_AST_CALLABLE_CONVERT
4716
15.4k
   && !zend_args_contain_unpack_or_named(zend_ast_get_list(args_ast))
4717
   /* Avoid blowing up op count with nested frameless branches. */
4718
15.4k
   && !CG(context).in_jmp_frameless_branch) {
4719
11.8k
    zend_string *lc_func_name = Z_STR_P(CT_CONSTANT_EX(CG(active_op_array), name_constants + 2));
4720
11.8k
    frameless_function = zend_hash_find_ptr(CG(function_table), lc_func_name);
4721
11.8k
  }
4722
4723
  /* Check whether any frameless handler may actually be used. */
4724
15.4k
  uint32_t jmp_fl_opnum = 0;
4725
15.4k
  const zend_frameless_function_info *frameless_function_info = NULL;
4726
15.4k
  if (frameless_function) {
4727
6.88k
    frameless_function_info = find_frameless_function_info(zend_ast_get_list(args_ast), frameless_function, type);
4728
6.88k
    if (frameless_function_info) {
4729
2.34k
      CG(context).in_jmp_frameless_branch = true;
4730
2.34k
      znode op1;
4731
2.34k
      op1.op_type = IS_CONST;
4732
2.34k
      ZVAL_COPY(&op1.u.constant, CT_CONSTANT_EX(CG(active_op_array), name_constants + 1));
4733
2.34k
      jmp_fl_opnum = get_next_op_number();
4734
2.34k
      zend_emit_op(NULL, ZEND_JMP_FRAMELESS, &op1, NULL);
4735
2.34k
    }
4736
6.88k
  }
4737
4738
  /* Compile ns call. */
4739
15.4k
  zend_op *opline = get_next_op();
4740
15.4k
  opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
4741
15.4k
  opline->op2_type = IS_CONST;
4742
15.4k
  opline->op2.constant = name_constants;
4743
15.4k
  opline->result.num = zend_alloc_cache_slot();
4744
15.4k
  zend_compile_call_common(result, args_ast, NULL, lineno);
4745
4746
  /* Compile frameless call. */
4747
15.4k
  if (frameless_function_info) {
4748
2.33k
    CG(zend_lineno) = lineno;
4749
4750
2.33k
    uint32_t jmp_end_opnum = zend_emit_jump(0);
4751
2.33k
    uint32_t jmp_fl_target = get_next_op_number();
4752
4753
2.33k
    uint32_t flf_icall_opnum = zend_compile_frameless_icall_ex(NULL, zend_ast_get_list(args_ast), frameless_function, frameless_function_info, type);
4754
4755
2.33k
    zend_op *jmp_fl = &CG(active_op_array)->opcodes[jmp_fl_opnum];
4756
2.33k
    jmp_fl->op2.opline_num = jmp_fl_target;
4757
2.33k
    jmp_fl->extended_value = zend_alloc_cache_slot();
4758
2.33k
    zend_op *flf_icall = &CG(active_op_array)->opcodes[flf_icall_opnum];
4759
2.33k
    SET_NODE(flf_icall->result, result);
4760
2.33k
    zend_update_jump_target_to_next(jmp_end_opnum);
4761
4762
2.33k
    CG(context).in_jmp_frameless_branch = false;
4763
2.33k
  }
4764
15.4k
}
4765
/* }}} */
4766
4767
static zend_op *zend_compile_rope_add(znode *result, uint32_t num, znode *elem_node);
4768
static zend_op *zend_compile_rope_add_ex(zend_op *opline, znode *result, uint32_t num, znode *elem_node);
4769
static void zend_compile_rope_finalize(znode *result, uint32_t j, zend_op *init_opline, zend_op *opline);
4770
4771
static zend_result zend_compile_func_sprintf(znode *result, zend_ast_list *args) /* {{{ */
4772
1.56k
{
4773
  /* Bail out if we do not have a format string. */
4774
1.56k
  if (args->children < 1) {
4775
68
    return FAILURE;
4776
68
  }
4777
4778
1.49k
  zend_eval_const_expr(&args->child[0]);
4779
  /* Bail out if the format string is not constant. */
4780
1.49k
  if (args->child[0]->kind != ZEND_AST_ZVAL) {
4781
550
    return FAILURE;
4782
550
  }
4783
4784
948
  zval *format_string = zend_ast_get_zval(args->child[0]);
4785
948
  if (Z_TYPE_P(format_string) != IS_STRING) {
4786
34
    return FAILURE;
4787
34
  }
4788
914
  if (Z_STRLEN_P(format_string) >= 256) {
4789
34
    return FAILURE;
4790
34
  }
4791
4792
880
  char *p;
4793
880
  char *end;
4794
880
  uint32_t placeholder_count;
4795
4796
880
  placeholder_count = 0;
4797
880
  p = Z_STRVAL_P(format_string);
4798
880
  end = p + Z_STRLEN_P(format_string);
4799
4800
2.73k
  for (;;) {
4801
2.73k
    p = memchr(p, '%', end - p);
4802
2.73k
    if (!p) {
4803
730
      break;
4804
730
    }
4805
4806
2.00k
    char *q = p + 1;
4807
2.00k
    if (q == end) {
4808
68
      return FAILURE;
4809
68
    }
4810
4811
1.93k
    switch (*q) {
4812
553
      case 's':
4813
877
      case 'd':
4814
877
        placeholder_count++;
4815
877
        break;
4816
975
      case '%':
4817
975
        break;
4818
82
      default:
4819
82
        return FAILURE;
4820
1.93k
    }
4821
4822
1.85k
    p = q;
4823
1.85k
    p++;
4824
1.85k
  }
4825
4826
  /* Bail out if the number of placeholders does not match the number of values. */
4827
730
  if (placeholder_count != (args->children - 1)) {
4828
95
    return FAILURE;
4829
95
  }
4830
4831
  /* Handle empty format strings. */
4832
635
  if (Z_STRLEN_P(format_string) == 0) {
4833
66
    result->op_type = IS_CONST;
4834
66
    ZVAL_EMPTY_STRING(&result->u.constant);
4835
4836
66
    return SUCCESS;
4837
66
  }
4838
4839
569
  znode *elements = NULL;
4840
4841
569
  if (placeholder_count > 0) {
4842
441
    elements = safe_emalloc(sizeof(*elements), placeholder_count, 0);
4843
441
  }
4844
4845
  /* Compile the value expressions first for error handling that is consistent
4846
   * with a function call: Values that fail to convert to a string may emit errors.
4847
   */
4848
1.37k
  for (uint32_t i = 0; i < placeholder_count; i++) {
4849
801
    zend_compile_expr(elements + i, args->child[1 + i]);
4850
801
  }
4851
4852
569
  uint32_t rope_elements = 0;
4853
569
  uint32_t rope_init_lineno = -1;
4854
569
  zend_op *opline = NULL;
4855
4856
569
  placeholder_count = 0;
4857
569
  p = Z_STRVAL_P(format_string);
4858
569
  end = p + Z_STRLEN_P(format_string);
4859
569
  char *offset = p;
4860
2.11k
  for (;;) {
4861
2.11k
    p = memchr(p, '%', end - p);
4862
2.11k
    if (!p) {
4863
569
      break;
4864
569
    }
4865
4866
1.54k
    char *q = p + 1;
4867
1.54k
    ZEND_ASSERT(q < end);
4868
1.54k
    ZEND_ASSERT(*q == 's' || *q == 'd' || *q == '%');
4869
4870
1.54k
    if (*q == '%') {
4871
      /* Optimization to not create a dedicated rope element for the literal '%':
4872
       * Include the first '%' within the "constant" part instead of dropping the
4873
       * full placeholder.
4874
       */
4875
742
      p++;
4876
742
    }
4877
4878
1.54k
    if (p != offset) {
4879
972
      znode const_node;
4880
972
      const_node.op_type = IS_CONST;
4881
972
      ZVAL_STRINGL(&const_node.u.constant, offset, p - offset);
4882
972
      if (rope_elements == 0) {
4883
235
        rope_init_lineno = get_next_op_number();
4884
235
      }
4885
972
      opline = zend_compile_rope_add(result, rope_elements++, &const_node);
4886
972
    }
4887
4888
1.54k
    if (*q != '%') {
4889
801
      switch (*q) {
4890
501
        case 's':
4891
          /* Perform the cast of constants when actually evaluating the corresponding placeholder
4892
           * for correct error reporting.
4893
           */
4894
501
          if (elements[placeholder_count].op_type == IS_CONST) {
4895
245
            if (Z_TYPE(elements[placeholder_count].u.constant) == IS_ARRAY) {
4896
83
              zend_emit_op_tmp(&elements[placeholder_count], ZEND_CAST, &elements[placeholder_count], NULL)->extended_value = IS_STRING;
4897
162
            } else {
4898
162
              convert_to_string(&elements[placeholder_count].u.constant);
4899
162
            }
4900
245
          }
4901
501
          break;
4902
300
        case 'd':
4903
300
          zend_emit_op_tmp(&elements[placeholder_count], ZEND_CAST, &elements[placeholder_count], NULL)->extended_value = IS_LONG;
4904
300
          break;
4905
0
        EMPTY_SWITCH_DEFAULT_CASE();
4906
801
      }
4907
4908
801
      if (rope_elements == 0) {
4909
246
        rope_init_lineno = get_next_op_number();
4910
246
      }
4911
801
      opline = zend_compile_rope_add(result, rope_elements++, &elements[placeholder_count]);
4912
4913
801
      placeholder_count++;
4914
801
    }
4915
4916
1.54k
    p = q;
4917
1.54k
    p++;
4918
1.54k
    offset = p;
4919
1.54k
  }
4920
569
  if (end != offset) {
4921
    /* Add the constant part after the last placeholder. */
4922
468
    znode const_node;
4923
468
    const_node.op_type = IS_CONST;
4924
468
    ZVAL_STRINGL(&const_node.u.constant, offset, end - offset);
4925
468
    if (rope_elements == 0) {
4926
88
      rope_init_lineno = get_next_op_number();
4927
88
    }
4928
468
    opline = zend_compile_rope_add(result, rope_elements++, &const_node);
4929
468
  }
4930
569
  ZEND_ASSERT(opline != NULL);
4931
4932
569
  zend_op *init_opline = CG(active_op_array)->opcodes + rope_init_lineno;
4933
569
  zend_compile_rope_finalize(result, rope_elements, init_opline, opline);
4934
569
  efree(elements);
4935
4936
569
  return SUCCESS;
4937
569
}
4938
4939
static zend_result zend_try_compile_special_func_ex(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */
4940
121k
{
4941
121k
  if (zend_string_equals_literal(lcname, "strlen")) {
4942
1.23k
    return zend_compile_func_strlen(result, args);
4943
120k
  } else if (zend_string_equals_literal(lcname, "is_null")) {
4944
527
    return zend_compile_func_typecheck(result, args, IS_NULL);
4945
119k
  } else if (zend_string_equals_literal(lcname, "is_bool")) {
4946
80
    return zend_compile_func_typecheck(result, args, _IS_BOOL);
4947
119k
  } else if (zend_string_equals_literal(lcname, "is_long")
4948
119k
    || zend_string_equals_literal(lcname, "is_int")
4949
119k
    || zend_string_equals_literal(lcname, "is_integer")
4950
119k
  ) {
4951
399
    return zend_compile_func_typecheck(result, args, IS_LONG);
4952
119k
  } else if (zend_string_equals_literal(lcname, "is_float")
4953
119k
    || zend_string_equals_literal(lcname, "is_double")
4954
119k
  ) {
4955
717
    return zend_compile_func_typecheck(result, args, IS_DOUBLE);
4956
118k
  } else if (zend_string_equals_literal(lcname, "is_string")) {
4957
82
    return zend_compile_func_typecheck(result, args, IS_STRING);
4958
118k
  } else if (zend_string_equals_literal(lcname, "is_array")) {
4959
566
    return zend_compile_func_typecheck(result, args, IS_ARRAY);
4960
117k
  } else if (zend_string_equals_literal(lcname, "is_object")) {
4961
177
    return zend_compile_func_typecheck(result, args, IS_OBJECT);
4962
117k
  } else if (zend_string_equals_literal(lcname, "is_resource")) {
4963
119
    return zend_compile_func_typecheck(result, args, IS_RESOURCE);
4964
117k
  } else if (zend_string_equals_literal(lcname, "is_scalar")) {
4965
323
    return zend_compile_func_is_scalar(result, args);
4966
117k
  } else if (zend_string_equals_literal(lcname, "boolval")) {
4967
214
    return zend_compile_func_cast(result, args, _IS_BOOL);
4968
117k
  } else if (zend_string_equals_literal(lcname, "intval")) {
4969
628
    return zend_compile_func_cast(result, args, IS_LONG);
4970
116k
  } else if (zend_string_equals_literal(lcname, "floatval")
4971
116k
    || zend_string_equals_literal(lcname, "doubleval")
4972
116k
  ) {
4973
590
    return zend_compile_func_cast(result, args, IS_DOUBLE);
4974
115k
  } else if (zend_string_equals_literal(lcname, "strval")) {
4975
275
    return zend_compile_func_cast(result, args, IS_STRING);
4976
115k
  } else if (zend_string_equals_literal(lcname, "defined")) {
4977
1.53k
    return zend_compile_func_defined(result, args);
4978
114k
  } else if (zend_string_equals_literal(lcname, "chr") && type == BP_VAR_R) {
4979
1.14k
    return zend_compile_func_chr(result, args);
4980
112k
  } else if (zend_string_equals_literal(lcname, "ord") && type == BP_VAR_R) {
4981
614
    return zend_compile_func_ord(result, args);
4982
112k
  } else if (zend_string_equals_literal(lcname, "call_user_func_array")) {
4983
1.90k
    return zend_compile_func_cufa(result, args, lcname);
4984
110k
  } else if (zend_string_equals_literal(lcname, "call_user_func")) {
4985
1.85k
    return zend_compile_func_cuf(result, args, lcname);
4986
108k
  } else if (zend_string_equals_literal(lcname, "in_array")) {
4987
3.87k
    return zend_compile_func_in_array(result, args);
4988
104k
  } else if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_COUNT))
4989
104k
      || zend_string_equals_literal(lcname, "sizeof")) {
4990
1.10k
    return zend_compile_func_count(result, args, lcname);
4991
103k
  } else if (zend_string_equals_literal(lcname, "get_class")) {
4992
1.52k
    return zend_compile_func_get_class(result, args);
4993
102k
  } else if (zend_string_equals_literal(lcname, "get_called_class")) {
4994
213
    return zend_compile_func_get_called_class(result, args);
4995
101k
  } else if (zend_string_equals_literal(lcname, "gettype")) {
4996
1.33k
    return zend_compile_func_gettype(result, args);
4997
100k
  } else if (zend_string_equals_literal(lcname, "func_num_args")) {
4998
610
    return zend_compile_func_num_args(result, args);
4999
99.8k
  } else if (zend_string_equals_literal(lcname, "func_get_args")) {
5000
548
    return zend_compile_func_get_args(result, args);
5001
99.3k
  } else if (zend_string_equals_literal(lcname, "array_slice")) {
5002
1.64k
    return zend_compile_func_array_slice(result, args);
5003
97.6k
  } else if (zend_string_equals_literal(lcname, "array_key_exists")) {
5004
353
    return zend_compile_func_array_key_exists(result, args);
5005
97.3k
  } else if (zend_string_equals_literal(lcname, "sprintf")) {
5006
1.56k
    return zend_compile_func_sprintf(result, args);
5007
95.7k
  } else {
5008
95.7k
    return FAILURE;
5009
95.7k
  }
5010
121k
}
5011
5012
static zend_result zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */
5013
144k
{
5014
144k
  if (CG(compiler_options) & ZEND_COMPILE_NO_BUILTINS) {
5015
0
    return FAILURE;
5016
0
  }
5017
5018
144k
  if (fbc->type != ZEND_INTERNAL_FUNCTION) {
5019
    /* If the function is part of disabled_functions, it may be redeclared as a userland
5020
     * function with a different implementation. Don't use the VM builtin in that case. */
5021
21.3k
    return FAILURE;
5022
21.3k
  }
5023
5024
123k
  if (zend_args_contain_unpack_or_named(args)) {
5025
1.88k
    return FAILURE;
5026
1.88k
  }
5027
5028
121k
  if (zend_try_compile_special_func_ex(result, lcname, args, fbc, type) == SUCCESS) {
5029
15.5k
    return SUCCESS;
5030
15.5k
  }
5031
5032
106k
  return zend_compile_frameless_icall(result, args, fbc, type) != (uint32_t)-1 ? SUCCESS : FAILURE;
5033
121k
}
5034
5035
7
static const char *zend_get_cstring_from_property_hook_kind(zend_property_hook_kind kind) {
5036
7
  switch (kind) {
5037
1
    case ZEND_PROPERTY_HOOK_GET:
5038
1
      return "get";
5039
6
    case ZEND_PROPERTY_HOOK_SET:
5040
6
      return "set";
5041
7
    EMPTY_SWITCH_DEFAULT_CASE()
5042
7
  }
5043
7
}
5044
5045
static zend_string *zend_copy_unmangled_prop_name(zend_string *prop_name)
5046
456
{
5047
456
  if (ZSTR_VAL(prop_name)[0] != '\0') {
5048
313
    return zend_string_copy(prop_name);
5049
313
  } else {
5050
143
    const char *unmangled = zend_get_unmangled_property_name(prop_name);
5051
143
    return zend_string_init(unmangled, strlen(unmangled), /* persistent */ false);
5052
143
  }
5053
456
}
5054
5055
static bool zend_compile_parent_property_hook_call(znode *result, zend_ast *ast, uint32_t type)
5056
16.0k
{
5057
16.0k
  ZEND_ASSERT(ast->kind == ZEND_AST_STATIC_CALL);
5058
5059
16.0k
  zend_ast *class_ast = ast->child[0];
5060
16.0k
  zend_ast *method_ast = ast->child[1];
5061
5062
  /* Recognize parent::$prop::get() pattern. */
5063
16.0k
  if (class_ast->kind != ZEND_AST_STATIC_PROP
5064
16.0k
   || (class_ast->attr & ZEND_PARENTHESIZED_STATIC_PROP)
5065
16.0k
   || class_ast->child[0]->kind != ZEND_AST_ZVAL
5066
16.0k
   || Z_TYPE_P(zend_ast_get_zval(class_ast->child[0])) != IS_STRING
5067
16.0k
   || zend_get_class_fetch_type(zend_ast_get_str(class_ast->child[0])) != ZEND_FETCH_CLASS_PARENT
5068
16.0k
   || class_ast->child[1]->kind != ZEND_AST_ZVAL
5069
16.0k
   || method_ast->kind != ZEND_AST_ZVAL
5070
16.0k
   || Z_TYPE_P(zend_ast_get_zval(method_ast)) != IS_STRING
5071
16.0k
   || (!zend_string_equals_literal_ci(zend_ast_get_str(method_ast), "get")
5072
15.3k
    && !zend_string_equals_literal_ci(zend_ast_get_str(method_ast), "set"))) {
5073
15.3k
    return false;
5074
15.3k
  }
5075
5076
675
  zend_class_entry *ce = CG(active_class_entry);
5077
675
  if (!ce) {
5078
7
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"parent\" when no class scope is active");
5079
7
  }
5080
5081
668
  zend_ast *args_ast = ast->child[2];
5082
668
  if (args_ast->kind == ZEND_AST_CALLABLE_CONVERT) {
5083
6
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot create Closure for parent property hook call");
5084
6
  }
5085
5086
662
  zval *property_hook_name_zv = zend_ast_get_zval(class_ast->child[1]);
5087
662
  zend_string *property_name = zval_get_string(property_hook_name_zv);
5088
662
  zend_string *hook_name = zend_ast_get_str(method_ast);
5089
662
  zend_property_hook_kind hook_kind = zend_get_property_hook_kind_from_name(hook_name);
5090
662
  ZEND_ASSERT(hook_kind != (uint32_t)-1);
5091
5092
662
  const zend_string *prop_info_name = CG(context).active_property_info_name;
5093
662
  if (!prop_info_name) {
5094
6
    zend_error_noreturn(E_COMPILE_ERROR, "Must not use parent::$%s::%s() outside a property hook",
5095
6
      ZSTR_VAL(property_name), ZSTR_VAL(hook_name));
5096
6
  }
5097
5098
656
  const char *unmangled_prop_name = zend_get_unmangled_property_name(prop_info_name);
5099
656
  if (!zend_string_equals_cstr(property_name, unmangled_prop_name, strlen(unmangled_prop_name))) {
5100
27
    zend_error_noreturn(E_COMPILE_ERROR, "Must not use parent::$%s::%s() in a different property ($%s)",
5101
27
      ZSTR_VAL(property_name), ZSTR_VAL(hook_name), unmangled_prop_name);
5102
27
  }
5103
629
  if (hook_kind != CG(context).active_property_hook_kind) {
5104
7
    zend_error_noreturn(E_COMPILE_ERROR, "Must not use parent::$%s::%s() in a different property hook (%s)",
5105
7
      ZSTR_VAL(property_name), ZSTR_VAL(hook_name), zend_get_cstring_from_property_hook_kind(CG(context).active_property_hook_kind));
5106
7
  }
5107
5108
622
  zend_op *opline = get_next_op();
5109
622
  opline->opcode = ZEND_INIT_PARENT_PROPERTY_HOOK_CALL;
5110
622
  opline->op1_type = IS_CONST;
5111
622
  opline->op1.constant = zend_add_literal_string(&property_name);
5112
622
  opline->op2.num = hook_kind;
5113
5114
622
  zend_function *fbc = NULL;
5115
622
  zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast));
5116
5117
622
  return true;
5118
629
}
5119
5120
static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
5121
242k
{
5122
242k
  zend_ast *name_ast = ast->child[0];
5123
242k
  zend_ast *args_ast = ast->child[1];
5124
242k
  bool is_callable_convert = args_ast->kind == ZEND_AST_CALLABLE_CONVERT;
5125
5126
242k
  znode name_node;
5127
5128
242k
  if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
5129
13.5k
    zend_compile_expr(&name_node, name_ast);
5130
13.5k
    zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno);
5131
13.5k
    return;
5132
13.5k
  }
5133
5134
229k
  {
5135
229k
    bool runtime_resolution = zend_compile_function_name(&name_node, name_ast);
5136
229k
    if (runtime_resolution) {
5137
16.5k
      if (zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "assert")
5138
16.5k
          && !is_callable_convert) {
5139
1.12k
        zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL, ast->lineno);
5140
15.4k
      } else {
5141
15.4k
        zend_compile_ns_call(result, &name_node, args_ast, ast->lineno, type);
5142
15.4k
      }
5143
16.5k
      return;
5144
16.5k
    }
5145
229k
  }
5146
5147
212k
  {
5148
212k
    zval *name = &name_node.u.constant;
5149
212k
    zend_string *lcname;
5150
212k
    zend_function *fbc;
5151
212k
    zend_op *opline;
5152
5153
212k
    lcname = zend_string_tolower(Z_STR_P(name));
5154
212k
    zval *fbc_zv = zend_hash_find(CG(function_table), lcname);
5155
212k
    fbc = fbc_zv ? Z_PTR_P(fbc_zv) : NULL;
5156
5157
    /* Special assert() handling should apply independently of compiler flags. */
5158
212k
    if (fbc && zend_string_equals_literal(lcname, "assert") && !is_callable_convert) {
5159
22.9k
      zend_compile_assert(result, zend_ast_get_list(args_ast), lcname, fbc, ast->lineno);
5160
22.9k
      zend_string_release(lcname);
5161
22.9k
      zval_ptr_dtor(&name_node.u.constant);
5162
22.9k
      return;
5163
22.9k
    }
5164
5165
189k
    if (!fbc
5166
189k
     || !fbc_is_finalized(fbc)
5167
189k
     || zend_compile_ignore_function(fbc, CG(active_op_array)->filename)) {
5168
44.3k
      zend_string_release_ex(lcname, 0);
5169
44.3k
      zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno);
5170
44.3k
      return;
5171
44.3k
    }
5172
5173
145k
    if (!is_callable_convert &&
5174
145k
        zend_try_compile_special_func(result, lcname,
5175
144k
        zend_ast_get_list(args_ast), fbc, type) == SUCCESS
5176
145k
    ) {
5177
18.5k
      zend_string_release_ex(lcname, 0);
5178
18.5k
      zval_ptr_dtor(&name_node.u.constant);
5179
18.5k
      return;
5180
18.5k
    }
5181
5182
126k
    zval_ptr_dtor(&name_node.u.constant);
5183
126k
    ZVAL_NEW_STR(&name_node.u.constant, lcname);
5184
5185
126k
    opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
5186
126k
    opline->result.num = zend_alloc_cache_slot();
5187
5188
    /* Store offset to function from symbol table in op2.extra. */
5189
126k
    if (fbc->type == ZEND_INTERNAL_FUNCTION) {
5190
105k
      Bucket *fbc_bucket = (Bucket*)((uintptr_t)fbc_zv - XtOffsetOf(Bucket, val));
5191
105k
      Z_EXTRA_P(CT_CONSTANT(opline->op2)) = fbc_bucket - CG(function_table)->arData;
5192
105k
    }
5193
5194
126k
    zend_compile_call_common(result, args_ast, fbc, ast->lineno);
5195
126k
  }
5196
126k
}
5197
/* }}} */
5198
5199
static void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
5200
53.1k
{
5201
53.1k
  zend_ast *obj_ast = ast->child[0];
5202
53.1k
  zend_ast *method_ast = ast->child[1];
5203
53.1k
  zend_ast *args_ast = ast->child[2];
5204
5205
53.1k
  znode obj_node, method_node;
5206
53.1k
  zend_op *opline;
5207
53.1k
  zend_function *fbc = NULL;
5208
53.1k
  bool nullsafe = ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL;
5209
53.1k
  uint32_t short_circuiting_checkpoint = zend_short_circuiting_checkpoint();
5210
5211
53.1k
  if (is_this_fetch(obj_ast)) {
5212
958
    if (this_guaranteed_exists()) {
5213
836
      obj_node.op_type = IS_UNUSED;
5214
836
    } else {
5215
122
      zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL);
5216
122
    }
5217
958
    CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
5218
5219
    /* We will throw if $this doesn't exist, so there's no need to emit a JMP_NULL
5220
     * check for a nullsafe access. */
5221
52.1k
  } else {
5222
52.1k
    zend_short_circuiting_mark_inner(obj_ast);
5223
52.1k
    zend_compile_expr(&obj_node, obj_ast);
5224
52.1k
    if (nullsafe) {
5225
3.25k
      zend_emit_jmp_null(&obj_node, type);
5226
3.25k
    }
5227
52.1k
  }
5228
5229
53.1k
  zend_compile_expr(&method_node, method_ast);
5230
53.1k
  opline = zend_emit_op(NULL, ZEND_INIT_METHOD_CALL, &obj_node, NULL);
5231
5232
53.1k
  if (method_node.op_type == IS_CONST) {
5233
52.0k
    if (Z_TYPE(method_node.u.constant) != IS_STRING) {
5234
6
      zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
5235
6
    }
5236
5237
52.0k
    opline->op2_type = IS_CONST;
5238
52.0k
    opline->op2.constant = zend_add_func_name_literal(
5239
52.0k
      Z_STR(method_node.u.constant));
5240
52.0k
    opline->result.num = zend_alloc_cache_slots(2);
5241
52.0k
  } else {
5242
1.08k
    SET_NODE(opline->op2, &method_node);
5243
1.08k
  }
5244
5245
  /* Check if this calls a known method on $this */
5246
53.1k
  if (opline->op1_type == IS_UNUSED && opline->op2_type == IS_CONST &&
5247
53.1k
      CG(active_class_entry) && zend_is_scope_known()) {
5248
644
    zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op2) + 1);
5249
644
    fbc = zend_hash_find_ptr(&CG(active_class_entry)->function_table, lcname);
5250
5251
    /* We only know the exact method that is being called if it is either private or final.
5252
     * Otherwise an overriding method in a child class may be called. */
5253
644
    if (fbc && !(fbc->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_FINAL))) {
5254
274
      fbc = NULL;
5255
274
    }
5256
644
  }
5257
5258
53.1k
  if (zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast))) {
5259
332
    if (short_circuiting_checkpoint != zend_short_circuiting_checkpoint()) {
5260
14
      zend_error_noreturn(E_COMPILE_ERROR,
5261
14
        "Cannot combine nullsafe operator with Closure creation");
5262
14
    }
5263
332
  }
5264
53.1k
}
5265
/* }}} */
5266
5267
static bool zend_is_constructor(zend_string *name) /* {{{ */
5268
14.7k
{
5269
14.7k
  return zend_string_equals_literal_ci(name, ZEND_CONSTRUCTOR_FUNC_NAME);
5270
14.7k
}
5271
/* }}} */
5272
5273
static zend_function *zend_get_compatible_func_or_null(zend_class_entry *ce, zend_string *lcname) /* {{{ */
5274
5.16k
{
5275
5.16k
  zend_function *fbc = zend_hash_find_ptr(&ce->function_table, lcname);
5276
5.16k
  if (!fbc || (fbc->common.fn_flags & ZEND_ACC_PUBLIC) || ce == CG(active_class_entry)) {
5277
4.92k
    return fbc;
5278
4.92k
  }
5279
5280
244
  if (!(fbc->common.fn_flags & ZEND_ACC_PRIVATE)
5281
244
    && (fbc->common.scope->ce_flags & ZEND_ACC_LINKED)
5282
244
    && (!CG(active_class_entry) || (CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED))
5283
244
    && zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry))) {
5284
0
    return fbc;
5285
0
  }
5286
5287
244
  return NULL;
5288
244
}
5289
/* }}} */
5290
5291
static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
5292
16.0k
{
5293
16.0k
  zend_ast *class_ast = ast->child[0];
5294
16.0k
  zend_ast *method_ast = ast->child[1];
5295
16.0k
  zend_ast *args_ast = ast->child[2];
5296
5297
16.0k
  znode class_node, method_node;
5298
16.0k
  zend_op *opline;
5299
16.0k
  zend_function *fbc = NULL;
5300
5301
16.0k
  if (zend_compile_parent_property_hook_call(result, ast, type)) {
5302
622
    return;
5303
622
  }
5304
5305
15.4k
  zend_short_circuiting_mark_inner(class_ast);
5306
15.4k
  zend_compile_class_ref(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
5307
5308
15.4k
  zend_compile_expr(&method_node, method_ast);
5309
5310
15.4k
  if (method_node.op_type == IS_CONST) {
5311
13.5k
    zval *name = &method_node.u.constant;
5312
13.5k
    if (Z_TYPE_P(name) != IS_STRING) {
5313
3
      zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
5314
3
    }
5315
13.5k
    if (zend_is_constructor(Z_STR_P(name))) {
5316
313
      zval_ptr_dtor(name);
5317
313
      method_node.op_type = IS_UNUSED;
5318
313
    }
5319
13.5k
  }
5320
5321
15.4k
  opline = get_next_op();
5322
15.4k
  opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
5323
5324
15.4k
  zend_set_class_name_op1(opline, &class_node);
5325
5326
15.4k
  if (method_node.op_type == IS_CONST) {
5327
13.2k
    opline->op2_type = IS_CONST;
5328
13.2k
    opline->op2.constant = zend_add_func_name_literal(
5329
13.2k
      Z_STR(method_node.u.constant));
5330
13.2k
    opline->result.num = zend_alloc_cache_slots(2);
5331
13.2k
  } else {
5332
2.19k
    if (opline->op1_type == IS_CONST) {
5333
519
      opline->result.num = zend_alloc_cache_slot();
5334
519
    }
5335
2.19k
    SET_NODE(opline->op2, &method_node);
5336
2.19k
  }
5337
5338
  /* Check if we already know which method we're calling */
5339
15.4k
  if (opline->op2_type == IS_CONST) {
5340
13.2k
    zend_class_entry *ce = NULL;
5341
13.2k
    if (opline->op1_type == IS_CONST) {
5342
8.39k
      zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op1) + 1);
5343
8.39k
      ce = zend_hash_find_ptr(CG(class_table), lcname);
5344
8.39k
      if (ce) {
5345
4.54k
        if (zend_compile_ignore_class(ce, CG(active_op_array)->filename)) {
5346
0
          ce = NULL;
5347
0
        }
5348
4.54k
      } else if (CG(active_class_entry)
5349
3.85k
          && zend_string_equals_ci(CG(active_class_entry)->name, lcname)) {
5350
300
        ce = CG(active_class_entry);
5351
300
      }
5352
8.39k
    } else if (opline->op1_type == IS_UNUSED
5353
4.84k
        && (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF
5354
4.84k
        && zend_is_scope_known()) {
5355
327
      ce = CG(active_class_entry);
5356
327
    }
5357
13.2k
    if (ce) {
5358
5.16k
      zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op2) + 1);
5359
5.16k
      fbc = zend_get_compatible_func_or_null(ce, lcname);
5360
5.16k
    }
5361
13.2k
  }
5362
5363
15.4k
  zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast));
5364
15.4k
}
5365
/* }}} */
5366
5367
static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel);
5368
5369
static void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
5370
84.1k
{
5371
84.1k
  zend_ast *class_ast = ast->child[0];
5372
84.1k
  zend_ast *args_ast = ast->child[1];
5373
5374
84.1k
  znode class_node, ctor_result;
5375
84.1k
  zend_op *opline;
5376
5377
84.1k
  if (class_ast->kind == ZEND_AST_CLASS) {
5378
    /* anon class declaration */
5379
2.11k
    zend_compile_class_decl(&class_node, class_ast, 0);
5380
82.0k
  } else {
5381
82.0k
    zend_compile_class_ref(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
5382
82.0k
  }
5383
5384
84.1k
  opline = zend_emit_op(result, ZEND_NEW, NULL, NULL);
5385
5386
84.1k
  if (class_node.op_type == IS_CONST) {
5387
80.4k
    opline->op1_type = IS_CONST;
5388
80.4k
    opline->op1.constant = zend_add_class_name_literal(
5389
80.4k
      Z_STR(class_node.u.constant));
5390
80.4k
    opline->op2.num = zend_alloc_cache_slot();
5391
80.4k
  } else {
5392
3.69k
    SET_NODE(opline->op1, &class_node);
5393
3.69k
  }
5394
5395
84.1k
  zend_compile_call_common(&ctor_result, args_ast, NULL, ast->lineno);
5396
84.1k
  zend_do_free(&ctor_result);
5397
84.1k
}
5398
/* }}} */
5399
5400
static void zend_compile_clone(znode *result, zend_ast *ast) /* {{{ */
5401
774
{
5402
774
  zend_ast *obj_ast = ast->child[0];
5403
5404
774
  znode obj_node;
5405
774
  zend_compile_expr(&obj_node, obj_ast);
5406
5407
774
  zend_emit_op_tmp(result, ZEND_CLONE, &obj_node, NULL);
5408
774
}
5409
/* }}} */
5410
5411
static void zend_compile_global_var(zend_ast *ast) /* {{{ */
5412
2.24k
{
5413
2.24k
  zend_ast *var_ast = ast->child[0];
5414
2.24k
  zend_ast *name_ast = var_ast->child[0];
5415
5416
2.24k
  znode name_node, result;
5417
5418
2.24k
  zend_compile_expr(&name_node, name_ast);
5419
2.24k
  if (name_node.op_type == IS_CONST) {
5420
1.80k
    convert_to_string(&name_node.u.constant);
5421
1.80k
  }
5422
5423
  // TODO(GLOBALS) Forbid "global $GLOBALS"?
5424
2.24k
  if (is_this_fetch(var_ast)) {
5425
6
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as global variable");
5426
2.23k
  } else if (zend_try_compile_cv(&result, var_ast) == SUCCESS) {
5427
1.30k
    zend_op *opline = zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node);
5428
1.30k
    opline->extended_value = zend_alloc_cache_slot();
5429
1.30k
  } else {
5430
    /* name_ast should be evaluated only. FETCH_GLOBAL_LOCK instructs FETCH_W
5431
     * to not free the name_node operand, so it can be reused in the following
5432
     * ASSIGN_REF, which then frees it. */
5433
933
    zend_op *opline = zend_emit_op(&result, ZEND_FETCH_W, &name_node, NULL);
5434
933
    opline->extended_value = ZEND_FETCH_GLOBAL_LOCK;
5435
5436
933
    if (name_node.op_type == IS_CONST) {
5437
498
      zend_string_addref(Z_STR(name_node.u.constant));
5438
498
    }
5439
5440
933
    zend_emit_assign_ref_znode(
5441
933
      zend_ast_create(ZEND_AST_VAR, zend_ast_create_znode(&name_node)),
5442
933
      &result
5443
933
    );
5444
933
  }
5445
2.24k
}
5446
/* }}} */
5447
5448
static void zend_compile_static_var_common(zend_string *var_name, zval *value, uint32_t mode) /* {{{ */
5449
98.8k
{
5450
98.8k
  zend_op *opline;
5451
98.8k
  if (!CG(active_op_array)->static_variables) {
5452
0
    if (CG(active_op_array)->scope) {
5453
0
      CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
5454
0
    }
5455
0
    CG(active_op_array)->static_variables = zend_new_array(8);
5456
0
  }
5457
5458
98.8k
  value = zend_hash_update(CG(active_op_array)->static_variables, var_name, value);
5459
5460
98.8k
  if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) {
5461
0
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as static variable");
5462
0
  }
5463
5464
98.8k
  opline = zend_emit_op(NULL, ZEND_BIND_STATIC, NULL, NULL);
5465
98.8k
  opline->op1_type = IS_CV;
5466
98.8k
  opline->op1.var = lookup_cv(var_name);
5467
98.8k
  opline->extended_value = (uint32_t)((char*)value - (char*)CG(active_op_array)->static_variables->arData) | mode;
5468
98.8k
}
5469
/* }}} */
5470
5471
static void zend_compile_static_var(zend_ast *ast) /* {{{ */
5472
1.09k
{
5473
1.09k
  zend_ast *var_ast = ast->child[0];
5474
1.09k
  zend_string *var_name = zend_ast_get_str(var_ast);
5475
5476
1.09k
  if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) {
5477
6
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as static variable");
5478
6
  }
5479
5480
1.08k
  if (!CG(active_op_array)->static_variables) {
5481
907
    if (CG(active_op_array)->scope) {
5482
294
      CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
5483
294
    }
5484
907
    CG(active_op_array)->static_variables = zend_new_array(8);
5485
907
  }
5486
5487
1.08k
  if (zend_hash_exists(CG(active_op_array)->static_variables, var_name)) {
5488
20
    zend_error_noreturn_unchecked(E_COMPILE_ERROR, "Duplicate declaration of static variable $%S", var_name);
5489
20
  }
5490
5491
1.06k
  zend_eval_const_expr(&ast->child[1]);
5492
1.06k
  zend_ast *value_ast = ast->child[1];
5493
5494
1.06k
  if (!value_ast || value_ast->kind == ZEND_AST_ZVAL) {
5495
626
    zval *value_zv = value_ast
5496
626
      ? zend_ast_get_zval(value_ast)
5497
626
      : &EG(uninitialized_zval);
5498
626
    Z_TRY_ADDREF_P(value_zv);
5499
626
    zend_compile_static_var_common(var_name, value_zv, ZEND_BIND_REF);
5500
626
  } else {
5501
442
    zend_op *opline;
5502
5503
442
    zval *placeholder_ptr = zend_hash_update(CG(active_op_array)->static_variables, var_name, &EG(uninitialized_zval));
5504
442
    uint32_t placeholder_offset = (uint32_t)((char*)placeholder_ptr - (char*)CG(active_op_array)->static_variables->arData);
5505
5506
442
    uint32_t static_def_jmp_opnum = get_next_op_number();
5507
442
    opline = zend_emit_op(NULL, ZEND_BIND_INIT_STATIC_OR_JMP, NULL, NULL);
5508
442
    opline->op1_type = IS_CV;
5509
442
    opline->op1.var = lookup_cv(var_name);
5510
442
    opline->extended_value = placeholder_offset;
5511
5512
442
    znode expr;
5513
442
    zend_compile_expr(&expr, value_ast);
5514
5515
442
    opline = zend_emit_op(NULL, ZEND_BIND_STATIC, NULL, &expr);
5516
442
    opline->op1_type = IS_CV;
5517
442
    opline->op1.var = lookup_cv(var_name);
5518
442
    opline->extended_value = placeholder_offset | ZEND_BIND_REF;
5519
5520
442
    zend_update_jump_target_to_next(static_def_jmp_opnum);
5521
442
  }
5522
1.06k
}
5523
/* }}} */
5524
5525
static void zend_compile_unset(zend_ast *ast) /* {{{ */
5526
6.19k
{
5527
6.19k
  zend_ast *var_ast = ast->child[0];
5528
6.19k
  znode var_node;
5529
6.19k
  zend_op *opline;
5530
5531
6.19k
  zend_ensure_writable_variable(var_ast);
5532
5533
6.19k
  if (is_global_var_fetch(var_ast)) {
5534
301
    if (!var_ast->child[1]) {
5535
6
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting");
5536
6
    }
5537
5538
295
    zend_compile_expr(&var_node, var_ast->child[1]);
5539
295
    if (var_node.op_type == IS_CONST) {
5540
218
      convert_to_string(&var_node.u.constant);
5541
218
    }
5542
5543
295
    opline = zend_emit_op(NULL, ZEND_UNSET_VAR, &var_node, NULL);
5544
295
    opline->extended_value = ZEND_FETCH_GLOBAL;
5545
295
    return;
5546
301
  }
5547
5548
5.89k
  switch (var_ast->kind) {
5549
3.07k
    case ZEND_AST_VAR:
5550
3.07k
      if (is_this_fetch(var_ast)) {
5551
11
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot unset $this");
5552
3.06k
      } else if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) {
5553
2.78k
        opline = zend_emit_op(NULL, ZEND_UNSET_CV, &var_node, NULL);
5554
2.78k
      } else {
5555
284
        opline = zend_compile_simple_var_no_cv(NULL, var_ast, BP_VAR_UNSET, 0);
5556
284
        opline->opcode = ZEND_UNSET_VAR;
5557
284
      }
5558
3.06k
      return;
5559
3.06k
    case ZEND_AST_DIM:
5560
1.48k
      opline = zend_compile_dim(NULL, var_ast, BP_VAR_UNSET, /* by_ref */ false);
5561
1.48k
      opline->opcode = ZEND_UNSET_DIM;
5562
1.48k
      return;
5563
1.23k
    case ZEND_AST_PROP:
5564
1.23k
    case ZEND_AST_NULLSAFE_PROP:
5565
1.23k
      opline = zend_compile_prop(NULL, var_ast, BP_VAR_UNSET, 0);
5566
1.23k
      opline->opcode = ZEND_UNSET_OBJ;
5567
1.23k
      return;
5568
82
    case ZEND_AST_STATIC_PROP:
5569
82
      opline = zend_compile_static_prop(NULL, var_ast, BP_VAR_UNSET, 0, 0);
5570
82
      opline->opcode = ZEND_UNSET_STATIC_PROP;
5571
82
      return;
5572
5.89k
    EMPTY_SWITCH_DEFAULT_CASE()
5573
5.89k
  }
5574
5.89k
}
5575
/* }}} */
5576
5577
static bool zend_handle_loops_and_finally_ex(zend_long depth, znode *return_value) /* {{{ */
5578
41.3k
{
5579
41.3k
  zend_loop_var *base;
5580
41.3k
  zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack));
5581
5582
41.3k
  if (!loop_var) {
5583
1.37k
    return 1;
5584
1.37k
  }
5585
39.9k
  base = zend_stack_base(&CG(loop_var_stack));
5586
49.3k
  for (; loop_var >= base; loop_var--) {
5587
48.0k
    if (loop_var->opcode == ZEND_FAST_CALL) {
5588
3.41k
      zend_op *opline = get_next_op();
5589
5590
3.41k
      opline->opcode = ZEND_FAST_CALL;
5591
3.41k
      opline->result_type = IS_TMP_VAR;
5592
3.41k
      opline->result.var = loop_var->var_num;
5593
3.41k
      if (return_value) {
5594
1.09k
        SET_NODE(opline->op2, return_value);
5595
1.09k
      }
5596
3.41k
      opline->op1.num = loop_var->try_catch_offset;
5597
44.6k
    } else if (loop_var->opcode == ZEND_DISCARD_EXCEPTION) {
5598
2.70k
      zend_op *opline = get_next_op();
5599
2.70k
      opline->opcode = ZEND_DISCARD_EXCEPTION;
5600
2.70k
      opline->op1_type = IS_TMP_VAR;
5601
2.70k
      opline->op1.var = loop_var->var_num;
5602
41.9k
    } else if (loop_var->opcode == ZEND_RETURN) {
5603
      /* Stack separator */
5604
36.4k
      break;
5605
36.4k
    } else if (depth <= 1) {
5606
2.19k
      return 1;
5607
3.27k
    } else if (loop_var->opcode == ZEND_NOP) {
5608
      /* Loop doesn't have freeable variable */
5609
2.06k
      depth--;
5610
2.06k
    } else {
5611
1.21k
      zend_op *opline;
5612
5613
1.21k
      ZEND_ASSERT(loop_var->var_type & (IS_VAR|IS_TMP_VAR));
5614
1.21k
      opline = get_next_op();
5615
1.21k
      opline->opcode = loop_var->opcode;
5616
1.21k
      opline->op1_type = loop_var->var_type;
5617
1.21k
      opline->op1.var = loop_var->var_num;
5618
1.21k
      opline->extended_value = ZEND_FREE_ON_RETURN;
5619
1.21k
      depth--;
5620
1.21k
      }
5621
48.0k
  }
5622
37.7k
  return (depth == 0);
5623
39.9k
}
5624
/* }}} */
5625
5626
static bool zend_handle_loops_and_finally(znode *return_value) /* {{{ */
5627
39.0k
{
5628
39.0k
  return zend_handle_loops_and_finally_ex(zend_stack_count(&CG(loop_var_stack)) + 1, return_value);
5629
39.0k
}
5630
/* }}} */
5631
5632
static bool zend_has_finally_ex(zend_long depth) /* {{{ */
5633
755
{
5634
755
  zend_loop_var *base;
5635
755
  zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack));
5636
5637
755
  if (!loop_var) {
5638
258
    return 0;
5639
258
  }
5640
497
  base = zend_stack_base(&CG(loop_var_stack));
5641
672
  for (; loop_var >= base; loop_var--) {
5642
588
    if (loop_var->opcode == ZEND_FAST_CALL) {
5643
280
      return 1;
5644
308
    } else if (loop_var->opcode == ZEND_DISCARD_EXCEPTION) {
5645
216
    } else if (loop_var->opcode == ZEND_RETURN) {
5646
      /* Stack separator */
5647
133
      return 0;
5648
133
    } else if (depth <= 1) {
5649
0
      return 0;
5650
83
    } else {
5651
83
      depth--;
5652
83
      }
5653
588
  }
5654
84
  return 0;
5655
497
}
5656
/* }}} */
5657
5658
static bool zend_has_finally(void) /* {{{ */
5659
755
{
5660
755
  return zend_has_finally_ex(zend_stack_count(&CG(loop_var_stack)) + 1);
5661
755
}
5662
/* }}} */
5663
5664
static void zend_compile_return(zend_ast *ast) /* {{{ */
5665
38.0k
{
5666
38.0k
  zend_ast *expr_ast = ast->child[0];
5667
38.0k
  bool is_generator = (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0;
5668
38.0k
  bool by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
5669
5670
38.0k
  znode expr_node;
5671
38.0k
  zend_op *opline;
5672
5673
38.0k
  if (is_generator) {
5674
    /* For generators the by-ref flag refers to yields, not returns */
5675
1.58k
    by_ref = 0;
5676
1.58k
  }
5677
5678
38.0k
  if (!expr_ast) {
5679
1.95k
    expr_node.op_type = IS_CONST;
5680
1.95k
    ZVAL_NULL(&expr_node.u.constant);
5681
36.0k
  } else if (by_ref && zend_is_variable(expr_ast)) {
5682
1.91k
    zend_assert_not_short_circuited(expr_ast);
5683
1.91k
    zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1);
5684
34.1k
  } else {
5685
34.1k
    zend_compile_expr(&expr_node, expr_ast);
5686
34.1k
  }
5687
5688
38.0k
  if ((CG(active_op_array)->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)
5689
38.0k
   && (expr_node.op_type == IS_CV || (by_ref && expr_node.op_type == IS_VAR))
5690
38.0k
   && zend_has_finally()) {
5691
    /* Copy return value into temporary VAR to avoid modification in finally code */
5692
280
    if (by_ref) {
5693
130
      zend_emit_op(&expr_node, ZEND_MAKE_REF, &expr_node, NULL);
5694
150
    } else {
5695
150
      zend_emit_op_tmp(&expr_node, ZEND_QM_ASSIGN, &expr_node, NULL);
5696
150
    }
5697
280
  }
5698
5699
  /* Generator return types are handled separately */
5700
38.0k
  if (!is_generator && (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
5701
5.76k
    zend_emit_return_type_check(
5702
5.76k
      expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1, 0);
5703
5.76k
  }
5704
5705
38.0k
  zend_handle_loops_and_finally((expr_node.op_type & (IS_TMP_VAR | IS_VAR)) ? &expr_node : NULL);
5706
5707
38.0k
  opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN,
5708
38.0k
    &expr_node, NULL);
5709
5710
38.0k
  if (by_ref && expr_ast) {
5711
3.06k
    if (zend_is_call(expr_ast)) {
5712
610
      opline->extended_value = ZEND_RETURNS_FUNCTION;
5713
2.45k
    } else if (!zend_is_variable(expr_ast) || zend_ast_is_short_circuited(expr_ast)) {
5714
549
      opline->extended_value = ZEND_RETURNS_VALUE;
5715
549
    }
5716
3.06k
  }
5717
38.0k
}
5718
/* }}} */
5719
5720
static void zend_compile_void_cast(znode *result, zend_ast *ast)
5721
481
{
5722
481
  zend_ast *expr_ast = ast->child[0];
5723
481
  znode expr_node;
5724
481
  zend_op *opline;
5725
5726
481
  zend_compile_expr(&expr_node, expr_ast);
5727
5728
481
  switch (expr_node.op_type) {
5729
149
    case IS_TMP_VAR:
5730
353
    case IS_VAR:
5731
353
      opline = zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
5732
353
      opline->extended_value = ZEND_FREE_VOID_CAST;
5733
353
      break;
5734
90
    case IS_CONST:
5735
90
      zend_do_free(&expr_node);
5736
90
      break;
5737
481
  }
5738
481
}
5739
5740
static void zend_compile_echo(zend_ast *ast) /* {{{ */
5741
181k
{
5742
181k
  zend_op *opline;
5743
181k
  zend_ast *expr_ast = ast->child[0];
5744
5745
181k
  znode expr_node;
5746
181k
  zend_compile_expr(&expr_node, expr_ast);
5747
5748
181k
  opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL);
5749
181k
  opline->extended_value = 0;
5750
181k
}
5751
/* }}} */
5752
5753
static void zend_compile_throw(znode *result, zend_ast *ast) /* {{{ */
5754
3.13k
{
5755
3.13k
  zend_ast *expr_ast = ast->child[0];
5756
5757
3.13k
  znode expr_node;
5758
3.13k
  zend_compile_expr(&expr_node, expr_ast);
5759
5760
3.13k
  zend_op *opline = zend_emit_op(NULL, ZEND_THROW, &expr_node, NULL);
5761
3.13k
  if (result) {
5762
    /* Mark this as an "expression throw" for opcache. */
5763
585
    opline->extended_value = ZEND_THROW_IS_EXPR;
5764
585
    result->op_type = IS_CONST;
5765
585
    ZVAL_TRUE(&result->u.constant);
5766
585
  }
5767
3.13k
}
5768
/* }}} */
5769
5770
static void zend_compile_break_continue(zend_ast *ast) /* {{{ */
5771
2.42k
{
5772
2.42k
  zend_ast *depth_ast = ast->child[0];
5773
5774
2.42k
  zend_op *opline;
5775
2.42k
  zend_long depth;
5776
5777
2.42k
  ZEND_ASSERT(ast->kind == ZEND_AST_BREAK || ast->kind == ZEND_AST_CONTINUE);
5778
5779
2.42k
  if (depth_ast) {
5780
1.13k
    zval *depth_zv;
5781
1.13k
    if (depth_ast->kind != ZEND_AST_ZVAL) {
5782
19
      zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-integer operand "
5783
19
        "is no longer supported", ast->kind == ZEND_AST_BREAK ? "break" : "continue");
5784
19
    }
5785
5786
1.11k
    depth_zv = zend_ast_get_zval(depth_ast);
5787
1.11k
    if (Z_TYPE_P(depth_zv) != IS_LONG || Z_LVAL_P(depth_zv) < 1) {
5788
13
      zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive integers",
5789
13
        ast->kind == ZEND_AST_BREAK ? "break" : "continue");
5790
13
    }
5791
5792
1.10k
    depth = Z_LVAL_P(depth_zv);
5793
1.29k
  } else {
5794
1.29k
    depth = 1;
5795
1.29k
  }
5796
5797
2.39k
  if (CG(context).current_brk_cont == -1) {
5798
92
    zend_error_noreturn(E_COMPILE_ERROR, "'%s' not in the 'loop' or 'switch' context",
5799
92
      ast->kind == ZEND_AST_BREAK ? "break" : "continue");
5800
2.29k
  } else {
5801
2.29k
    if (!zend_handle_loops_and_finally_ex(depth, NULL)) {
5802
104
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot '%s' " ZEND_LONG_FMT " level%s",
5803
104
        ast->kind == ZEND_AST_BREAK ? "break" : "continue",
5804
104
        depth, depth == 1 ? "" : "s");
5805
104
    }
5806
2.29k
  }
5807
5808
2.19k
  if (ast->kind == ZEND_AST_CONTINUE) {
5809
1.08k
    int d, cur = CG(context).current_brk_cont;
5810
1.45k
    for (d = depth - 1; d > 0; d--) {
5811
369
      cur = CG(context).brk_cont_array[cur].parent;
5812
369
      ZEND_ASSERT(cur != -1);
5813
369
    }
5814
5815
1.08k
    if (CG(context).brk_cont_array[cur].is_switch) {
5816
501
      if (depth == 1) {
5817
222
        if (CG(context).brk_cont_array[cur].parent == -1) {
5818
81
          zend_error(E_WARNING,
5819
81
            "\"continue\" targeting switch is equivalent to \"break\"");
5820
141
        } else {
5821
141
          zend_error(E_WARNING,
5822
141
            "\"continue\" targeting switch is equivalent to \"break\". " \
5823
141
            "Did you mean to use \"continue " ZEND_LONG_FMT "\"?",
5824
141
            depth + 1);
5825
141
        }
5826
279
      } else {
5827
279
        if (CG(context).brk_cont_array[cur].parent == -1) {
5828
170
          zend_error(E_WARNING,
5829
170
            "\"continue " ZEND_LONG_FMT "\" targeting switch is equivalent to \"break " ZEND_LONG_FMT "\"",
5830
170
            depth, depth);
5831
170
        } else {
5832
109
          zend_error(E_WARNING,
5833
109
            "\"continue " ZEND_LONG_FMT "\" targeting switch is equivalent to \"break " ZEND_LONG_FMT "\". " \
5834
109
            "Did you mean to use \"continue " ZEND_LONG_FMT "\"?",
5835
109
            depth, depth, depth + 1);
5836
109
        }
5837
279
      }
5838
501
    }
5839
1.08k
  }
5840
5841
2.19k
  opline = zend_emit_op(NULL, ast->kind == ZEND_AST_BREAK ? ZEND_BRK : ZEND_CONT, NULL, NULL);
5842
2.19k
  opline->op1.num = CG(context).current_brk_cont;
5843
2.19k
  opline->op2.num = depth;
5844
2.19k
}
5845
/* }}} */
5846
5847
void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline) /* {{{ */
5848
1.12k
{
5849
1.12k
  zend_label *dest;
5850
1.12k
  int current, remove_oplines = opline->op1.num;
5851
1.12k
  zval *label;
5852
1.12k
  uint32_t opnum = opline - op_array->opcodes;
5853
5854
1.12k
  label = CT_CONSTANT_EX(op_array, opline->op2.constant);
5855
1.12k
  if (CG(context).labels == NULL ||
5856
1.12k
      (dest = zend_hash_find_ptr(CG(context).labels, Z_STR_P(label))) == NULL
5857
1.12k
  ) {
5858
66
    CG(in_compilation) = 1;
5859
66
    CG(active_op_array) = op_array;
5860
66
    CG(zend_lineno) = opline->lineno;
5861
66
    zend_error_noreturn(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL_P(label));
5862
66
  }
5863
5864
1.05k
  zval_ptr_dtor_str(label);
5865
1.05k
  ZVAL_NULL(label);
5866
5867
1.05k
  current = opline->extended_value;
5868
2.51k
  for (; current != dest->brk_cont; current = CG(context).brk_cont_array[current].parent) {
5869
1.47k
    if (current == -1) {
5870
11
      CG(in_compilation) = 1;
5871
11
      CG(active_op_array) = op_array;
5872
11
      CG(zend_lineno) = opline->lineno;
5873
11
      zend_error_noreturn(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
5874
11
    }
5875
1.45k
    if (CG(context).brk_cont_array[current].start >= 0) {
5876
828
      remove_oplines--;
5877
828
    }
5878
1.45k
  }
5879
5880
2.32k
  for (current = 0; current < op_array->last_try_catch; ++current) {
5881
1.42k
    zend_try_catch_element *elem = &op_array->try_catch_array[current];
5882
1.42k
    if (elem->try_op > opnum) {
5883
149
      break;
5884
149
    }
5885
1.28k
    if (elem->finally_op && opnum < elem->finally_op - 1
5886
1.28k
      && (dest->opline_num > elem->finally_end || dest->opline_num < elem->try_op)
5887
1.28k
    ) {
5888
401
      remove_oplines--;
5889
401
    }
5890
1.28k
  }
5891
5892
1.04k
  opline->opcode = ZEND_JMP;
5893
1.04k
  SET_UNUSED(opline->op1);
5894
1.04k
  SET_UNUSED(opline->op2);
5895
1.04k
  SET_UNUSED(opline->result);
5896
1.04k
  opline->op1.opline_num = dest->opline_num;
5897
1.04k
  opline->extended_value = 0;
5898
5899
1.04k
  ZEND_ASSERT(remove_oplines >= 0);
5900
1.46k
  while (remove_oplines--) {
5901
418
    opline--;
5902
418
    MAKE_NOP(opline);
5903
418
    ZEND_VM_SET_OPCODE_HANDLER(opline);
5904
418
  }
5905
1.04k
}
5906
/* }}} */
5907
5908
static void zend_compile_goto(zend_ast *ast) /* {{{ */
5909
1.24k
{
5910
1.24k
  zend_ast *label_ast = ast->child[0];
5911
1.24k
  znode label_node;
5912
1.24k
  zend_op *opline;
5913
5914
1.24k
  zend_compile_expr(&label_node, label_ast);
5915
5916
  /* Label resolution and unwinding adjustments happen in pass two. */
5917
1.24k
  uint32_t opnum_start = get_next_op_number();
5918
1.24k
  zend_handle_loops_and_finally(NULL);
5919
1.24k
  opline = zend_emit_op(NULL, ZEND_GOTO, NULL, &label_node);
5920
1.24k
  opline->op1.num = get_next_op_number() - opnum_start - 1;
5921
1.24k
  opline->extended_value = CG(context).current_brk_cont;
5922
1.24k
}
5923
/* }}} */
5924
5925
static void zend_compile_label(zend_ast *ast) /* {{{ */
5926
1.42k
{
5927
1.42k
  zend_string *label = zend_ast_get_str(ast->child[0]);
5928
1.42k
  zend_label dest;
5929
5930
1.42k
  if (!CG(context).labels) {
5931
935
    ALLOC_HASHTABLE(CG(context).labels);
5932
935
    zend_hash_init(CG(context).labels, 8, NULL, label_ptr_dtor, 0);
5933
935
  }
5934
5935
1.42k
  dest.brk_cont = CG(context).current_brk_cont;
5936
1.42k
  dest.opline_num = get_next_op_number();
5937
5938
1.42k
  if (!zend_hash_add_mem(CG(context).labels, label, &dest, sizeof(zend_label))) {
5939
61
    zend_error_noreturn(E_COMPILE_ERROR, "Label '%s' already defined", ZSTR_VAL(label));
5940
61
  }
5941
1.42k
}
5942
/* }}} */
5943
5944
static void zend_compile_while(zend_ast *ast) /* {{{ */
5945
1.55k
{
5946
1.55k
  zend_ast *cond_ast = ast->child[0];
5947
1.55k
  zend_ast *stmt_ast = ast->child[1];
5948
1.55k
  znode cond_node;
5949
1.55k
  uint32_t opnum_start, opnum_jmp, opnum_cond;
5950
5951
1.55k
  opnum_jmp = zend_emit_jump(0);
5952
5953
1.55k
  zend_begin_loop(ZEND_NOP, NULL, 0);
5954
5955
1.55k
  opnum_start = get_next_op_number();
5956
1.55k
  zend_compile_stmt(stmt_ast);
5957
5958
1.55k
  opnum_cond = get_next_op_number();
5959
1.55k
  zend_update_jump_target(opnum_jmp, opnum_cond);
5960
1.55k
  zend_compile_expr(&cond_node, cond_ast);
5961
5962
1.55k
  zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
5963
5964
1.55k
  zend_end_loop(opnum_cond, NULL);
5965
1.55k
}
5966
/* }}} */
5967
5968
static void zend_compile_do_while(zend_ast *ast) /* {{{ */
5969
545
{
5970
545
  zend_ast *stmt_ast = ast->child[0];
5971
545
  zend_ast *cond_ast = ast->child[1];
5972
5973
545
  znode cond_node;
5974
545
  uint32_t opnum_start, opnum_cond;
5975
5976
545
  zend_begin_loop(ZEND_NOP, NULL, 0);
5977
5978
545
  opnum_start = get_next_op_number();
5979
545
  zend_compile_stmt(stmt_ast);
5980
5981
545
  opnum_cond = get_next_op_number();
5982
545
  zend_compile_expr(&cond_node, cond_ast);
5983
5984
545
  zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
5985
5986
545
  zend_end_loop(opnum_cond, NULL);
5987
545
}
5988
/* }}} */
5989
5990
static void zend_compile_for_expr_list(znode *result, zend_ast *ast) /* {{{ */
5991
53.8k
{
5992
53.8k
  zend_ast_list *list;
5993
53.8k
  uint32_t i;
5994
5995
53.8k
  result->op_type = IS_CONST;
5996
53.8k
  ZVAL_TRUE(&result->u.constant);
5997
5998
53.8k
  if (!ast) {
5999
17.6k
    return;
6000
17.6k
  }
6001
6002
36.1k
  list = zend_ast_get_list(ast);
6003
75.3k
  for (i = 0; i < list->children; ++i) {
6004
39.2k
    zend_ast *expr_ast = list->child[i];
6005
6006
39.2k
    zend_do_free(result);
6007
39.2k
    if (expr_ast->kind == ZEND_AST_CAST_VOID) {
6008
151
      zend_compile_void_cast(NULL, expr_ast);
6009
151
      result->op_type = IS_CONST;
6010
151
      ZVAL_NULL(&result->u.constant);
6011
39.0k
    } else {
6012
39.0k
      zend_compile_expr(result, expr_ast);
6013
39.0k
    }
6014
39.2k
  }
6015
36.1k
}
6016
/* }}} */
6017
6018
static void zend_compile_for(zend_ast *ast) /* {{{ */
6019
17.9k
{
6020
17.9k
  zend_ast *init_ast = ast->child[0];
6021
17.9k
  zend_ast *cond_ast = ast->child[1];
6022
17.9k
  zend_ast *loop_ast = ast->child[2];
6023
17.9k
  zend_ast *stmt_ast = ast->child[3];
6024
6025
17.9k
  znode result;
6026
17.9k
  uint32_t opnum_start, opnum_jmp, opnum_loop;
6027
6028
17.9k
  zend_compile_for_expr_list(&result, init_ast);
6029
17.9k
  zend_do_free(&result);
6030
6031
17.9k
  opnum_jmp = zend_emit_jump(0);
6032
6033
17.9k
  zend_begin_loop(ZEND_NOP, NULL, 0);
6034
6035
17.9k
  opnum_start = get_next_op_number();
6036
17.9k
  zend_compile_stmt(stmt_ast);
6037
6038
17.9k
  opnum_loop = get_next_op_number();
6039
17.9k
  zend_compile_for_expr_list(&result, loop_ast);
6040
17.9k
  zend_do_free(&result);
6041
6042
17.9k
  zend_update_jump_target_to_next(opnum_jmp);
6043
17.9k
  zend_compile_for_expr_list(&result, cond_ast);
6044
17.9k
  zend_do_extended_stmt();
6045
6046
17.9k
  zend_emit_cond_jump(ZEND_JMPNZ, &result, opnum_start);
6047
6048
17.9k
  zend_end_loop(opnum_loop, NULL);
6049
17.9k
}
6050
/* }}} */
6051
6052
static void zend_compile_foreach(zend_ast *ast) /* {{{ */
6053
18.6k
{
6054
18.6k
  zend_ast *expr_ast = ast->child[0];
6055
18.6k
  zend_ast *value_ast = ast->child[1];
6056
18.6k
  zend_ast *key_ast = ast->child[2];
6057
18.6k
  zend_ast *stmt_ast = ast->child[3];
6058
18.6k
  bool by_ref = value_ast->kind == ZEND_AST_REF;
6059
18.6k
  bool is_variable = zend_is_variable(expr_ast) && zend_can_write_to_variable(expr_ast);
6060
6061
18.6k
  znode expr_node, reset_node, value_node, key_node;
6062
18.6k
  zend_op *opline;
6063
18.6k
  uint32_t opnum_reset, opnum_fetch;
6064
6065
18.6k
  if (key_ast) {
6066
1.31k
    if (key_ast->kind == ZEND_AST_REF) {
6067
13
      zend_error_noreturn(E_COMPILE_ERROR, "Key element cannot be a reference");
6068
13
    }
6069
1.30k
    if (key_ast->kind == ZEND_AST_ARRAY) {
6070
8
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use list as key element");
6071
8
    }
6072
1.30k
  }
6073
6074
18.6k
  if (by_ref) {
6075
1.19k
    value_ast = value_ast->child[0];
6076
1.19k
  }
6077
6078
18.6k
  if (value_ast->kind == ZEND_AST_ARRAY && zend_propagate_list_refs(value_ast)) {
6079
92
    by_ref = 1;
6080
92
  }
6081
6082
18.6k
  if (by_ref && is_variable) {
6083
837
    zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1);
6084
17.8k
  } else {
6085
17.8k
    zend_compile_expr(&expr_node, expr_ast);
6086
17.8k
  }
6087
6088
18.6k
  if (by_ref) {
6089
1.28k
    zend_separate_if_call_and_write(&expr_node, expr_ast, BP_VAR_W);
6090
1.28k
  }
6091
6092
18.6k
  opnum_reset = get_next_op_number();
6093
18.6k
  opline = zend_emit_op(&reset_node, by_ref ? ZEND_FE_RESET_RW : ZEND_FE_RESET_R, &expr_node, NULL);
6094
6095
18.6k
  zend_begin_loop(ZEND_FE_FREE, &reset_node, 0);
6096
6097
18.6k
  opnum_fetch = get_next_op_number();
6098
18.6k
  opline = zend_emit_op(NULL, by_ref ? ZEND_FE_FETCH_RW : ZEND_FE_FETCH_R, &reset_node, NULL);
6099
6100
18.6k
  if (is_this_fetch(value_ast)) {
6101
8
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
6102
18.6k
  } else if (value_ast->kind == ZEND_AST_VAR &&
6103
18.6k
    zend_try_compile_cv(&value_node, value_ast) == SUCCESS) {
6104
17.7k
    SET_NODE(opline->op2, &value_node);
6105
17.7k
  } else {
6106
860
    opline->op2_type = IS_VAR;
6107
860
    opline->op2.var = get_temporary_variable();
6108
860
    GET_NODE(&value_node, opline->op2);
6109
860
    if (value_ast->kind == ZEND_AST_ARRAY) {
6110
349
      zend_compile_list_assign(NULL, value_ast, &value_node, value_ast->attr);
6111
511
    } else if (by_ref) {
6112
173
      zend_emit_assign_ref_znode(value_ast, &value_node);
6113
338
    } else {
6114
338
      zend_emit_assign_znode(value_ast, &value_node);
6115
338
    }
6116
860
  }
6117
6118
18.6k
  if (key_ast) {
6119
1.28k
    opline = &CG(active_op_array)->opcodes[opnum_fetch];
6120
1.28k
    zend_make_tmp_result(&key_node, opline);
6121
1.28k
    zend_emit_assign_znode(key_ast, &key_node);
6122
1.28k
  }
6123
6124
18.6k
  zend_compile_stmt(stmt_ast);
6125
6126
  /* Place JMP and FE_FREE on the line where foreach starts. It would be
6127
   * better to use the end line, but this information is not available
6128
   * currently. */
6129
18.6k
  CG(zend_lineno) = ast->lineno;
6130
18.6k
  zend_emit_jump(opnum_fetch);
6131
6132
18.6k
  opline = &CG(active_op_array)->opcodes[opnum_reset];
6133
18.6k
  opline->op2.opline_num = get_next_op_number();
6134
6135
18.6k
  opline = &CG(active_op_array)->opcodes[opnum_fetch];
6136
18.6k
  opline->extended_value = get_next_op_number();
6137
6138
18.6k
  zend_end_loop(opnum_fetch, &reset_node);
6139
6140
18.6k
  opline = zend_emit_op(NULL, ZEND_FE_FREE, &reset_node, NULL);
6141
18.6k
}
6142
/* }}} */
6143
6144
static void zend_compile_if(zend_ast *ast) /* {{{ */
6145
19.1k
{
6146
19.1k
  zend_ast_list *list = zend_ast_get_list(ast);
6147
19.1k
  uint32_t i;
6148
19.1k
  uint32_t *jmp_opnums = NULL;
6149
6150
19.1k
  if (list->children > 1) {
6151
2.03k
    jmp_opnums = safe_emalloc(sizeof(uint32_t), list->children - 1, 0);
6152
2.03k
  }
6153
6154
41.2k
  for (i = 0; i < list->children; ++i) {
6155
22.0k
    zend_ast *elem_ast = list->child[i];
6156
22.0k
    zend_ast *cond_ast = elem_ast->child[0];
6157
22.0k
    zend_ast *stmt_ast = elem_ast->child[1];
6158
6159
22.0k
    if (cond_ast) {
6160
20.2k
      znode cond_node;
6161
20.2k
      uint32_t opnum_jmpz;
6162
6163
20.2k
      if (i > 0) {
6164
1.04k
        CG(zend_lineno) = cond_ast->lineno;
6165
1.04k
        zend_do_extended_stmt();
6166
1.04k
      }
6167
6168
20.2k
      zend_compile_expr(&cond_node, cond_ast);
6169
20.2k
      opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
6170
6171
20.2k
      zend_compile_stmt(stmt_ast);
6172
6173
20.2k
      if (i != list->children - 1) {
6174
        /* Set the lineno of JMP to the position of the if keyword, as we don't want to
6175
         * report the last line in the if branch as covered if it hasn't actually executed. */
6176
2.89k
        CG(zend_lineno) = elem_ast->lineno;
6177
2.89k
        jmp_opnums[i] = zend_emit_jump(0);
6178
2.89k
      }
6179
20.2k
      zend_update_jump_target_to_next(opnum_jmpz);
6180
20.2k
    } else {
6181
      /* "else" can only occur as last element. */
6182
1.84k
      ZEND_ASSERT(i == list->children - 1);
6183
1.84k
      zend_compile_stmt(stmt_ast);
6184
1.84k
    }
6185
22.0k
  }
6186
6187
19.1k
  if (list->children > 1) {
6188
4.92k
    for (i = 0; i < list->children - 1; ++i) {
6189
2.89k
      zend_update_jump_target_to_next(jmp_opnums[i]);
6190
2.89k
    }
6191
2.03k
    efree(jmp_opnums);
6192
2.03k
  }
6193
19.1k
}
6194
/* }}} */
6195
6196
2.17k
static uint8_t determine_switch_jumptable_type(zend_ast_list *cases) {
6197
2.17k
  uint32_t i;
6198
2.17k
  uint8_t common_type = IS_UNDEF;
6199
5.39k
  for (i = 0; i < cases->children; i++) {
6200
3.92k
    zend_ast *case_ast = cases->child[i];
6201
3.92k
    zend_ast **cond_ast = &case_ast->child[0];
6202
3.92k
    zval *cond_zv;
6203
3.92k
    if (!case_ast->child[0]) {
6204
      /* Skip default clause */
6205
480
      continue;
6206
480
    }
6207
6208
3.44k
    zend_eval_const_expr(cond_ast);
6209
3.44k
    if ((*cond_ast)->kind != ZEND_AST_ZVAL) {
6210
      /* Non-constant case */
6211
273
      return IS_UNDEF;
6212
273
    }
6213
6214
3.16k
    cond_zv = zend_ast_get_zval(case_ast->child[0]);
6215
3.16k
    if (Z_TYPE_P(cond_zv) != IS_LONG && Z_TYPE_P(cond_zv) != IS_STRING) {
6216
      /* We only optimize switched on integers and strings */
6217
164
      return IS_UNDEF;
6218
164
    }
6219
6220
3.00k
    if (common_type == IS_UNDEF) {
6221
1.43k
      common_type = Z_TYPE_P(cond_zv);
6222
1.56k
    } else if (common_type != Z_TYPE_P(cond_zv)) {
6223
      /* Non-uniform case types */
6224
70
      return IS_UNDEF;
6225
70
    }
6226
6227
2.93k
    if (Z_TYPE_P(cond_zv) == IS_STRING
6228
2.93k
        && is_numeric_string(Z_STRVAL_P(cond_zv), Z_STRLEN_P(cond_zv), NULL, NULL, 0)) {
6229
      /* Numeric strings cannot be compared with a simple hash lookup */
6230
193
      return IS_UNDEF;
6231
193
    }
6232
2.93k
  }
6233
6234
1.47k
  return common_type;
6235
2.17k
}
6236
6237
1.08k
static bool should_use_jumptable(zend_ast_list *cases, uint8_t jumptable_type) {
6238
1.08k
  if (CG(compiler_options) & ZEND_COMPILE_NO_JUMPTABLES) {
6239
0
    return 0;
6240
0
  }
6241
6242
  /* Thresholds are chosen based on when the average switch time for equidistributed
6243
   * input becomes smaller when using the jumptable optimization. */
6244
1.08k
  if (jumptable_type == IS_LONG) {
6245
262
    return cases->children >= 5;
6246
827
  } else {
6247
827
    ZEND_ASSERT(jumptable_type == IS_STRING);
6248
827
    return cases->children >= 2;
6249
827
  }
6250
1.08k
}
6251
6252
static void zend_compile_switch(zend_ast *ast) /* {{{ */
6253
2.17k
{
6254
2.17k
  zend_ast *expr_ast = ast->child[0];
6255
2.17k
  zend_ast_list *cases = zend_ast_get_list(ast->child[1]);
6256
6257
2.17k
  uint32_t i;
6258
2.17k
  bool has_default_case = 0;
6259
6260
2.17k
  znode expr_node, case_node;
6261
2.17k
  zend_op *opline;
6262
2.17k
  uint32_t *jmpnz_opnums, opnum_default_jmp, opnum_switch = (uint32_t)-1;
6263
2.17k
  uint8_t jumptable_type;
6264
2.17k
  HashTable *jumptable = NULL;
6265
6266
2.17k
  zend_compile_expr(&expr_node, expr_ast);
6267
6268
2.17k
  zend_begin_loop(ZEND_FREE, &expr_node, 1);
6269
6270
2.17k
  case_node.op_type = IS_TMP_VAR;
6271
2.17k
  case_node.u.op.var = get_temporary_variable();
6272
6273
2.17k
  jumptable_type = determine_switch_jumptable_type(cases);
6274
2.17k
  if (jumptable_type != IS_UNDEF && should_use_jumptable(cases, jumptable_type)) {
6275
725
    znode jumptable_op;
6276
6277
725
    ALLOC_HASHTABLE(jumptable);
6278
725
    zend_hash_init(jumptable, cases->children, NULL, NULL, 0);
6279
725
    jumptable_op.op_type = IS_CONST;
6280
725
    ZVAL_ARR(&jumptable_op.u.constant, jumptable);
6281
6282
725
    opline = zend_emit_op(NULL,
6283
725
      jumptable_type == IS_LONG ? ZEND_SWITCH_LONG : ZEND_SWITCH_STRING,
6284
725
      &expr_node, &jumptable_op);
6285
725
    if (opline->op1_type == IS_CONST) {
6286
469
      Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
6287
469
    }
6288
725
    opnum_switch = opline - CG(active_op_array)->opcodes;
6289
725
  }
6290
6291
2.17k
  jmpnz_opnums = safe_emalloc(sizeof(uint32_t), cases->children, 0);
6292
8.81k
  for (i = 0; i < cases->children; ++i) {
6293
6.65k
    zend_ast *case_ast = cases->child[i];
6294
6.65k
    zend_ast *cond_ast = case_ast->child[0];
6295
6.65k
    znode cond_node;
6296
6297
6.65k
    if (!cond_ast) {
6298
304
      if (has_default_case) {
6299
21
        CG(zend_lineno) = case_ast->lineno;
6300
21
        zend_error_noreturn(E_COMPILE_ERROR,
6301
21
          "Switch statements may only contain one default clause");
6302
21
      }
6303
283
      has_default_case = 1;
6304
283
      continue;
6305
304
    }
6306
6307
6.35k
    zend_compile_expr(&cond_node, cond_ast);
6308
6309
6.35k
    if (expr_node.op_type == IS_CONST
6310
6.35k
      && Z_TYPE(expr_node.u.constant) == IS_FALSE) {
6311
1.78k
      jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
6312
4.56k
    } else if (expr_node.op_type == IS_CONST
6313
4.56k
      && Z_TYPE(expr_node.u.constant) == IS_TRUE) {
6314
1.56k
      jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, 0);
6315
3.00k
    } else {
6316
3.00k
      opline = zend_emit_op(NULL,
6317
3.00k
        (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) ? ZEND_CASE : ZEND_IS_EQUAL,
6318
3.00k
        &expr_node, &cond_node);
6319
3.00k
      SET_NODE(opline->result, &case_node);
6320
3.00k
      if (opline->op1_type == IS_CONST) {
6321
863
        Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
6322
863
      }
6323
6324
3.00k
      jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0);
6325
3.00k
    }
6326
6.35k
  }
6327
6328
2.15k
  opnum_default_jmp = zend_emit_jump(0);
6329
6330
7.48k
  for (i = 0; i < cases->children; ++i) {
6331
5.32k
    zend_ast *case_ast = cases->child[i];
6332
5.32k
    zend_ast *cond_ast = case_ast->child[0];
6333
5.32k
    zend_ast *stmt_ast = case_ast->child[1];
6334
6335
5.32k
    if (cond_ast) {
6336
5.06k
      zend_update_jump_target_to_next(jmpnz_opnums[i]);
6337
6338
5.06k
      if (jumptable) {
6339
2.00k
        zval *cond_zv = zend_ast_get_zval(cond_ast);
6340
2.00k
        zval jmp_target;
6341
2.00k
        ZVAL_LONG(&jmp_target, get_next_op_number());
6342
6343
2.00k
        ZEND_ASSERT(Z_TYPE_P(cond_zv) == jumptable_type);
6344
2.00k
        if (Z_TYPE_P(cond_zv) == IS_LONG) {
6345
329
          zend_hash_index_add(jumptable, Z_LVAL_P(cond_zv), &jmp_target);
6346
1.67k
        } else {
6347
1.67k
          ZEND_ASSERT(Z_TYPE_P(cond_zv) == IS_STRING);
6348
1.67k
          zend_hash_add(jumptable, Z_STR_P(cond_zv), &jmp_target);
6349
1.67k
        }
6350
2.00k
      }
6351
5.06k
    } else {
6352
262
      zend_update_jump_target_to_next(opnum_default_jmp);
6353
6354
262
      if (jumptable) {
6355
96
        ZEND_ASSERT(opnum_switch != (uint32_t)-1);
6356
96
        opline = &CG(active_op_array)->opcodes[opnum_switch];
6357
96
        opline->extended_value = get_next_op_number();
6358
96
      }
6359
262
    }
6360
6361
5.32k
    zend_compile_stmt(stmt_ast);
6362
5.32k
  }
6363
6364
2.15k
  if (!has_default_case) {
6365
1.86k
    zend_update_jump_target_to_next(opnum_default_jmp);
6366
6367
1.86k
    if (jumptable) {
6368
614
      opline = &CG(active_op_array)->opcodes[opnum_switch];
6369
614
      opline->extended_value = get_next_op_number();
6370
614
    }
6371
1.86k
  }
6372
6373
2.15k
  zend_end_loop(get_next_op_number(), &expr_node);
6374
6375
2.15k
  if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) {
6376
621
    opline = zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
6377
621
    opline->extended_value = ZEND_FREE_SWITCH;
6378
1.53k
  } else if (expr_node.op_type == IS_CONST) {
6379
1.16k
    zval_ptr_dtor_nogc(&expr_node.u.constant);
6380
1.16k
  }
6381
6382
2.15k
  efree(jmpnz_opnums);
6383
2.15k
}
6384
/* }}} */
6385
6386
static uint32_t count_match_conds(zend_ast_list *arms)
6387
2.52k
{
6388
2.52k
  uint32_t num_conds = 0;
6389
6390
7.28k
  for (uint32_t i = 0; i < arms->children; i++) {
6391
4.76k
    zend_ast *arm_ast = arms->child[i];
6392
4.76k
    if (arm_ast->child[0] == NULL) {
6393
929
      continue;
6394
929
    }
6395
6396
3.83k
    zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
6397
3.83k
    num_conds += conds->children;
6398
3.83k
  }
6399
6400
2.52k
  return num_conds;
6401
2.52k
}
6402
6403
2.52k
static bool can_match_use_jumptable(zend_ast_list *arms) {
6404
5.43k
  for (uint32_t i = 0; i < arms->children; i++) {
6405
4.06k
    zend_ast *arm_ast = arms->child[i];
6406
4.06k
    if (!arm_ast->child[0]) {
6407
      /* Skip default arm */
6408
861
      continue;
6409
861
    }
6410
6411
3.20k
    zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
6412
6.86k
    for (uint32_t j = 0; j < conds->children; j++) {
6413
4.81k
      zend_ast **cond_ast = &conds->child[j];
6414
6415
4.81k
      zend_eval_const_expr(cond_ast);
6416
4.81k
      if ((*cond_ast)->kind != ZEND_AST_ZVAL) {
6417
945
        return 0;
6418
945
      }
6419
6420
3.86k
      zval *cond_zv = zend_ast_get_zval(*cond_ast);
6421
3.86k
      if (Z_TYPE_P(cond_zv) != IS_LONG && Z_TYPE_P(cond_zv) != IS_STRING) {
6422
209
        return 0;
6423
209
      }
6424
3.86k
    }
6425
3.20k
  }
6426
6427
1.36k
  return 1;
6428
2.52k
}
6429
6430
static void zend_compile_pipe(znode *result, zend_ast *ast)
6431
364
{
6432
364
  zend_ast *operand_ast = ast->child[0];
6433
364
  zend_ast *callable_ast = ast->child[1];
6434
6435
  /* Compile the left hand side down to a value first. */
6436
364
  znode operand_result;
6437
364
  zend_compile_expr(&operand_result, operand_ast);
6438
6439
  /* Wrap simple values in a ZEND_QM_ASSIGN opcode to ensure references
6440
   * always fail. They will already fail in complex cases like arrays,
6441
   * so those don't need a wrapper. */
6442
364
  znode wrapped_operand_result;
6443
364
  if (operand_result.op_type & (IS_CV|IS_VAR)) {
6444
239
    zend_emit_op_tmp(&wrapped_operand_result, ZEND_QM_ASSIGN, &operand_result, NULL);
6445
239
  } else {
6446
125
    wrapped_operand_result = operand_result;
6447
125
  }
6448
6449
  /* Turn the operand into a function parameter list. */
6450
364
  zend_ast *arg_list_ast = zend_ast_create_list(1, ZEND_AST_ARG_LIST, zend_ast_create_znode(&wrapped_operand_result));
6451
6452
364
  zend_ast *fcall_ast;
6453
364
  znode callable_result;
6454
6455
  /* Turn $foo |> bar(...) into bar($foo). */
6456
364
  if (callable_ast->kind == ZEND_AST_CALL
6457
364
    && callable_ast->child[1]->kind == ZEND_AST_CALLABLE_CONVERT) {
6458
77
    fcall_ast = zend_ast_create(ZEND_AST_CALL,
6459
77
        callable_ast->child[0], arg_list_ast);
6460
  /* Turn $foo |> bar::baz(...) into bar::baz($foo). */
6461
287
  } else if (callable_ast->kind == ZEND_AST_STATIC_CALL
6462
287
      && callable_ast->child[2]->kind == ZEND_AST_CALLABLE_CONVERT) {
6463
9
    fcall_ast = zend_ast_create(ZEND_AST_STATIC_CALL,
6464
9
      callable_ast->child[0], callable_ast->child[1], arg_list_ast);
6465
  /* Turn $foo |> $bar->baz(...) into $bar->baz($foo). */
6466
278
  } else if (callable_ast->kind == ZEND_AST_METHOD_CALL
6467
278
      && callable_ast->child[2]->kind == ZEND_AST_CALLABLE_CONVERT) {
6468
9
    fcall_ast = zend_ast_create(ZEND_AST_METHOD_CALL,
6469
9
      callable_ast->child[0], callable_ast->child[1], arg_list_ast);
6470
  /* Turn $foo |> $expr into ($expr)($foo) */
6471
269
  } else {
6472
269
    zend_compile_expr(&callable_result, callable_ast);
6473
269
    callable_ast = zend_ast_create_znode(&callable_result);
6474
269
    fcall_ast = zend_ast_create(ZEND_AST_CALL,
6475
269
      callable_ast, arg_list_ast);
6476
269
  }
6477
6478
364
  zend_compile_expr(result, fcall_ast);
6479
364
}
6480
6481
static void zend_compile_match(znode *result, zend_ast *ast)
6482
2.52k
{
6483
2.52k
  zend_ast *expr_ast = ast->child[0];
6484
2.52k
  zend_ast_list *arms = zend_ast_get_list(ast->child[1]);
6485
2.52k
  bool has_default_arm = 0;
6486
2.52k
  uint32_t opnum_match = (uint32_t)-1;
6487
6488
2.52k
  znode expr_node;
6489
2.52k
  zend_compile_expr(&expr_node, expr_ast);
6490
6491
2.52k
  znode case_node;
6492
2.52k
  case_node.op_type = IS_TMP_VAR;
6493
2.52k
  case_node.u.op.var = get_temporary_variable();
6494
6495
2.52k
  uint32_t num_conds = count_match_conds(arms);
6496
2.52k
  uint8_t can_use_jumptable = can_match_use_jumptable(arms);
6497
2.52k
  bool uses_jumptable = can_use_jumptable && num_conds >= 2;
6498
2.52k
  HashTable *jumptable = NULL;
6499
2.52k
  uint32_t *jmpnz_opnums = NULL;
6500
6501
7.27k
  for (uint32_t i = 0; i < arms->children; ++i) {
6502
4.76k
    zend_ast *arm_ast = arms->child[i];
6503
6504
4.76k
    if (!arm_ast->child[0]) {
6505
927
      if (has_default_arm) {
6506
7
        CG(zend_lineno) = arm_ast->lineno;
6507
7
        zend_error_noreturn(E_COMPILE_ERROR,
6508
7
          "Match expressions may only contain one default arm");
6509
7
      }
6510
920
      has_default_arm = 1;
6511
920
    }
6512
4.76k
  }
6513
6514
2.51k
  if (uses_jumptable) {
6515
772
    znode jumptable_op;
6516
6517
772
    ALLOC_HASHTABLE(jumptable);
6518
772
    zend_hash_init(jumptable, num_conds, NULL, NULL, 0);
6519
772
    jumptable_op.op_type = IS_CONST;
6520
772
    ZVAL_ARR(&jumptable_op.u.constant, jumptable);
6521
6522
772
    zend_op *opline = zend_emit_op(NULL, ZEND_MATCH, &expr_node, &jumptable_op);
6523
772
    if (opline->op1_type == IS_CONST) {
6524
105
      Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
6525
105
    }
6526
772
    opnum_match = opline - CG(active_op_array)->opcodes;
6527
1.74k
  } else {
6528
1.74k
    jmpnz_opnums = safe_emalloc(sizeof(uint32_t), num_conds, 0);
6529
1.74k
    uint32_t cond_count = 0;
6530
4.44k
    for (uint32_t i = 0; i < arms->children; ++i) {
6531
2.69k
      zend_ast *arm_ast = arms->child[i];
6532
6533
2.69k
      if (!arm_ast->child[0]) {
6534
424
        continue;
6535
424
      }
6536
6537
2.27k
      zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
6538
5.76k
      for (uint32_t j = 0; j < conds->children; j++) {
6539
3.48k
        zend_ast *cond_ast = conds->child[j];
6540
6541
3.48k
        znode cond_node;
6542
3.48k
        zend_compile_expr(&cond_node, cond_ast);
6543
6544
3.48k
        uint32_t opcode = (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) ? ZEND_CASE_STRICT : ZEND_IS_IDENTICAL;
6545
3.48k
        zend_op *opline = zend_emit_op(NULL, opcode, &expr_node, &cond_node);
6546
3.48k
        SET_NODE(opline->result, &case_node);
6547
3.48k
        if (opline->op1_type == IS_CONST) {
6548
844
          Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
6549
844
        }
6550
6551
3.48k
        jmpnz_opnums[cond_count] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0);
6552
6553
3.48k
        cond_count++;
6554
3.48k
      }
6555
2.27k
    }
6556
1.74k
  }
6557
6558
2.51k
  uint32_t opnum_default_jmp = 0;
6559
2.51k
  if (!uses_jumptable) {
6560
1.74k
    opnum_default_jmp = zend_emit_jump(0);
6561
1.74k
  }
6562
6563
2.51k
  bool is_first_case = 1;
6564
2.51k
  uint32_t cond_count = 0;
6565
2.51k
  uint32_t *jmp_end_opnums = safe_emalloc(sizeof(uint32_t), arms->children, 0);
6566
6567
  // The generated default arm is emitted first to avoid live range issues where the tmpvar
6568
  // for the arm result is freed even though it has not been initialized yet.
6569
2.51k
  if (!has_default_arm) {
6570
1.60k
    if (!uses_jumptable) {
6571
1.31k
      zend_update_jump_target_to_next(opnum_default_jmp);
6572
1.31k
    }
6573
6574
1.60k
    if (jumptable) {
6575
283
      zend_op *opline = &CG(active_op_array)->opcodes[opnum_match];
6576
283
      opline->extended_value = get_next_op_number();
6577
283
    }
6578
6579
1.60k
    zend_op *opline = zend_emit_op(NULL, ZEND_MATCH_ERROR, &expr_node, NULL);
6580
1.60k
    if (opline->op1_type == IS_CONST) {
6581
348
      Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
6582
348
    }
6583
1.60k
    if (arms->children == 0) {
6584
      /* Mark this as an "expression throw" for opcache. */
6585
140
      opline->extended_value = ZEND_THROW_IS_EXPR;
6586
140
    }
6587
1.60k
  }
6588
6589
7.25k
  for (uint32_t i = 0; i < arms->children; ++i) {
6590
4.73k
    zend_ast *arm_ast = arms->child[i];
6591
4.73k
    zend_ast *body_ast = arm_ast->child[1];
6592
6593
4.73k
    if (arm_ast->child[0] != NULL) {
6594
3.82k
      zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
6595
6596
10.2k
      for (uint32_t j = 0; j < conds->children; j++) {
6597
6.38k
        zend_ast *cond_ast = conds->child[j];
6598
6599
6.38k
        if (jmpnz_opnums != NULL) {
6600
3.48k
          zend_update_jump_target_to_next(jmpnz_opnums[cond_count]);
6601
3.48k
        }
6602
6603
6.38k
        if (jumptable) {
6604
2.89k
          zval *cond_zv = zend_ast_get_zval(cond_ast);
6605
2.89k
          zval jmp_target;
6606
2.89k
          ZVAL_LONG(&jmp_target, get_next_op_number());
6607
6608
2.89k
          if (Z_TYPE_P(cond_zv) == IS_LONG) {
6609
2.45k
            zend_hash_index_add(jumptable, Z_LVAL_P(cond_zv), &jmp_target);
6610
2.45k
          } else {
6611
443
            ZEND_ASSERT(Z_TYPE_P(cond_zv) == IS_STRING);
6612
443
            zend_hash_add(jumptable, Z_STR_P(cond_zv), &jmp_target);
6613
443
          }
6614
2.89k
        }
6615
6616
6.38k
        cond_count++;
6617
6.38k
      }
6618
3.82k
    } else {
6619
913
      if (!uses_jumptable) {
6620
424
        zend_update_jump_target_to_next(opnum_default_jmp);
6621
424
      }
6622
6623
913
      if (jumptable) {
6624
489
        ZEND_ASSERT(opnum_match != (uint32_t)-1);
6625
489
        zend_op *opline = &CG(active_op_array)->opcodes[opnum_match];
6626
489
        opline->extended_value = get_next_op_number();
6627
489
      }
6628
913
    }
6629
6630
4.73k
    znode body_node;
6631
4.73k
    zend_compile_expr(&body_node, body_ast);
6632
6633
4.73k
    if (is_first_case) {
6634
2.37k
      zend_emit_op_tmp(result, ZEND_QM_ASSIGN, &body_node, NULL);
6635
2.37k
      is_first_case = 0;
6636
2.37k
    } else {
6637
2.36k
      zend_op *opline_qm_assign = zend_emit_op(NULL, ZEND_QM_ASSIGN, &body_node, NULL);
6638
2.36k
      SET_NODE(opline_qm_assign->result, result);
6639
2.36k
    }
6640
6641
4.73k
    jmp_end_opnums[i] = zend_emit_jump(0);
6642
4.73k
  }
6643
6644
  // Initialize result in case there is no arm
6645
2.51k
  if (arms->children == 0) {
6646
140
    result->op_type = IS_CONST;
6647
140
    ZVAL_NULL(&result->u.constant);
6648
140
  }
6649
6650
7.25k
  for (uint32_t i = 0; i < arms->children; ++i) {
6651
4.73k
    zend_update_jump_target_to_next(jmp_end_opnums[i]);
6652
4.73k
  }
6653
6654
2.51k
  if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) {
6655
1.17k
    zend_op *opline = zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
6656
1.17k
    opline->extended_value = ZEND_FREE_SWITCH;
6657
1.33k
  } else if (expr_node.op_type == IS_CONST) {
6658
520
    zval_ptr_dtor_nogc(&expr_node.u.constant);
6659
520
  }
6660
6661
2.51k
  if (jmpnz_opnums != NULL) {
6662
1.74k
    efree(jmpnz_opnums);
6663
1.74k
  }
6664
2.51k
  efree(jmp_end_opnums);
6665
2.51k
}
6666
6667
static void zend_compile_try(zend_ast *ast) /* {{{ */
6668
44.9k
{
6669
44.9k
  zend_ast *try_ast = ast->child[0];
6670
44.9k
  zend_ast_list *catches = zend_ast_get_list(ast->child[1]);
6671
44.9k
  zend_ast *finally_ast = ast->child[2];
6672
6673
44.9k
  uint32_t i, j;
6674
44.9k
  zend_op *opline;
6675
44.9k
  uint32_t try_catch_offset;
6676
44.9k
  uint32_t *jmp_opnums = safe_emalloc(sizeof(uint32_t), catches->children, 0);
6677
44.9k
  uint32_t orig_fast_call_var = CG(context).fast_call_var;
6678
44.9k
  uint32_t orig_try_catch_offset = CG(context).try_catch_offset;
6679
6680
44.9k
  if (catches->children == 0 && !finally_ast) {
6681
65
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally");
6682
65
  }
6683
6684
  /* label: try { } must not be equal to try { label: } */
6685
44.8k
  if (CG(context).labels) {
6686
329
    zend_label *label;
6687
329
    ZEND_HASH_MAP_REVERSE_FOREACH_PTR(CG(context).labels, label) {
6688
329
      if (label->opline_num == get_next_op_number()) {
6689
86
        zend_emit_op(NULL, ZEND_NOP, NULL, NULL);
6690
86
      }
6691
329
      break;
6692
987
    } ZEND_HASH_FOREACH_END();
6693
329
  }
6694
6695
44.8k
  try_catch_offset = zend_add_try_element(get_next_op_number());
6696
6697
44.8k
  if (finally_ast) {
6698
2.34k
    zend_loop_var fast_call;
6699
2.34k
    if (!(CG(active_op_array)->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) {
6700
789
      CG(active_op_array)->fn_flags |= ZEND_ACC_HAS_FINALLY_BLOCK;
6701
789
    }
6702
2.34k
    CG(context).fast_call_var = get_temporary_variable();
6703
6704
    /* Push FAST_CALL on unwind stack */
6705
2.34k
    fast_call.opcode = ZEND_FAST_CALL;
6706
2.34k
    fast_call.var_type = IS_TMP_VAR;
6707
2.34k
    fast_call.var_num = CG(context).fast_call_var;
6708
2.34k
    fast_call.try_catch_offset = try_catch_offset;
6709
2.34k
    zend_stack_push(&CG(loop_var_stack), &fast_call);
6710
2.34k
  }
6711
6712
44.8k
  CG(context).try_catch_offset = try_catch_offset;
6713
6714
44.8k
  zend_compile_stmt(try_ast);
6715
6716
44.8k
  if (catches->children != 0) {
6717
42.6k
    jmp_opnums[0] = zend_emit_jump(0);
6718
42.6k
  }
6719
6720
93.7k
  for (i = 0; i < catches->children; ++i) {
6721
48.9k
    zend_ast *catch_ast = catches->child[i];
6722
48.9k
    zend_ast_list *classes = zend_ast_get_list(catch_ast->child[0]);
6723
48.9k
    zend_ast *var_ast = catch_ast->child[1];
6724
48.9k
    zend_ast *stmt_ast = catch_ast->child[2];
6725
48.9k
    zend_string *var_name = var_ast ? zval_make_interned_string(zend_ast_get_zval(var_ast)) : NULL;
6726
48.9k
    bool is_last_catch = (i + 1 == catches->children);
6727
6728
48.9k
    uint32_t *jmp_multicatch = safe_emalloc(sizeof(uint32_t), classes->children - 1, 0);
6729
48.9k
    uint32_t opnum_catch = (uint32_t)-1;
6730
6731
48.9k
    CG(zend_lineno) = catch_ast->lineno;
6732
6733
101k
    for (j = 0; j < classes->children; j++) {
6734
52.6k
      zend_ast *class_ast = classes->child[j];
6735
52.6k
      bool is_last_class = (j + 1 == classes->children);
6736
6737
52.6k
      if (!zend_is_const_default_class_ref(class_ast)) {
6738
6
        zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement");
6739
6
      }
6740
6741
52.6k
      opnum_catch = get_next_op_number();
6742
52.6k
      if (i == 0 && j == 0) {
6743
42.6k
        CG(active_op_array)->try_catch_array[try_catch_offset].catch_op = opnum_catch;
6744
42.6k
      }
6745
6746
52.6k
      opline = get_next_op();
6747
52.6k
      opline->opcode = ZEND_CATCH;
6748
52.6k
      opline->op1_type = IS_CONST;
6749
52.6k
      opline->op1.constant = zend_add_class_name_literal(
6750
52.6k
          zend_resolve_class_name_ast(class_ast));
6751
52.6k
      opline->extended_value = zend_alloc_cache_slot();
6752
6753
52.6k
      if (var_name && zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) {
6754
6
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
6755
6
      }
6756
6757
52.6k
      opline->result_type = var_name ? IS_CV : IS_UNUSED;
6758
52.6k
      opline->result.var = var_name ? lookup_cv(var_name) : -1;
6759
6760
52.6k
      if (is_last_catch && is_last_class) {
6761
42.6k
        opline->extended_value |= ZEND_LAST_CATCH;
6762
42.6k
      }
6763
6764
52.6k
      if (!is_last_class) {
6765
3.75k
        jmp_multicatch[j] = zend_emit_jump(0);
6766
3.75k
        opline = &CG(active_op_array)->opcodes[opnum_catch];
6767
3.75k
        opline->op2.opline_num = get_next_op_number();
6768
3.75k
      }
6769
52.6k
    }
6770
6771
52.6k
    for (j = 0; j < classes->children - 1; j++) {
6772
3.75k
      zend_update_jump_target_to_next(jmp_multicatch[j]);
6773
3.75k
    }
6774
6775
48.9k
    efree(jmp_multicatch);
6776
6777
48.9k
    zend_compile_stmt(stmt_ast);
6778
6779
48.9k
    if (!is_last_catch) {
6780
6.29k
      jmp_opnums[i + 1] = zend_emit_jump(0);
6781
6.29k
    }
6782
6783
48.9k
    ZEND_ASSERT(opnum_catch != (uint32_t)-1 && "Should have at least one class");
6784
48.9k
    opline = &CG(active_op_array)->opcodes[opnum_catch];
6785
48.9k
    if (!is_last_catch) {
6786
6.29k
      opline->op2.opline_num = get_next_op_number();
6787
6.29k
    }
6788
48.9k
  }
6789
6790
93.7k
  for (i = 0; i < catches->children; ++i) {
6791
48.9k
    zend_update_jump_target_to_next(jmp_opnums[i]);
6792
48.9k
  }
6793
6794
44.8k
  if (finally_ast) {
6795
2.32k
    zend_loop_var discard_exception;
6796
2.32k
    uint32_t opnum_jmp = get_next_op_number() + 1;
6797
6798
    /* Pop FAST_CALL from unwind stack */
6799
2.32k
    zend_stack_del_top(&CG(loop_var_stack));
6800
6801
    /* Push DISCARD_EXCEPTION on unwind stack */
6802
2.32k
    discard_exception.opcode = ZEND_DISCARD_EXCEPTION;
6803
2.32k
    discard_exception.var_type = IS_TMP_VAR;
6804
2.32k
    discard_exception.var_num = CG(context).fast_call_var;
6805
2.32k
    zend_stack_push(&CG(loop_var_stack), &discard_exception);
6806
6807
2.32k
    CG(zend_lineno) = finally_ast->lineno;
6808
6809
2.32k
    opline = zend_emit_op(NULL, ZEND_FAST_CALL, NULL, NULL);
6810
2.32k
    opline->op1.num = try_catch_offset;
6811
2.32k
    opline->result_type = IS_TMP_VAR;
6812
2.32k
    opline->result.var = CG(context).fast_call_var;
6813
6814
2.32k
    zend_emit_op(NULL, ZEND_JMP, NULL, NULL);
6815
6816
2.32k
    zend_compile_stmt(finally_ast);
6817
6818
2.32k
    CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = opnum_jmp + 1;
6819
2.32k
    CG(active_op_array)->try_catch_array[try_catch_offset].finally_end
6820
2.32k
      = get_next_op_number();
6821
6822
2.32k
    opline = zend_emit_op(NULL, ZEND_FAST_RET, NULL, NULL);
6823
2.32k
    opline->op1_type = IS_TMP_VAR;
6824
2.32k
    opline->op1.var = CG(context).fast_call_var;
6825
2.32k
    opline->op2.num = orig_try_catch_offset;
6826
6827
2.32k
    zend_update_jump_target_to_next(opnum_jmp);
6828
6829
2.32k
    CG(context).fast_call_var = orig_fast_call_var;
6830
6831
    /* Pop DISCARD_EXCEPTION from unwind stack */
6832
2.32k
    zend_stack_del_top(&CG(loop_var_stack));
6833
2.32k
  }
6834
6835
44.8k
  CG(context).try_catch_offset = orig_try_catch_offset;
6836
6837
44.8k
  efree(jmp_opnums);
6838
44.8k
}
6839
/* }}} */
6840
6841
/* Encoding declarations must already be handled during parsing */
6842
bool zend_handle_encoding_declaration(zend_ast *ast) /* {{{ */
6843
1.97k
{
6844
1.97k
  zend_ast_list *declares = zend_ast_get_list(ast);
6845
1.97k
  uint32_t i;
6846
5.39k
  for (i = 0; i < declares->children; ++i) {
6847
3.44k
    zend_ast *declare_ast = declares->child[i];
6848
3.44k
    zend_ast *name_ast = declare_ast->child[0];
6849
3.44k
    zend_ast *value_ast = declare_ast->child[1];
6850
3.44k
    zend_string *name = zend_ast_get_str(name_ast);
6851
6852
3.44k
    if (zend_string_equals_literal_ci(name, "encoding")) {
6853
540
      if (value_ast->kind != ZEND_AST_ZVAL) {
6854
18
        zend_throw_exception(zend_ce_compile_error, "Encoding must be a literal", 0);
6855
18
        return 0;
6856
18
      }
6857
6858
522
      if (CG(multibyte)) {
6859
0
        zend_string *encoding_name = zval_get_string(zend_ast_get_zval(value_ast));
6860
6861
0
        const zend_encoding *new_encoding, *old_encoding;
6862
0
        zend_encoding_filter old_input_filter;
6863
6864
0
        CG(encoding_declared) = 1;
6865
6866
0
        new_encoding = zend_multibyte_fetch_encoding(ZSTR_VAL(encoding_name));
6867
0
        if (!new_encoding) {
6868
0
          zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", ZSTR_VAL(encoding_name));
6869
0
        } else {
6870
0
          old_input_filter = LANG_SCNG(input_filter);
6871
0
          old_encoding = LANG_SCNG(script_encoding);
6872
0
          zend_multibyte_set_filter(new_encoding);
6873
6874
          /* need to re-scan if input filter changed */
6875
0
          if (old_input_filter != LANG_SCNG(input_filter) ||
6876
0
             (old_input_filter && new_encoding != old_encoding)) {
6877
0
            zend_multibyte_yyinput_again(old_input_filter, old_encoding);
6878
0
          }
6879
0
        }
6880
6881
0
        zend_string_release_ex(encoding_name, 0);
6882
522
      } else {
6883
522
        zend_error(E_COMPILE_WARNING, "declare(encoding=...) ignored because "
6884
522
          "Zend multibyte feature is turned off by settings");
6885
522
      }
6886
522
    }
6887
3.44k
  }
6888
6889
1.95k
  return 1;
6890
1.97k
}
6891
/* }}} */
6892
6893
/* Check whether this is the first statement, not counting declares. */
6894
static zend_result zend_is_first_statement(zend_ast *ast, bool allow_nop) /* {{{ */
6895
3.30k
{
6896
3.30k
  uint32_t i = 0;
6897
3.30k
  zend_ast_list *file_ast = zend_ast_get_list(CG(ast));
6898
6899
22.4k
  while (i < file_ast->children) {
6900
22.4k
    if (file_ast->child[i] == ast) {
6901
3.25k
      return SUCCESS;
6902
19.1k
    } else if (file_ast->child[i] == NULL) {
6903
247
      if (!allow_nop) {
6904
1
        return FAILURE;
6905
1
      }
6906
18.9k
    } else if (file_ast->child[i]->kind != ZEND_AST_DECLARE) {
6907
50
      return FAILURE;
6908
50
    }
6909
19.1k
    i++;
6910
19.1k
  }
6911
2
  return FAILURE;
6912
3.30k
}
6913
/* }}} */
6914
6915
static void zend_compile_declare(zend_ast *ast) /* {{{ */
6916
1.56k
{
6917
1.56k
  zend_ast_list *declares = zend_ast_get_list(ast->child[0]);
6918
1.56k
  zend_ast *stmt_ast = ast->child[1];
6919
1.56k
  zend_declarables orig_declarables = FC(declarables);
6920
1.56k
  uint32_t i;
6921
6922
4.36k
  for (i = 0; i < declares->children; ++i) {
6923
2.89k
    zend_ast *declare_ast = declares->child[i];
6924
2.89k
    zend_ast *name_ast = declare_ast->child[0];
6925
2.89k
    zend_ast **value_ast_ptr = &declare_ast->child[1];
6926
2.89k
    zend_string *name = zend_ast_get_str(name_ast);
6927
6928
2.89k
    if ((*value_ast_ptr)->kind != ZEND_AST_ZVAL) {
6929
20
      zend_error_noreturn(E_COMPILE_ERROR, "declare(%s) value must be a literal", ZSTR_VAL(name));
6930
20
    }
6931
6932
2.87k
    if (zend_string_equals_literal_ci(name, "ticks")) {
6933
835
      zval value_zv;
6934
835
      zend_const_expr_to_zval(&value_zv, value_ast_ptr, /* allow_dynamic */ false);
6935
835
      FC(declarables).ticks = zval_get_long(&value_zv);
6936
835
      zval_ptr_dtor_nogc(&value_zv);
6937
2.03k
    } else if (zend_string_equals_literal_ci(name, "encoding")) {
6938
6939
366
      if (FAILURE == zend_is_first_statement(ast, /* allow_nop */ 0)) {
6940
8
        zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be "
6941
8
          "the very first statement in the script");
6942
8
      }
6943
1.67k
    } else if (zend_string_equals_literal_ci(name, "strict_types")) {
6944
332
      zval value_zv;
6945
6946
332
      if (FAILURE == zend_is_first_statement(ast, /* allow_nop */ 0)) {
6947
16
        zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must be "
6948
16
          "the very first statement in the script");
6949
16
      }
6950
6951
316
      if (ast->child[1] != NULL) {
6952
6
        zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must not "
6953
6
          "use block mode");
6954
6
      }
6955
6956
310
      zend_const_expr_to_zval(&value_zv, value_ast_ptr, /* allow_dynamic */ false);
6957
6958
310
      if (Z_TYPE(value_zv) != IS_LONG || (Z_LVAL(value_zv) != 0 && Z_LVAL(value_zv) != 1)) {
6959
46
        zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must have 0 or 1 as its value");
6960
46
      }
6961
6962
264
      if (Z_LVAL(value_zv) == 1) {
6963
232
        CG(active_op_array)->fn_flags |= ZEND_ACC_STRICT_TYPES;
6964
232
      }
6965
6966
1.33k
    } else {
6967
1.33k
      zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", ZSTR_VAL(name));
6968
1.33k
    }
6969
2.87k
  }
6970
6971
1.47k
  if (stmt_ast) {
6972
230
    zend_compile_stmt(stmt_ast);
6973
6974
230
    FC(declarables) = orig_declarables;
6975
230
  }
6976
1.47k
}
6977
/* }}} */
6978
6979
static void zend_compile_stmt_list(zend_ast *ast) /* {{{ */
6980
311k
{
6981
311k
  zend_ast_list *list = zend_ast_get_list(ast);
6982
311k
  uint32_t i;
6983
733k
  for (i = 0; i < list->children; ++i) {
6984
421k
    zend_compile_stmt(list->child[i]);
6985
421k
  }
6986
311k
}
6987
/* }}} */
6988
6989
ZEND_API void zend_set_function_arg_flags(zend_function *func) /* {{{ */
6990
73.7k
{
6991
73.7k
  uint32_t i, n;
6992
6993
73.7k
  func->common.arg_flags[0] = 0;
6994
73.7k
  func->common.arg_flags[1] = 0;
6995
73.7k
  func->common.arg_flags[2] = 0;
6996
73.7k
  if (func->common.arg_info) {
6997
73.7k
    n = MIN(func->common.num_args, MAX_ARG_FLAG_NUM);
6998
73.7k
    i = 0;
6999
152k
    while (i < n) {
7000
78.6k
      ZEND_SET_ARG_FLAG(func, i + 1, ZEND_ARG_SEND_MODE(&func->common.arg_info[i]));
7001
78.6k
      i++;
7002
78.6k
    }
7003
73.7k
    if (UNEXPECTED((func->common.fn_flags & ZEND_ACC_VARIADIC) && ZEND_ARG_SEND_MODE(&func->common.arg_info[i]))) {
7004
246
      uint32_t pass_by_reference = ZEND_ARG_SEND_MODE(&func->common.arg_info[i]);
7005
2.99k
      while (i < MAX_ARG_FLAG_NUM) {
7006
2.74k
        ZEND_SET_ARG_FLAG(func, i + 1, pass_by_reference);
7007
2.74k
        i++;
7008
2.74k
      }
7009
246
    }
7010
73.7k
  }
7011
73.7k
}
7012
/* }}} */
7013
7014
static zend_type zend_compile_single_typename(zend_ast *ast)
7015
75.1k
{
7016
75.1k
  ZEND_ASSERT(!(ast->attr & ZEND_TYPE_NULLABLE));
7017
75.1k
  if (ast->kind == ZEND_AST_TYPE) {
7018
5.65k
    if (ast->attr == IS_STATIC && !CG(active_class_entry) && zend_is_scope_known()) {
7019
6
      zend_error_noreturn(E_COMPILE_ERROR,
7020
6
        "Cannot use \"static\" when no class scope is active");
7021
6
    }
7022
7023
5.65k
    return (zend_type) ZEND_TYPE_INIT_CODE(ast->attr, 0, 0);
7024
69.4k
  } else {
7025
69.4k
    zend_string *type_name = zend_ast_get_str(ast);
7026
69.4k
    uint8_t type_code = zend_lookup_builtin_type_by_name(type_name);
7027
7028
69.4k
    if (type_code != 0) {
7029
26.0k
      if ((ast->attr & ZEND_NAME_NOT_FQ) != ZEND_NAME_NOT_FQ) {
7030
6
        zend_error_noreturn(E_COMPILE_ERROR,
7031
6
          "Type declaration '%s' must be unqualified",
7032
6
          ZSTR_VAL(zend_string_tolower(type_name)));
7033
6
      }
7034
7035
      /* Transform iterable into a type union alias */
7036
26.0k
      if (type_code == IS_ITERABLE) {
7037
        /* Set iterable bit for BC compat during Reflection and string representation of type */
7038
749
        zend_type iterable = (zend_type) ZEND_TYPE_INIT_CLASS_MASK(ZSTR_KNOWN(ZEND_STR_TRAVERSABLE),
7039
749
                  (MAY_BE_ARRAY|_ZEND_TYPE_ITERABLE_BIT));
7040
749
        return iterable;
7041
749
      }
7042
7043
25.2k
      return (zend_type) ZEND_TYPE_INIT_CODE(type_code, 0, 0);
7044
43.4k
    } else {
7045
43.4k
      const char *correct_name;
7046
43.4k
      uint32_t fetch_type = zend_get_class_fetch_type_ast(ast);
7047
43.4k
      zend_string *class_name = type_name;
7048
7049
43.4k
      if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
7050
41.9k
        class_name = zend_resolve_class_name_ast(ast);
7051
41.9k
        zend_assert_valid_class_name(class_name, "a type name");
7052
41.9k
      } else {
7053
1.50k
        ZEND_ASSERT(fetch_type == ZEND_FETCH_CLASS_SELF || fetch_type == ZEND_FETCH_CLASS_PARENT);
7054
7055
1.50k
        zend_ensure_valid_class_fetch_type(fetch_type);
7056
1.50k
        if (fetch_type == ZEND_FETCH_CLASS_SELF) {
7057
          /* Scope might be unknown for unbound closures and traits */
7058
1.10k
          if (zend_is_scope_known()) {
7059
416
            class_name = CG(active_class_entry)->name;
7060
416
            ZEND_ASSERT(class_name && "must know class name when resolving self type at compile time");
7061
416
          }
7062
1.10k
        } else {
7063
393
          ZEND_ASSERT(fetch_type == ZEND_FETCH_CLASS_PARENT);
7064
          /* Scope might be unknown for unbound closures and traits */
7065
372
          if (zend_is_scope_known()) {
7066
203
            class_name = CG(active_class_entry)->parent_name;
7067
203
            ZEND_ASSERT(class_name && "must know class name when resolving parent type at compile time");
7068
203
          }
7069
372
        }
7070
1.47k
        zend_string_addref(class_name);
7071
1.47k
      }
7072
7073
43.4k
      if (ast->attr == ZEND_NAME_NOT_FQ
7074
43.4k
          && zend_is_confusable_type(type_name, &correct_name)
7075
43.4k
          && zend_is_not_imported(type_name)) {
7076
505
        const char *extra =
7077
505
          FC(current_namespace) ? " or import the class with \"use\"" : "";
7078
505
        if (correct_name) {
7079
434
          zend_error(E_COMPILE_WARNING,
7080
434
            "\"%s\" will be interpreted as a class name. Did you mean \"%s\"? "
7081
434
            "Write \"\\%s\"%s to suppress this warning",
7082
434
            ZSTR_VAL(type_name), correct_name, ZSTR_VAL(class_name), extra);
7083
434
        } else {
7084
71
          zend_error(E_COMPILE_WARNING,
7085
71
            "\"%s\" is not a supported builtin type "
7086
71
            "and will be interpreted as a class name. "
7087
71
            "Write \"\\%s\"%s to suppress this warning",
7088
71
            ZSTR_VAL(type_name), ZSTR_VAL(class_name), extra);
7089
71
        }
7090
505
      }
7091
7092
43.4k
      class_name = zend_new_interned_string(class_name);
7093
43.4k
      zend_alloc_ce_cache(class_name);
7094
43.4k
      return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, /* allow null */ false, 0);
7095
43.4k
    }
7096
69.4k
  }
7097
75.1k
}
7098
7099
static void zend_are_intersection_types_redundant(const zend_type left_type, const zend_type right_type)
7100
9.49k
{
7101
9.49k
  ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(left_type));
7102
9.49k
  ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(right_type));
7103
9.49k
  zend_type_list *l_type_list = ZEND_TYPE_LIST(left_type);
7104
9.49k
  zend_type_list *r_type_list = ZEND_TYPE_LIST(right_type);
7105
9.49k
  zend_type_list *smaller_type_list, *larger_type_list;
7106
9.49k
  bool flipped = false;
7107
7108
9.49k
  if (r_type_list->num_types < l_type_list->num_types) {
7109
3.13k
    smaller_type_list = r_type_list;
7110
3.13k
    larger_type_list = l_type_list;
7111
3.13k
    flipped = true;
7112
6.36k
  } else {
7113
6.36k
    smaller_type_list = l_type_list;
7114
6.36k
    larger_type_list = r_type_list;
7115
6.36k
  }
7116
7117
9.49k
  unsigned int sum = 0;
7118
9.49k
  const zend_type *outer_type;
7119
33.3k
  ZEND_TYPE_LIST_FOREACH(smaller_type_list, outer_type)
7120
33.3k
    const zend_type *inner_type;
7121
114k
    ZEND_TYPE_LIST_FOREACH(larger_type_list, inner_type)
7122
114k
      if (zend_string_equals_ci(ZEND_TYPE_NAME(*inner_type), ZEND_TYPE_NAME(*outer_type))) {
7123
2.97k
        sum++;
7124
2.97k
        break;
7125
2.97k
      }
7126
114k
    ZEND_TYPE_LIST_FOREACH_END();
7127
33.3k
  ZEND_TYPE_LIST_FOREACH_END();
7128
7129
9.49k
  if (sum == smaller_type_list->num_types) {
7130
22
    zend_string *smaller_type_str;
7131
22
    zend_string *larger_type_str;
7132
22
    if (flipped) {
7133
8
      smaller_type_str = zend_type_to_string(right_type);
7134
8
      larger_type_str = zend_type_to_string(left_type);
7135
14
    } else {
7136
14
      smaller_type_str = zend_type_to_string(left_type);
7137
14
      larger_type_str = zend_type_to_string(right_type);
7138
14
    }
7139
22
    if (smaller_type_list->num_types == larger_type_list->num_types) {
7140
13
      zend_error_noreturn(E_COMPILE_ERROR, "Type %s is redundant with type %s",
7141
13
        ZSTR_VAL(smaller_type_str), ZSTR_VAL(larger_type_str));
7142
13
    } else {
7143
9
      zend_error_noreturn(E_COMPILE_ERROR, "Type %s is redundant as it is more restrictive than type %s",
7144
9
        ZSTR_VAL(larger_type_str), ZSTR_VAL(smaller_type_str));
7145
9
    }
7146
22
  }
7147
9.49k
}
7148
7149
static void zend_is_intersection_type_redundant_by_single_type(const zend_type intersection_type, const zend_type single_type)
7150
8.57k
{
7151
8.57k
  ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(intersection_type));
7152
8.57k
  ZEND_ASSERT(!ZEND_TYPE_IS_INTERSECTION(single_type));
7153
7154
8.57k
  const zend_type *single_intersection_type = NULL;
7155
32.8k
  ZEND_TYPE_FOREACH(intersection_type, single_intersection_type)
7156
32.8k
    if (zend_string_equals_ci(ZEND_TYPE_NAME(*single_intersection_type), ZEND_TYPE_NAME(single_type))) {
7157
8
      zend_string *single_type_str = zend_type_to_string(single_type);
7158
8
      zend_string *complete_type = zend_type_to_string(intersection_type);
7159
8
      zend_error_noreturn(E_COMPILE_ERROR, "Type %s is redundant as it is more restrictive than type %s",
7160
8
          ZSTR_VAL(complete_type), ZSTR_VAL(single_type_str));
7161
8
    }
7162
32.8k
  ZEND_TYPE_FOREACH_END();
7163
8.57k
}
7164
7165
/* Used by both intersection and union types prior to transforming the type list to a full zend_type */
7166
static void zend_is_type_list_redundant_by_single_type(const zend_type_list *type_list, const zend_type type)
7167
20.6k
{
7168
20.6k
  ZEND_ASSERT(!ZEND_TYPE_IS_INTERSECTION(type));
7169
47.0k
  for (size_t i = 0; i < type_list->num_types - 1; i++) {
7170
26.4k
    if (ZEND_TYPE_IS_INTERSECTION(type_list->types[i])) {
7171
4.85k
      zend_is_intersection_type_redundant_by_single_type(type_list->types[i], type);
7172
4.85k
      continue;
7173
4.85k
    }
7174
21.6k
    if (zend_string_equals_ci(ZEND_TYPE_NAME(type_list->types[i]), ZEND_TYPE_NAME(type))) {
7175
56
      zend_string *single_type_str = zend_type_to_string(type);
7176
56
      zend_error_noreturn(E_COMPILE_ERROR, "Duplicate type %s is redundant", ZSTR_VAL(single_type_str));
7177
56
    }
7178
21.6k
  }
7179
20.6k
}
7180
7181
static zend_type zend_compile_typename(zend_ast *ast);
7182
7183
static zend_type zend_compile_typename_ex(
7184
    zend_ast *ast, bool force_allow_null, bool *forced_allow_null) /* {{{ */
7185
57.3k
{
7186
57.3k
  bool is_marked_nullable = ast->attr & ZEND_TYPE_NULLABLE;
7187
57.3k
  zend_ast_attr orig_ast_attr = ast->attr;
7188
57.3k
  zend_type type = ZEND_TYPE_INIT_NONE(0);
7189
7190
57.3k
  if (is_marked_nullable) {
7191
2.47k
    ast->attr &= ~ZEND_TYPE_NULLABLE;
7192
2.47k
  }
7193
7194
57.3k
  if (ast->kind == ZEND_AST_TYPE_UNION) {
7195
8.24k
    zend_ast_list *list = zend_ast_get_list(ast);
7196
8.24k
    zend_type_list *type_list;
7197
8.24k
    bool is_composite = false;
7198
8.24k
    bool has_only_iterable_class = true;
7199
8.24k
    ALLOCA_FLAG(use_heap)
7200
7201
8.24k
    type_list = do_alloca(ZEND_TYPE_LIST_SIZE(list->children), use_heap);
7202
8.24k
    type_list->num_types = 0;
7203
7204
30.0k
    for (uint32_t i = 0; i < list->children; i++) {
7205
21.8k
      zend_ast *type_ast = list->child[i];
7206
21.8k
      zend_type single_type;
7207
21.8k
      uint32_t type_mask = ZEND_TYPE_FULL_MASK(type);
7208
7209
21.8k
      if (type_ast->kind == ZEND_AST_TYPE_INTERSECTION) {
7210
4.26k
        has_only_iterable_class = false;
7211
4.26k
        is_composite = true;
7212
        /* The first class type can be stored directly as the type ptr payload. */
7213
4.26k
        if (ZEND_TYPE_IS_COMPLEX(type) && !ZEND_TYPE_HAS_LIST(type)) {
7214
          /* Switch from single name to name list. */
7215
342
          type_list->num_types = 1;
7216
342
          type_list->types[0] = type;
7217
          /* Clear MAY_BE_* type flags */
7218
342
          ZEND_TYPE_FULL_MASK(type_list->types[0]) &= ~_ZEND_TYPE_MAY_BE_MASK;
7219
342
        }
7220
        /* Mark type as list type */
7221
4.26k
        ZEND_TYPE_SET_LIST(type, type_list);
7222
7223
4.26k
        single_type = zend_compile_typename(type_ast);
7224
4.26k
        ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(single_type));
7225
7226
4.26k
        type_list->types[type_list->num_types++] = single_type;
7227
7228
        /* Check for trivially redundant class types */
7229
17.4k
        for (size_t i = 0; i < type_list->num_types - 1; i++) {
7230
13.2k
          if (ZEND_TYPE_IS_INTERSECTION(type_list->types[i])) {
7231
9.49k
            zend_are_intersection_types_redundant(single_type, type_list->types[i]);
7232
9.49k
            continue;
7233
9.49k
          }
7234
          /* Type from type list is a simple type */
7235
3.71k
          zend_is_intersection_type_redundant_by_single_type(single_type, type_list->types[i]);
7236
3.71k
        }
7237
4.26k
        continue;
7238
4.26k
      }
7239
7240
17.5k
      single_type = zend_compile_single_typename(type_ast);
7241
17.5k
      uint32_t single_type_mask = ZEND_TYPE_PURE_MASK(single_type);
7242
7243
17.5k
      if (single_type_mask == MAY_BE_ANY) {
7244
6
        zend_error_noreturn(E_COMPILE_ERROR, "Type mixed can only be used as a standalone type");
7245
6
      }
7246
17.5k
      if (ZEND_TYPE_IS_COMPLEX(single_type) && !ZEND_TYPE_IS_ITERABLE_FALLBACK(single_type)) {
7247
10.5k
        has_only_iterable_class = false;
7248
10.5k
      }
7249
7250
17.5k
      uint32_t type_mask_overlap = ZEND_TYPE_PURE_MASK(type) & single_type_mask;
7251
17.5k
      if (type_mask_overlap) {
7252
42
        zend_type overlap_type = ZEND_TYPE_INIT_MASK(type_mask_overlap);
7253
42
        zend_string *overlap_type_str = zend_type_to_string(overlap_type);
7254
42
        zend_error_noreturn(E_COMPILE_ERROR,
7255
42
          "Duplicate type %s is redundant", ZSTR_VAL(overlap_type_str));
7256
42
      }
7257
7258
17.5k
      if ( ((type_mask & MAY_BE_TRUE) && (single_type_mask == MAY_BE_FALSE))
7259
17.5k
          || ((type_mask & MAY_BE_FALSE) && (single_type_mask == MAY_BE_TRUE)) ) {
7260
12
        zend_error_noreturn(E_COMPILE_ERROR,
7261
12
          "Type contains both true and false, bool must be used instead");
7262
12
      }
7263
17.5k
      ZEND_TYPE_FULL_MASK(type) |= ZEND_TYPE_PURE_MASK(single_type);
7264
      /* Clear MAY_BE_* type flags */
7265
17.5k
      ZEND_TYPE_FULL_MASK(single_type) &= ~_ZEND_TYPE_MAY_BE_MASK;
7266
7267
17.5k
      if (ZEND_TYPE_IS_COMPLEX(single_type)) {
7268
11.0k
        if (!ZEND_TYPE_IS_COMPLEX(type) && !is_composite) {
7269
          /* The first class type can be stored directly as the type ptr payload. */
7270
4.59k
          ZEND_TYPE_SET_PTR(type, ZEND_TYPE_NAME(single_type));
7271
4.59k
          ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_NAME_BIT;
7272
6.44k
        } else {
7273
6.44k
          if (type_list->num_types == 0) {
7274
            /* Switch from single name to name list. */
7275
3.05k
            type_list->num_types = 1;
7276
3.05k
            type_list->types[0] = type;
7277
            /* Clear MAY_BE_* type flags */
7278
3.05k
            ZEND_TYPE_FULL_MASK(type_list->types[0]) &= ~_ZEND_TYPE_MAY_BE_MASK;
7279
3.05k
            ZEND_TYPE_SET_LIST(type, type_list);
7280
3.05k
          }
7281
7282
6.44k
          type_list->types[type_list->num_types++] = single_type;
7283
7284
          /* Check for trivially redundant class types */
7285
6.44k
          zend_is_type_list_redundant_by_single_type(type_list, single_type);
7286
6.44k
        }
7287
11.0k
      }
7288
17.5k
    }
7289
7290
8.18k
    if (type_list->num_types) {
7291
5.05k
      zend_type_list *list = zend_arena_alloc(
7292
5.05k
        &CG(arena), ZEND_TYPE_LIST_SIZE(type_list->num_types));
7293
5.05k
      memcpy(list, type_list, ZEND_TYPE_LIST_SIZE(type_list->num_types));
7294
5.05k
      ZEND_TYPE_SET_LIST(type, list);
7295
5.05k
      ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT;
7296
      /* Inform that the type list is a union type */
7297
5.05k
      ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_UNION_BIT;
7298
5.05k
    }
7299
7300
8.18k
    free_alloca(type_list, use_heap);
7301
7302
8.18k
    uint32_t type_mask = ZEND_TYPE_FULL_MASK(type);
7303
8.18k
    if ((type_mask & MAY_BE_OBJECT) &&
7304
8.18k
        ((!has_only_iterable_class && ZEND_TYPE_IS_COMPLEX(type)) || (type_mask & MAY_BE_STATIC))) {
7305
37
      zend_string *type_str = zend_type_to_string(type);
7306
37
      zend_error_noreturn(E_COMPILE_ERROR,
7307
37
        "Type %s contains both object and a class type, which is redundant",
7308
37
        ZSTR_VAL(type_str));
7309
37
    }
7310
49.1k
  } else if (ast->kind == ZEND_AST_TYPE_INTERSECTION) {
7311
5.84k
    zend_ast_list *list = zend_ast_get_list(ast);
7312
5.84k
    zend_type_list *type_list;
7313
7314
    /* Allocate the type list directly on the arena as it must be a type
7315
     * list of the same number of elements as the AST list has children */
7316
5.84k
    type_list = zend_arena_alloc(&CG(arena), ZEND_TYPE_LIST_SIZE(list->children));
7317
5.84k
    type_list->num_types = 0;
7318
7319
5.84k
    ZEND_ASSERT(list->children > 1);
7320
7321
20.0k
    for (uint32_t i = 0; i < list->children; i++) {
7322
14.3k
      zend_ast *type_ast = list->child[i];
7323
14.3k
      zend_type single_type = zend_compile_single_typename(type_ast);
7324
7325
      /* An intersection of union types cannot exist so invalidate it
7326
       * Currently only can happen with iterable getting canonicalized to Traversable|array */
7327
14.3k
      if (ZEND_TYPE_IS_ITERABLE_FALLBACK(single_type)) {
7328
6
        zend_string *standard_type_str = zend_type_to_string(single_type);
7329
6
        zend_error_noreturn(E_COMPILE_ERROR,
7330
6
          "Type %s cannot be part of an intersection type", ZSTR_VAL(standard_type_str));
7331
0
        zend_string_release_ex(standard_type_str, false);
7332
0
      }
7333
      /* An intersection of standard types cannot exist so invalidate it */
7334
14.2k
      if (ZEND_TYPE_IS_ONLY_MASK(single_type)) {
7335
64
        zend_string *standard_type_str = zend_type_to_string(single_type);
7336
64
        zend_error_noreturn(E_COMPILE_ERROR,
7337
64
          "Type %s cannot be part of an intersection type", ZSTR_VAL(standard_type_str));
7338
0
        zend_string_release_ex(standard_type_str, false);
7339
0
      }
7340
      /* Check for "self" and "parent" too */
7341
14.2k
      if (
7342
14.2k
        zend_string_equals_ci(ZEND_TYPE_NAME(single_type), ZSTR_KNOWN(ZEND_STR_SELF))
7343
14.2k
        || zend_string_equals_ci(ZEND_TYPE_NAME(single_type), ZSTR_KNOWN(ZEND_STR_PARENT))
7344
14.2k
      ) {
7345
12
        zend_error_noreturn(E_COMPILE_ERROR,
7346
12
          "Type %s cannot be part of an intersection type", ZSTR_VAL(ZEND_TYPE_NAME(single_type)));
7347
12
      }
7348
7349
      /* Add type to the type list */
7350
14.2k
      type_list->types[type_list->num_types++] = single_type;
7351
7352
      /* Check for trivially redundant class types */
7353
14.2k
      zend_is_type_list_redundant_by_single_type(type_list, single_type);
7354
14.2k
    }
7355
7356
5.76k
    ZEND_ASSERT(list->children == type_list->num_types);
7357
7358
    /* An implicitly nullable intersection type needs to be converted to a DNF type */
7359
5.75k
    if (force_allow_null) {
7360
141
      zend_type intersection_type = ZEND_TYPE_INIT_NONE(0);
7361
141
      ZEND_TYPE_SET_LIST(intersection_type, type_list);
7362
141
      ZEND_TYPE_FULL_MASK(intersection_type) |= _ZEND_TYPE_INTERSECTION_BIT;
7363
141
      ZEND_TYPE_FULL_MASK(intersection_type) |= _ZEND_TYPE_ARENA_BIT;
7364
7365
141
      zend_type_list *dnf_type_list = zend_arena_alloc(&CG(arena), ZEND_TYPE_LIST_SIZE(1));
7366
141
      dnf_type_list->num_types = 1;
7367
141
      dnf_type_list->types[0] = intersection_type;
7368
141
      ZEND_TYPE_SET_LIST(type, dnf_type_list);
7369
      /* Inform that the type list is a DNF type */
7370
141
      ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_UNION_BIT;
7371
141
      ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT;
7372
5.60k
    } else {
7373
5.60k
      ZEND_TYPE_SET_LIST(type, type_list);
7374
      /* Inform that the type list is an intersection type */
7375
5.60k
      ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_INTERSECTION_BIT;
7376
5.60k
      ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT;
7377
5.60k
    }
7378
43.2k
  } else {
7379
43.2k
    type = zend_compile_single_typename(ast);
7380
43.2k
  }
7381
7382
57.1k
  uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
7383
7384
57.1k
  if (type_mask == MAY_BE_ANY && is_marked_nullable) {
7385
19
    zend_error_noreturn(E_COMPILE_ERROR, "Type mixed cannot be marked as nullable since mixed already includes null");
7386
19
  }
7387
7388
57.1k
  if ((type_mask & MAY_BE_NULL) && is_marked_nullable) {
7389
6
    zend_error_noreturn(E_COMPILE_ERROR, "null cannot be marked as nullable");
7390
6
  }
7391
7392
57.1k
  if (force_allow_null && !is_marked_nullable && !(type_mask & MAY_BE_NULL)) {
7393
398
    *forced_allow_null = true;
7394
398
  }
7395
7396
57.1k
  if (is_marked_nullable || force_allow_null) {
7397
2.97k
    ZEND_TYPE_FULL_MASK(type) |= MAY_BE_NULL;
7398
2.97k
    type_mask = ZEND_TYPE_PURE_MASK(type);
7399
2.97k
  }
7400
7401
57.1k
  if ((type_mask & MAY_BE_VOID) && (ZEND_TYPE_IS_COMPLEX(type) || type_mask != MAY_BE_VOID)) {
7402
12
    zend_error_noreturn(E_COMPILE_ERROR, "Void can only be used as a standalone type");
7403
12
  }
7404
7405
57.1k
  if ((type_mask & MAY_BE_NEVER) && (ZEND_TYPE_IS_COMPLEX(type) || type_mask != MAY_BE_NEVER)) {
7406
7
    zend_error_noreturn(E_COMPILE_ERROR, "never can only be used as a standalone type");
7407
7
  }
7408
7409
57.1k
  ast->attr = orig_ast_attr;
7410
57.1k
  return type;
7411
57.1k
}
7412
/* }}} */
7413
7414
static zend_type zend_compile_typename(zend_ast *ast)
7415
34.1k
{
7416
34.1k
  bool forced_allow_null;
7417
34.1k
  return zend_compile_typename_ex(ast, false, &forced_allow_null);
7418
34.1k
}
7419
7420
/* May convert value from int to float. */
7421
static bool zend_is_valid_default_value(zend_type type, zval *value)
7422
2.58k
{
7423
2.58k
  ZEND_ASSERT(ZEND_TYPE_IS_SET(type));
7424
2.58k
  if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(value))) {
7425
2.29k
    return 1;
7426
2.29k
  }
7427
293
  if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_DOUBLE) && Z_TYPE_P(value) == IS_LONG) {
7428
    /* Integers are allowed as initializers for floating-point values. */
7429
138
    convert_to_double(value);
7430
138
    return 1;
7431
138
  }
7432
155
  return 0;
7433
293
}
7434
7435
static void zend_compile_attributes(
7436
  HashTable **attributes, zend_ast *ast, uint32_t offset, uint32_t target, uint32_t promoted
7437
10.1k
) /* {{{ */ {
7438
10.1k
  zend_attribute *attr;
7439
10.1k
  zend_internal_attribute *config;
7440
7441
10.1k
  zend_ast_list *list = zend_ast_get_list(ast);
7442
10.1k
  uint32_t g, i, j;
7443
7444
10.1k
  ZEND_ASSERT(ast->kind == ZEND_AST_ATTRIBUTE_LIST);
7445
7446
21.8k
  for (g = 0; g < list->children; g++) {
7447
11.8k
    zend_ast_list *group = zend_ast_get_list(list->child[g]);
7448
7449
11.8k
    ZEND_ASSERT(group->kind == ZEND_AST_ATTRIBUTE_GROUP);
7450
7451
42.4k
    for (i = 0; i < group->children; i++) {
7452
30.6k
      ZEND_ASSERT(group->child[i]->kind == ZEND_AST_ATTRIBUTE);
7453
7454
30.6k
      zend_ast *el = group->child[i];
7455
7456
30.6k
      if (el->child[1] &&
7457
30.6k
          el->child[1]->kind == ZEND_AST_CALLABLE_CONVERT) {
7458
12
          zend_error_noreturn(E_COMPILE_ERROR,
7459
12
              "Cannot create Closure as attribute argument");
7460
12
      }
7461
7462
30.6k
      zend_string *name = zend_resolve_class_name_ast(el->child[0]);
7463
30.6k
      zend_string *lcname = zend_string_tolower_ex(name, false);
7464
30.6k
      zend_ast_list *args = el->child[1] ? zend_ast_get_list(el->child[1]) : NULL;
7465
7466
30.6k
      config = zend_internal_attribute_get(lcname);
7467
30.6k
      zend_string_release(lcname);
7468
7469
      /* Exclude internal attributes that do not match on promoted properties. */
7470
30.6k
      if (config && !(target & (config->flags & ZEND_ATTRIBUTE_TARGET_ALL))) {
7471
252
        if (promoted & (config->flags & ZEND_ATTRIBUTE_TARGET_ALL)) {
7472
0
          zend_string_release(name);
7473
0
          continue;
7474
0
        }
7475
252
      }
7476
7477
30.6k
      uint32_t flags = (CG(active_op_array)->fn_flags & ZEND_ACC_STRICT_TYPES)
7478
30.6k
        ? ZEND_ATTRIBUTE_STRICT_TYPES : 0;
7479
30.6k
      attr = zend_add_attribute(
7480
30.6k
        attributes, name, args ? args->children : 0, flags, offset, el->lineno);
7481
30.6k
      zend_string_release(name);
7482
7483
      /* Populate arguments */
7484
30.6k
      if (args) {
7485
4.17k
        ZEND_ASSERT(args->kind == ZEND_AST_ARG_LIST);
7486
7487
4.17k
        bool uses_named_args = 0;
7488
23.8k
        for (j = 0; j < args->children; j++) {
7489
19.7k
          zend_ast **arg_ast_ptr = &args->child[j];
7490
19.7k
          zend_ast *arg_ast = *arg_ast_ptr;
7491
7492
19.7k
          if (arg_ast->kind == ZEND_AST_UNPACK) {
7493
6
            zend_error_noreturn(E_COMPILE_ERROR,
7494
6
              "Cannot use unpacking in attribute argument list");
7495
6
          }
7496
7497
19.7k
          if (arg_ast->kind == ZEND_AST_NAMED_ARG) {
7498
2.11k
            attr->args[j].name = zend_string_copy(zend_ast_get_str(arg_ast->child[0]));
7499
2.11k
            arg_ast_ptr = &arg_ast->child[1];
7500
2.11k
            uses_named_args = 1;
7501
7502
7.55k
            for (uint32_t k = 0; k < j; k++) {
7503
5.45k
              if (attr->args[k].name &&
7504
5.45k
                  zend_string_equals(attr->args[k].name, attr->args[j].name)) {
7505
9
                zend_error_noreturn(E_COMPILE_ERROR, "Duplicate named parameter $%s",
7506
9
                  ZSTR_VAL(attr->args[j].name));
7507
9
              }
7508
5.45k
            }
7509
17.6k
          } else if (uses_named_args) {
7510
42
            zend_error_noreturn(E_COMPILE_ERROR,
7511
42
              "Cannot use positional argument after named argument");
7512
42
          }
7513
7514
19.6k
          zend_const_expr_to_zval(
7515
19.6k
            &attr->args[j].value, arg_ast_ptr, /* allow_dynamic */ true);
7516
19.6k
        }
7517
4.17k
      }
7518
30.6k
    }
7519
11.8k
  }
7520
7521
10.0k
  if (*attributes != NULL) {
7522
    /* Validate attributes in a secondary loop (needed to detect repeated attributes). */
7523
117k
    ZEND_HASH_PACKED_FOREACH_PTR(*attributes, attr) {
7524
117k
      if (attr->offset != offset || NULL == (config = zend_internal_attribute_get(attr->lcname))) {
7525
46.7k
        continue;
7526
46.7k
      }
7527
7528
1.84k
      if (!(target & (config->flags & ZEND_ATTRIBUTE_TARGET_ALL))) {
7529
45
        zend_string *location = zend_get_attribute_target_names(target);
7530
45
        zend_string *allowed = zend_get_attribute_target_names(config->flags);
7531
7532
45
        zend_error_noreturn(E_ERROR, "Attribute \"%s\" cannot target %s (allowed targets: %s)",
7533
45
          ZSTR_VAL(attr->name), ZSTR_VAL(location), ZSTR_VAL(allowed)
7534
45
        );
7535
45
      }
7536
7537
1.79k
      if (!(config->flags & ZEND_ATTRIBUTE_IS_REPEATABLE)) {
7538
1.79k
        if (zend_is_attribute_repeated(*attributes, attr)) {
7539
28
          zend_error_noreturn(E_ERROR, "Attribute \"%s\" must not be repeated", ZSTR_VAL(attr->name));
7540
28
        }
7541
1.79k
      }
7542
7543
1.76k
      if (config->validator != NULL) {
7544
481
        config->validator(attr, target, CG(active_class_entry));
7545
481
      }
7546
1.76k
    } ZEND_HASH_FOREACH_END();
7547
10.0k
  }
7548
10.0k
}
7549
/* }}} */
7550
7551
static void zend_compile_property_hooks(
7552
    zend_property_info *prop_info, zend_string *prop_name,
7553
    zend_ast *prop_type_ast, zend_ast_list *hooks);
7554
7555
typedef struct {
7556
  zend_string *property_name;
7557
  bool uses_property;
7558
} find_property_usage_context;
7559
7560
static void zend_property_hook_find_property_usage(zend_ast **ast_ptr, void *_context) /* {{{ */
7561
31.6k
{
7562
31.6k
  zend_ast *ast = *ast_ptr;
7563
31.6k
  find_property_usage_context *context = (find_property_usage_context *) _context;
7564
7565
31.6k
  if (ast == NULL) {
7566
549
    return;
7567
31.0k
  } else if (ast->kind == ZEND_AST_PROP || ast->kind == ZEND_AST_NULLSAFE_PROP) {
7568
2.63k
    zend_ast *object_ast = ast->child[0];
7569
2.63k
    zend_ast *property_ast = ast->child[1];
7570
7571
2.63k
    if (object_ast->kind == ZEND_AST_VAR
7572
2.63k
     && object_ast->child[0]->kind == ZEND_AST_ZVAL
7573
2.63k
     && property_ast->kind == ZEND_AST_ZVAL) {
7574
2.02k
      zval *object = zend_ast_get_zval(object_ast->child[0]);
7575
2.02k
      zval *property = zend_ast_get_zval(property_ast);
7576
2.02k
      if (Z_TYPE_P(object) == IS_STRING
7577
2.02k
        && Z_TYPE_P(property) == IS_STRING
7578
2.02k
        && zend_string_equals_literal(Z_STR_P(object), "this")
7579
2.02k
        && zend_string_equals(Z_STR_P(property), context->property_name)) {
7580
630
        context->uses_property = true;
7581
        /* No need to look for references in this branch. */
7582
630
        return;
7583
630
      }
7584
2.02k
    }
7585
2.63k
  }
7586
7587
  /* Don't search across function/class boundaries. */
7588
30.4k
  if (!zend_ast_is_special(ast)) {
7589
19.6k
    zend_ast_apply(ast, zend_property_hook_find_property_usage, context);
7590
19.6k
  }
7591
30.4k
}
7592
7593
static bool zend_property_hook_uses_property(zend_string *property_name, zend_string *hook_name, zend_ast *hook_ast)
7594
5.41k
{
7595
5.41k
  if (zend_string_equals_literal_ci(hook_name, "set")
7596
5.41k
   && hook_ast->kind == ZEND_AST_PROPERTY_HOOK_SHORT_BODY) {
7597
371
    return true;
7598
371
  }
7599
7600
5.04k
  find_property_usage_context context = { property_name, false };
7601
5.04k
  zend_property_hook_find_property_usage(&hook_ast, &context);
7602
5.04k
  return context.uses_property;
7603
5.41k
}
7604
7605
static bool zend_property_is_virtual(zend_class_entry *ce, zend_string *property_name, zend_ast *hooks_ast, uint32_t flags)
7606
23.0k
{
7607
23.0k
  if (ce->ce_flags & ZEND_ACC_INTERFACE) {
7608
334
    return true;
7609
334
  }
7610
22.7k
  if (!hooks_ast) {
7611
18.6k
    return false;
7612
18.6k
  }
7613
7614
4.12k
  bool is_virtual = true;
7615
7616
4.12k
  zend_ast_list *hooks = zend_ast_get_list(hooks_ast);
7617
10.7k
  for (uint32_t i = 0; i < hooks->children; i++) {
7618
6.61k
    zend_ast_decl *hook = (zend_ast_decl *) hooks->child[i];
7619
6.61k
    zend_ast *body = hook->child[2];
7620
6.61k
    if (body && zend_property_hook_uses_property(property_name, hook->name, body)) {
7621
944
      is_virtual = false;
7622
944
    }
7623
6.61k
  }
7624
7625
4.12k
  return is_virtual;
7626
22.7k
}
7627
7628
static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fallback_return_type) /* {{{ */
7629
94.3k
{
7630
94.3k
  zend_ast_list *list = zend_ast_get_list(ast);
7631
94.3k
  uint32_t i;
7632
94.3k
  zend_op_array *op_array = CG(active_op_array);
7633
94.3k
  zend_arg_info *arg_infos;
7634
7635
94.3k
  if (return_type_ast || fallback_return_type) {
7636
    /* Use op_array->arg_info[-1] for return type */
7637
17.8k
    arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children + 1, 0);
7638
17.8k
    arg_infos->name = NULL;
7639
17.8k
    if (return_type_ast) {
7640
17.4k
      arg_infos->type = zend_compile_typename(return_type_ast);
7641
17.4k
      ZEND_TYPE_FULL_MASK(arg_infos->type) |= _ZEND_ARG_INFO_FLAGS(
7642
17.4k
        (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0, /* is_tentative */ 0);
7643
17.4k
    } else {
7644
418
      arg_infos->type = (zend_type) ZEND_TYPE_INIT_CODE(fallback_return_type, 0, 0);
7645
418
    }
7646
17.8k
    arg_infos++;
7647
17.8k
    op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
7648
7649
17.8k
    if (ZEND_TYPE_CONTAINS_CODE(arg_infos[-1].type, IS_VOID)
7650
17.8k
        && (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
7651
264
      zend_string *func_name = get_function_or_method_name((zend_function *) op_array);
7652
264
      zend_error(E_DEPRECATED, "%s(): Returning by reference from a void function is deprecated", ZSTR_VAL(func_name));
7653
264
      zend_string_release(func_name);
7654
264
    }
7655
76.5k
  } else {
7656
76.5k
    if (list->children == 0) {
7657
46.0k
      return;
7658
46.0k
    }
7659
30.5k
    arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children, 0);
7660
30.5k
  }
7661
7662
  /* Find last required parameter number for deprecation message. */
7663
48.3k
  uint32_t last_required_param = (uint32_t) -1;
7664
105k
  for (i = 0; i < list->children; ++i) {
7665
56.7k
    zend_ast *param_ast = list->child[i];
7666
56.7k
    zend_ast *default_ast_ptr = param_ast->child[2];
7667
56.7k
    bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
7668
56.7k
    if (!default_ast_ptr && !is_variadic) {
7669
48.9k
      last_required_param = i;
7670
48.9k
    }
7671
56.7k
  }
7672
7673
101k
  for (i = 0; i < list->children; ++i) {
7674
53.2k
    zend_ast *param_ast = list->child[i];
7675
53.2k
    zend_ast *type_ast = param_ast->child[0];
7676
53.2k
    zend_ast *var_ast = param_ast->child[1];
7677
53.2k
    zend_ast **default_ast_ptr = &param_ast->child[2];
7678
53.2k
    zend_ast *attributes_ast = param_ast->child[3];
7679
53.2k
    zend_ast *doc_comment_ast = param_ast->child[4];
7680
53.2k
    zend_ast *hooks_ast = param_ast->child[5];
7681
53.2k
    zend_string *name = zval_make_interned_string(zend_ast_get_zval(var_ast));
7682
53.2k
    bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
7683
53.2k
    bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
7684
53.2k
    uint32_t property_flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY);
7685
53.2k
    bool is_promoted = property_flags || hooks_ast;
7686
7687
53.2k
    znode var_node, default_node;
7688
53.2k
    uint8_t opcode;
7689
53.2k
    zend_op *opline;
7690
53.2k
    zend_arg_info *arg_info;
7691
7692
53.2k
    if (zend_is_auto_global(name)) {
7693
3
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign auto-global variable %s",
7694
3
        ZSTR_VAL(name));
7695
3
    }
7696
7697
53.2k
    var_node.op_type = IS_CV;
7698
53.2k
    var_node.u.op.var = lookup_cv(name);
7699
7700
53.2k
    if (EX_VAR_TO_NUM(var_node.u.op.var) != i) {
7701
49
      zend_error_noreturn(E_COMPILE_ERROR, "Redefinition of parameter $%s",
7702
49
        ZSTR_VAL(name));
7703
53.1k
    } else if (zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS))) {
7704
6
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as parameter");
7705
6
    }
7706
7707
53.1k
    if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
7708
11
      zend_error_noreturn(E_COMPILE_ERROR, "Only the last parameter can be variadic");
7709
11
    }
7710
7711
53.1k
    if (is_variadic) {
7712
638
      opcode = ZEND_RECV_VARIADIC;
7713
638
      default_node.op_type = IS_UNUSED;
7714
638
      op_array->fn_flags |= ZEND_ACC_VARIADIC;
7715
7716
638
      if (*default_ast_ptr) {
7717
6
        zend_error_noreturn(E_COMPILE_ERROR,
7718
6
          "Variadic parameter cannot have a default value");
7719
6
      }
7720
52.5k
    } else if (*default_ast_ptr) {
7721
      /* we cannot substitute constants here or it will break ReflectionParameter::getDefaultValueConstantName() and ReflectionParameter::isDefaultValueConstant() */
7722
6.82k
      uint32_t cops = CG(compiler_options);
7723
6.82k
      CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION;
7724
6.82k
      opcode = ZEND_RECV_INIT;
7725
6.82k
      default_node.op_type = IS_CONST;
7726
6.82k
      zend_const_expr_to_zval(
7727
6.82k
        &default_node.u.constant, default_ast_ptr, /* allow_dynamic */ true);
7728
6.82k
      CG(compiler_options) = cops;
7729
45.6k
    } else {
7730
45.6k
      opcode = ZEND_RECV;
7731
45.6k
      default_node.op_type = IS_UNUSED;
7732
45.6k
      op_array->required_num_args = i + 1;
7733
45.6k
    }
7734
7735
53.1k
    arg_info = &arg_infos[i];
7736
53.1k
    arg_info->name = zend_string_copy(name);
7737
53.1k
    arg_info->type = (zend_type) ZEND_TYPE_INIT_NONE(0);
7738
7739
53.1k
    if (attributes_ast) {
7740
1.81k
      zend_compile_attributes(
7741
1.81k
        &op_array->attributes, attributes_ast, i + 1, ZEND_ATTRIBUTE_TARGET_PARAMETER,
7742
1.81k
        is_promoted ? ZEND_ATTRIBUTE_TARGET_PROPERTY : 0
7743
1.81k
      );
7744
1.81k
    }
7745
7746
53.1k
    bool forced_allow_nullable = false;
7747
53.1k
    if (type_ast) {
7748
23.1k
      uint32_t default_type = *default_ast_ptr ? Z_TYPE(default_node.u.constant) : IS_UNDEF;
7749
23.1k
      bool force_nullable = default_type == IS_NULL && !is_promoted;
7750
7751
23.1k
      op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
7752
23.1k
      arg_info->type = zend_compile_typename_ex(type_ast, force_nullable, &forced_allow_nullable);
7753
23.1k
      if (forced_allow_nullable) {
7754
398
        zend_string *func_name = get_function_or_method_name((zend_function *) op_array);
7755
398
        zend_error(E_DEPRECATED,
7756
398
           "%s(): Implicitly marking parameter $%s as nullable is deprecated, the explicit nullable type "
7757
398
           "must be used instead", ZSTR_VAL(func_name), ZSTR_VAL(name));
7758
398
        zend_string_release(func_name);
7759
398
      }
7760
7761
23.1k
      if (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_VOID) {
7762
6
        zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type");
7763
6
      }
7764
7765
23.1k
      if (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_NEVER) {
7766
6
        zend_error_noreturn(E_COMPILE_ERROR, "never cannot be used as a parameter type");
7767
6
      }
7768
7769
23.1k
      if (default_type != IS_UNDEF && default_type != IS_CONSTANT_AST && !force_nullable
7770
23.1k
          && !zend_is_valid_default_value(arg_info->type, &default_node.u.constant)) {
7771
39
        zend_string *type_str = zend_type_to_string(arg_info->type);
7772
39
        zend_error_noreturn(E_COMPILE_ERROR,
7773
39
          "Cannot use %s as default value for parameter $%s of type %s",
7774
39
          zend_get_type_by_const(default_type),
7775
39
          ZSTR_VAL(name), ZSTR_VAL(type_str));
7776
39
      }
7777
23.1k
    }
7778
53.0k
    if (last_required_param != (uint32_t) -1
7779
53.0k
     && i < last_required_param
7780
53.0k
     && default_node.op_type == IS_CONST) {
7781
      /* Ignore parameters of the form "Type $param = null".
7782
       * This is the PHP 5 style way of writing "?Type $param", so allow it for now. */
7783
1.00k
      if (!forced_allow_nullable) {
7784
721
        zend_string *func_name = get_function_or_method_name((zend_function *) op_array);
7785
721
        zend_ast *required_param_ast = list->child[last_required_param];
7786
721
        zend_error(E_DEPRECATED,
7787
721
          "%s(): Optional parameter $%s declared before required parameter $%s "
7788
721
          "is implicitly treated as a required parameter",
7789
721
          ZSTR_VAL(func_name), ZSTR_VAL(name), ZSTR_VAL(zend_ast_get_str(required_param_ast->child[1])));
7790
721
        zend_string_release(func_name);
7791
721
      }
7792
7793
      /* Regardless of whether we issue a deprecation, convert this parameter into
7794
       * a required parameter without a default value. This ensures that it cannot be
7795
       * used as an optional parameter even with named parameters. */
7796
1.00k
      opcode = ZEND_RECV;
7797
1.00k
      default_node.op_type = IS_UNUSED;
7798
1.00k
      zval_ptr_dtor(&default_node.u.constant);
7799
1.00k
    }
7800
7801
53.0k
    opline = zend_emit_op(NULL, opcode, NULL, &default_node);
7802
53.0k
    SET_NODE(opline->result, &var_node);
7803
53.0k
    opline->op1.num = i + 1;
7804
7805
53.0k
    uint32_t arg_info_flags = _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic, /* is_tentative */ 0)
7806
53.0k
      | (is_promoted ? _ZEND_IS_PROMOTED_BIT : 0);
7807
53.0k
    ZEND_TYPE_FULL_MASK(arg_info->type) |= arg_info_flags;
7808
53.0k
    if (opcode == ZEND_RECV) {
7809
46.6k
      opline->op2.num = type_ast ?
7810
26.4k
        ZEND_TYPE_FULL_MASK(arg_info->type) : MAY_BE_ANY;
7811
46.6k
    }
7812
7813
53.0k
    if (is_promoted) {
7814
898
      zend_op_array *op_array = CG(active_op_array);
7815
898
      zend_class_entry *scope = op_array->scope;
7816
7817
898
      bool is_ctor =
7818
898
        scope && zend_is_constructor(op_array->function_name);
7819
898
      if (!is_ctor) {
7820
33
        zend_error_noreturn(E_COMPILE_ERROR,
7821
33
          "Cannot declare promoted property outside a constructor");
7822
33
      }
7823
865
      if ((op_array->fn_flags & ZEND_ACC_ABSTRACT)
7824
865
          || (scope->ce_flags & ZEND_ACC_INTERFACE)) {
7825
6
        zend_error_noreturn(E_COMPILE_ERROR,
7826
6
          "Cannot declare promoted property in an abstract constructor");
7827
6
      }
7828
859
      if (is_variadic) {
7829
6
        zend_error_noreturn(E_COMPILE_ERROR,
7830
6
          "Cannot declare variadic promoted property");
7831
6
      }
7832
853
      if (zend_hash_exists(&scope->properties_info, name)) {
7833
6
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s",
7834
6
          ZSTR_VAL(scope->name), ZSTR_VAL(name));
7835
6
      }
7836
847
      if (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_CALLABLE) {
7837
6
        zend_string *str = zend_type_to_string(arg_info->type);
7838
6
        zend_error_noreturn(E_COMPILE_ERROR,
7839
6
          "Property %s::$%s cannot have type %s",
7840
6
          ZSTR_VAL(scope->name), ZSTR_VAL(name), ZSTR_VAL(str));
7841
6
      }
7842
7843
841
      if (!(property_flags & ZEND_ACC_READONLY) && (scope->ce_flags & ZEND_ACC_READONLY_CLASS)) {
7844
13
        property_flags |= ZEND_ACC_READONLY;
7845
13
      }
7846
7847
      /* Recompile the type, as it has different memory management requirements. */
7848
841
      zend_type type = ZEND_TYPE_INIT_NONE(0);
7849
841
      if (type_ast) {
7850
584
        type = zend_compile_typename(type_ast);
7851
584
      }
7852
7853
      /* Don't give the property an explicit default value. For typed properties this means
7854
       * uninitialized, for untyped properties it means an implicit null default value.
7855
       * Properties with hooks get an implicit default value of undefined until inheritance,
7856
       * where it is changed to null only once we know it is not virtual. If we were to set it
7857
       * here, we couldn't verify that a true virtual property must not have an explicit
7858
       * default value. */
7859
841
      zval default_value;
7860
841
      if (ZEND_TYPE_IS_SET(type) || hooks_ast) {
7861
633
        ZVAL_UNDEF(&default_value);
7862
633
      } else {
7863
208
        if (property_flags & ZEND_ACC_READONLY) {
7864
11
          zend_error_noreturn(E_COMPILE_ERROR, "Readonly property %s::$%s must have type",
7865
11
            ZSTR_VAL(scope->name), ZSTR_VAL(name));
7866
11
        }
7867
7868
197
        ZVAL_NULL(&default_value);
7869
197
      }
7870
7871
830
      zend_string *doc_comment =
7872
830
        doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL;
7873
830
      zend_property_info *prop = zend_declare_typed_property(
7874
830
        scope, name, &default_value,
7875
830
        property_flags | (zend_property_is_virtual(scope, name, hooks_ast, property_flags) ? ZEND_ACC_VIRTUAL : 0) | ZEND_ACC_PROMOTED,
7876
830
        doc_comment, type);
7877
830
      if (hooks_ast) {
7878
113
        zend_ast_list *hooks = zend_ast_get_list(hooks_ast);
7879
113
        zend_compile_property_hooks(prop, name, type_ast, hooks);
7880
113
      }
7881
830
      if (attributes_ast) {
7882
67
        zend_compile_attributes(
7883
67
          &prop->attributes, attributes_ast, 0, ZEND_ATTRIBUTE_TARGET_PROPERTY, ZEND_ATTRIBUTE_TARGET_PARAMETER);
7884
67
      }
7885
830
    }
7886
53.0k
  }
7887
7888
  /* These are assigned at the end to avoid uninitialized memory in case of an error */
7889
48.1k
  op_array->num_args = list->children;
7890
48.1k
  op_array->arg_info = arg_infos;
7891
7892
  /* Don't count the variadic argument */
7893
48.1k
  if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
7894
614
    op_array->num_args--;
7895
614
  }
7896
48.1k
  zend_set_function_arg_flags((zend_function*)op_array);
7897
7898
100k
  for (i = 0; i < list->children; i++) {
7899
52.6k
    zend_ast *param_ast = list->child[i];
7900
52.6k
    zend_ast *hooks_ast = param_ast->child[5];
7901
52.6k
    bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
7902
52.6k
    uint32_t flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY);
7903
52.6k
    bool is_promoted = flags || hooks_ast;
7904
52.6k
    if (!is_promoted) {
7905
51.8k
      continue;
7906
51.8k
    }
7907
7908
    /* Emit $this->prop = $prop for promoted properties. */
7909
808
    zend_string *name = zend_ast_get_str(param_ast->child[1]);
7910
808
    znode name_node, value_node;
7911
808
    name_node.op_type = IS_CONST;
7912
808
    ZVAL_STR_COPY(&name_node.u.constant, name);
7913
808
    value_node.op_type = IS_CV;
7914
808
    value_node.u.op.var = lookup_cv(name);
7915
7916
808
    zend_op *opline = zend_emit_op(NULL,
7917
808
      is_ref ? ZEND_ASSIGN_OBJ_REF : ZEND_ASSIGN_OBJ, NULL, &name_node);
7918
808
    opline->extended_value = zend_alloc_cache_slots(3);
7919
808
    zend_emit_op_data(&value_node);
7920
808
  }
7921
48.1k
}
7922
/* }}} */
7923
7924
static void zend_compile_closure_binding(znode *closure, zend_op_array *op_array, zend_ast *uses_ast) /* {{{ */
7925
1.58k
{
7926
1.58k
  zend_ast_list *list = zend_ast_get_list(uses_ast);
7927
1.58k
  uint32_t i;
7928
7929
1.58k
  if (!list->children) {
7930
0
    return;
7931
0
  }
7932
7933
1.58k
  if (!op_array->static_variables) {
7934
1.58k
    op_array->static_variables = zend_new_array(8);
7935
1.58k
  }
7936
7937
5.52k
  for (i = 0; i < list->children; ++i) {
7938
3.96k
    zend_ast *var_name_ast = list->child[i];
7939
3.96k
    zend_string *var_name = zval_make_interned_string(zend_ast_get_zval(var_name_ast));
7940
3.96k
    uint32_t mode = var_name_ast->attr;
7941
3.96k
    zend_op *opline;
7942
3.96k
    zval *value;
7943
7944
3.96k
    if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) {
7945
6
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
7946
6
    }
7947
7948
3.96k
    if (zend_is_auto_global(var_name)) {
7949
6
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use auto-global as lexical variable");
7950
6
    }
7951
7952
3.95k
    value = zend_hash_add(op_array->static_variables, var_name, &EG(uninitialized_zval));
7953
3.95k
    if (!value) {
7954
14
      zend_error_noreturn_unchecked(E_COMPILE_ERROR,
7955
14
        "Cannot use variable $%S twice", var_name);
7956
14
    }
7957
7958
3.94k
    CG(zend_lineno) = zend_ast_get_lineno(var_name_ast);
7959
7960
3.94k
    opline = zend_emit_op(NULL, ZEND_BIND_LEXICAL, closure, NULL);
7961
3.94k
    opline->op2_type = IS_CV;
7962
3.94k
    opline->op2.var = lookup_cv(var_name);
7963
3.94k
    opline->extended_value =
7964
3.94k
      (uint32_t)((char*)value - (char*)op_array->static_variables->arData) | mode;
7965
3.94k
  }
7966
1.58k
}
7967
/* }}} */
7968
7969
typedef struct {
7970
  HashTable uses;
7971
  bool varvars_used;
7972
} closure_info;
7973
7974
3.00M
static void find_implicit_binds_recursively(closure_info *info, zend_ast *ast) {
7975
3.00M
  if (!ast) {
7976
2.21k
    return;
7977
2.21k
  }
7978
7979
3.00M
  if (ast->kind == ZEND_AST_VAR) {
7980
243k
    zend_ast *name_ast = ast->child[0];
7981
243k
    if (name_ast->kind == ZEND_AST_ZVAL && Z_TYPE_P(zend_ast_get_zval(name_ast)) == IS_STRING) {
7982
241k
      zend_string *name = zend_ast_get_str(name_ast);
7983
241k
      if (zend_is_auto_global(name)) {
7984
        /* These is no need to explicitly import auto-globals. */
7985
2.19k
        return;
7986
2.19k
      }
7987
7988
239k
      if (zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS))) {
7989
        /* $this does not need to be explicitly imported. */
7990
673
        return;
7991
673
      }
7992
7993
239k
      zend_hash_add_empty_element(&info->uses, name);
7994
239k
    } else {
7995
1.64k
      info->varvars_used = 1;
7996
1.64k
      find_implicit_binds_recursively(info, name_ast);
7997
1.64k
    }
7998
2.75M
  } else if (zend_ast_is_list(ast)) {
7999
95.3k
    zend_ast_list *list = zend_ast_get_list(ast);
8000
95.3k
    uint32_t i;
8001
534k
    for (i = 0; i < list->children; i++) {
8002
439k
      find_implicit_binds_recursively(info, list->child[i]);
8003
439k
    }
8004
2.66M
  } else if (ast->kind == ZEND_AST_CLOSURE) {
8005
    /* For normal closures add the use() list. */
8006
639
    zend_ast_decl *closure_ast = (zend_ast_decl *) ast;
8007
639
    zend_ast *uses_ast = closure_ast->child[1];
8008
639
    if (uses_ast) {
8009
376
      zend_ast_list *uses_list = zend_ast_get_list(uses_ast);
8010
376
      uint32_t i;
8011
2.48k
      for (i = 0; i < uses_list->children; i++) {
8012
2.10k
        zend_hash_add_empty_element(&info->uses, zend_ast_get_str(uses_list->child[i]));
8013
2.10k
      }
8014
376
    }
8015
2.66M
  } else if (ast->kind == ZEND_AST_ARROW_FUNC) {
8016
    /* For arrow functions recursively check the expression. */
8017
1.11M
    zend_ast_decl *closure_ast = (zend_ast_decl *) ast;
8018
1.11M
    find_implicit_binds_recursively(info, closure_ast->child[2]);
8019
1.54M
  } else if (!zend_ast_is_special(ast)) {
8020
1.24M
    uint32_t i, children = zend_ast_get_num_children(ast);
8021
2.66M
    for (i = 0; i < children; i++) {
8022
1.42M
      find_implicit_binds_recursively(info, ast->child[i]);
8023
1.42M
    }
8024
1.24M
  }
8025
3.00M
}
8026
8027
static void find_implicit_binds(closure_info *info, zend_ast *params_ast, zend_ast *stmt_ast)
8028
21.7k
{
8029
21.7k
  zend_ast_list *param_list = zend_ast_get_list(params_ast);
8030
21.7k
  uint32_t i;
8031
8032
21.7k
  zend_hash_init(&info->uses, param_list->children, NULL, NULL, 0);
8033
8034
21.7k
  find_implicit_binds_recursively(info, stmt_ast);
8035
8036
  /* Remove variables that are parameters */
8037
34.1k
  for (i = 0; i < param_list->children; i++) {
8038
12.3k
    zend_ast *param_ast = param_list->child[i];
8039
12.3k
    zend_hash_del(&info->uses, zend_ast_get_str(param_ast->child[1]));
8040
12.3k
  }
8041
21.7k
}
8042
8043
static void compile_implicit_lexical_binds(
8044
    closure_info *info, znode *closure, zend_op_array *op_array)
8045
21.7k
{
8046
21.7k
  zend_string *var_name;
8047
21.7k
  zend_op *opline;
8048
8049
  /* TODO We might want to use a special binding mode if varvars_used is set. */
8050
21.7k
  if (zend_hash_num_elements(&info->uses) == 0) {
8051
9.68k
    return;
8052
9.68k
  }
8053
8054
12.0k
  if (!op_array->static_variables) {
8055
12.0k
    op_array->static_variables = zend_new_array(8);
8056
12.0k
  }
8057
8058
214k
  ZEND_HASH_MAP_FOREACH_STR_KEY(&info->uses, var_name)
8059
214k
    zval *value = zend_hash_add(
8060
214k
      op_array->static_variables, var_name, &EG(uninitialized_zval));
8061
214k
    uint32_t offset = (uint32_t)((char*)value - (char*)op_array->static_variables->arData);
8062
8063
214k
    opline = zend_emit_op(NULL, ZEND_BIND_LEXICAL, closure, NULL);
8064
214k
    opline->op2_type = IS_CV;
8065
214k
    opline->op2.var = lookup_cv(var_name);
8066
214k
    opline->extended_value = offset | ZEND_BIND_IMPLICIT;
8067
214k
  ZEND_HASH_FOREACH_END();
8068
12.0k
}
8069
8070
static void zend_compile_closure_uses(zend_ast *ast) /* {{{ */
8071
1.55k
{
8072
1.55k
  zend_op_array *op_array = CG(active_op_array);
8073
1.55k
  zend_ast_list *list = zend_ast_get_list(ast);
8074
1.55k
  uint32_t i;
8075
8076
5.44k
  for (i = 0; i < list->children; ++i) {
8077
3.89k
    uint32_t mode = ZEND_BIND_EXPLICIT;
8078
3.89k
    zend_ast *var_ast = list->child[i];
8079
3.89k
    zend_string *var_name = zend_ast_get_str(var_ast);
8080
3.89k
    zval zv;
8081
3.89k
    ZVAL_NULL(&zv);
8082
8083
3.89k
    {
8084
3.89k
      int i;
8085
11.9k
      for (i = 0; i < op_array->last_var; i++) {
8086
8.02k
        if (zend_string_equals(op_array->vars[i], var_name)) {
8087
9
          zend_error_noreturn_unchecked(E_COMPILE_ERROR,
8088
9
            "Cannot use lexical variable $%S as a parameter name", var_name);
8089
9
        }
8090
8.02k
      }
8091
3.89k
    }
8092
8093
3.88k
    CG(zend_lineno) = zend_ast_get_lineno(var_ast);
8094
8095
3.88k
    if (var_ast->attr) {
8096
1.00k
      mode |= ZEND_BIND_REF;
8097
1.00k
    }
8098
8099
3.88k
    zend_compile_static_var_common(var_name, &zv, mode);
8100
3.88k
  }
8101
1.55k
}
8102
/* }}} */
8103
8104
static void zend_compile_implicit_closure_uses(closure_info *info)
8105
21.6k
{
8106
21.6k
  zend_string *var_name;
8107
233k
  ZEND_HASH_MAP_FOREACH_STR_KEY(&info->uses, var_name)
8108
233k
    zval zv;
8109
233k
    ZVAL_NULL(&zv);
8110
233k
    zend_compile_static_var_common(var_name, &zv, ZEND_BIND_IMPLICIT);
8111
233k
  ZEND_HASH_FOREACH_END();
8112
21.6k
}
8113
8114
580
static void add_stringable_interface(zend_class_entry *ce) {
8115
684
  for (uint32_t i = 0; i < ce->num_interfaces; i++) {
8116
127
    if (zend_string_equals_literal(ce->interface_names[i].lc_name, "stringable")) {
8117
      /* Interface already explicitly implemented */
8118
23
      return;
8119
23
    }
8120
127
  }
8121
8122
557
  ce->num_interfaces++;
8123
557
  ce->interface_names =
8124
557
    erealloc(ce->interface_names, sizeof(zend_class_name) * ce->num_interfaces);
8125
  // TODO: Add known interned strings instead?
8126
557
  ce->interface_names[ce->num_interfaces - 1].name =
8127
557
    ZSTR_INIT_LITERAL("Stringable", 0);
8128
557
  ce->interface_names[ce->num_interfaces - 1].lc_name =
8129
557
    ZSTR_INIT_LITERAL("stringable", 0);
8130
557
}
8131
8132
static zend_string *zend_begin_method_decl(zend_op_array *op_array, zend_string *name, bool has_body) /* {{{ */
8133
33.1k
{
8134
33.1k
  zend_class_entry *ce = CG(active_class_entry);
8135
33.1k
  bool in_interface = (ce->ce_flags & ZEND_ACC_INTERFACE) != 0;
8136
33.1k
  uint32_t fn_flags = op_array->fn_flags;
8137
8138
33.1k
  zend_string *lcname;
8139
8140
33.1k
  if (fn_flags & ZEND_ACC_READONLY) {
8141
0
    zend_error(E_COMPILE_ERROR, "Cannot use 'readonly' as method modifier");
8142
0
  }
8143
8144
33.1k
  if ((fn_flags & ZEND_ACC_PRIVATE) && (fn_flags & ZEND_ACC_FINAL) && !zend_is_constructor(name)) {
8145
265
    zend_error(E_COMPILE_WARNING, "Private methods cannot be final as they are never overridden by other classes");
8146
265
  }
8147
8148
33.1k
  if ((fn_flags & ZEND_ACC_ABSTRACT)
8149
33.1k
   && !(ce->ce_flags & (ZEND_ACC_EXPLICIT_ABSTRACT_CLASS|ZEND_ACC_TRAIT))) {
8150
    // Don't say that the class should be declared abstract if it is
8151
    // anonymous or an enum and can't be abstract
8152
31
    if (ce->ce_flags & ZEND_ACC_ANON_CLASS) {
8153
6
      zend_error_noreturn(E_COMPILE_ERROR, "Anonymous class method %s() must not be abstract",
8154
6
        ZSTR_VAL(name));
8155
25
    } else if (ce->ce_flags & (ZEND_ACC_ENUM|ZEND_ACC_INTERFACE)) {
8156
12
      zend_error_noreturn(E_COMPILE_ERROR, "%s method %s::%s() must not be abstract",
8157
12
        zend_get_object_type_case(ce, true), ZSTR_VAL(ce->name), ZSTR_VAL(name));
8158
13
    } else {
8159
13
      zend_error_noreturn(E_COMPILE_ERROR, "Class %s declares abstract method %s() and must therefore be declared abstract",
8160
13
        ZSTR_VAL(ce->name), ZSTR_VAL(name));
8161
13
    }
8162
31
  }
8163
8164
33.1k
  if (in_interface) {
8165
888
    if (!(fn_flags & ZEND_ACC_PUBLIC)) {
8166
1
      zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method "
8167
1
        "%s::%s() must be public", ZSTR_VAL(ce->name), ZSTR_VAL(name));
8168
1
    }
8169
887
    if (fn_flags & ZEND_ACC_FINAL) {
8170
8
      zend_error_noreturn(E_COMPILE_ERROR, "Interface method "
8171
8
        "%s::%s() must not be final", ZSTR_VAL(ce->name), ZSTR_VAL(name));
8172
8
    }
8173
879
    op_array->fn_flags |= ZEND_ACC_ABSTRACT;
8174
879
  }
8175
8176
33.0k
  if (op_array->fn_flags & ZEND_ACC_ABSTRACT) {
8177
1.54k
    if ((op_array->fn_flags & ZEND_ACC_PRIVATE) && !(ce->ce_flags & ZEND_ACC_TRAIT)) {
8178
6
      zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private",
8179
6
        in_interface ? "Interface" : "Abstract", ZSTR_VAL(ce->name), ZSTR_VAL(name));
8180
6
    }
8181
8182
1.54k
    if (has_body) {
8183
12
      zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body",
8184
12
        in_interface ? "Interface" : "Abstract", ZSTR_VAL(ce->name), ZSTR_VAL(name));
8185
12
    }
8186
8187
1.53k
    ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
8188
31.5k
  } else if (!has_body) {
8189
7
    zend_error_noreturn(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body",
8190
7
      ZSTR_VAL(ce->name), ZSTR_VAL(name));
8191
7
  }
8192
8193
33.0k
  op_array->scope = ce;
8194
33.0k
  op_array->function_name = zend_string_copy(name);
8195
8196
33.0k
  lcname = zend_string_tolower(name);
8197
33.0k
  lcname = zend_new_interned_string(lcname);
8198
8199
33.0k
  if (zend_hash_add_ptr(&ce->function_table, lcname, op_array) == NULL) {
8200
46
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()",
8201
46
      ZSTR_VAL(ce->name), ZSTR_VAL(name));
8202
46
  }
8203
8204
33.0k
  zend_add_magic_method(ce, (zend_function *) op_array, lcname);
8205
33.0k
  if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)
8206
33.0k
      && !(ce->ce_flags & ZEND_ACC_TRAIT)) {
8207
580
    add_stringable_interface(ce);
8208
580
  }
8209
8210
33.0k
  return lcname;
8211
33.0k
}
8212
/* }}} */
8213
8214
40.9k
static uint32_t zend_add_dynamic_func_def(zend_op_array *def) {
8215
40.9k
  zend_op_array *op_array = CG(active_op_array);
8216
40.9k
  uint32_t def_offset = op_array->num_dynamic_func_defs++;
8217
40.9k
  op_array->dynamic_func_defs = erealloc(
8218
40.9k
    op_array->dynamic_func_defs, op_array->num_dynamic_func_defs * sizeof(zend_op_array *));
8219
40.9k
  op_array->dynamic_func_defs[def_offset] = def;
8220
40.9k
  return def_offset;
8221
40.9k
}
8222
8223
enum func_decl_level {
8224
  FUNC_DECL_LEVEL_TOPLEVEL,
8225
  FUNC_DECL_LEVEL_NESTED,
8226
  FUNC_DECL_LEVEL_CONSTEXPR,
8227
};
8228
8229
static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl, enum func_decl_level level) /* {{{ */
8230
56.3k
{
8231
56.3k
  zend_string *unqualified_name, *name, *lcname;
8232
56.3k
  zend_op *opline;
8233
8234
56.3k
  if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
8235
38.6k
    zend_string *filename = op_array->filename;
8236
38.6k
    uint32_t start_lineno = decl->start_lineno;
8237
8238
38.6k
    zend_string *class = zend_empty_string;
8239
38.6k
    zend_string *separator = zend_empty_string;
8240
38.6k
    zend_string *function = filename;
8241
38.6k
    char *parens = "";
8242
8243
38.6k
    if (CG(active_op_array) && CG(active_op_array)->function_name) {
8244
22.7k
      if (CG(active_op_array)->fn_flags & ZEND_ACC_CLOSURE) {
8245
        /* If the parent function is a closure, don't redundantly
8246
         * add the classname and parentheses.
8247
         */
8248
21.3k
        function = CG(active_op_array)->function_name;
8249
21.3k
      } else {
8250
1.42k
        function = CG(active_op_array)->function_name;
8251
1.42k
        parens = "()";
8252
8253
1.42k
        if (CG(active_class_entry) && CG(active_class_entry)->name) {
8254
908
          class = CG(active_class_entry)->name;
8255
908
          separator = ZSTR_KNOWN(ZEND_STR_PAAMAYIM_NEKUDOTAYIM);
8256
908
        }
8257
1.42k
      }
8258
22.7k
    }
8259
8260
38.6k
    unqualified_name = zend_strpprintf_unchecked(
8261
38.6k
      0,
8262
38.6k
      "{closure:%S%S%S%s:%" PRIu32 "}",
8263
38.6k
      class,
8264
38.6k
      separator,
8265
38.6k
      function,
8266
38.6k
      parens,
8267
38.6k
      start_lineno
8268
38.6k
    );
8269
8270
38.6k
    op_array->function_name = name = unqualified_name;
8271
38.6k
  } else {
8272
17.6k
    unqualified_name = decl->name;
8273
17.6k
    op_array->function_name = name = zend_prefix_with_ns(unqualified_name);
8274
17.6k
  }
8275
8276
56.3k
  lcname = zend_string_tolower(name);
8277
8278
56.3k
  if (FC(imports_function)) {
8279
231
    zend_string *import_name =
8280
231
      zend_hash_find_ptr_lc(FC(imports_function), unqualified_name);
8281
231
    if (import_name && !zend_string_equals_ci(lcname, import_name)) {
8282
14
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare function %s() (previously declared as local import)",
8283
14
        ZSTR_VAL(name));
8284
14
    }
8285
231
  }
8286
8287
56.3k
  if (zend_string_equals_literal(lcname, "__autoload")) {
8288
1
    zend_error_noreturn(E_COMPILE_ERROR,
8289
1
      "__autoload() is no longer supported, use spl_autoload_register() instead");
8290
1
  }
8291
8292
56.3k
  if (zend_string_equals_literal_ci(unqualified_name, "assert")) {
8293
6
    zend_error(E_COMPILE_ERROR,
8294
6
      "Defining a custom assert() function is not allowed, "
8295
6
      "as the function has special semantics");
8296
6
  }
8297
8298
56.3k
  zend_register_seen_symbol(lcname, ZEND_SYMBOL_FUNCTION);
8299
56.3k
  switch (level) {
8300
40.9k
    case FUNC_DECL_LEVEL_NESTED: {
8301
40.9k
      uint32_t func_ref = zend_add_dynamic_func_def(op_array);
8302
40.9k
      if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
8303
38.5k
        opline = zend_emit_op_tmp(result, ZEND_DECLARE_LAMBDA_FUNCTION, NULL, NULL);
8304
38.5k
        opline->op2.num = func_ref;
8305
38.5k
      } else {
8306
2.39k
        opline = get_next_op();
8307
2.39k
        opline->opcode = ZEND_DECLARE_FUNCTION;
8308
2.39k
        opline->op1_type = IS_CONST;
8309
2.39k
        LITERAL_STR(opline->op1, zend_string_copy(lcname));
8310
2.39k
        opline->op2.num = func_ref;
8311
2.39k
      }
8312
40.9k
      break;
8313
0
    }
8314
73
    case FUNC_DECL_LEVEL_CONSTEXPR:
8315
15.3k
    case FUNC_DECL_LEVEL_TOPLEVEL:
8316
      /* Nothing to do. */
8317
15.3k
      break;
8318
56.3k
  }
8319
56.2k
  return lcname;
8320
56.3k
}
8321
/* }}} */
8322
8323
static zend_op_array *zend_compile_func_decl_ex(
8324
  znode *result, zend_ast *ast, enum func_decl_level level,
8325
  zend_string *property_info_name,
8326
  zend_property_hook_kind hook_kind
8327
94.5k
) {
8328
94.5k
  zend_ast_decl *decl = (zend_ast_decl *) ast;
8329
94.5k
  zend_ast *params_ast = decl->child[0];
8330
94.5k
  zend_ast *uses_ast = decl->child[1];
8331
94.5k
  zend_ast *stmt_ast = decl->child[2];
8332
94.5k
  zend_ast *return_type_ast = decl->child[3];
8333
94.5k
  bool is_method = decl->kind == ZEND_AST_METHOD;
8334
94.5k
  zend_string *lcname = NULL;
8335
94.5k
  bool is_hook = decl->kind == ZEND_AST_PROPERTY_HOOK;
8336
8337
94.5k
  zend_class_entry *orig_class_entry = CG(active_class_entry);
8338
94.5k
  zend_op_array *orig_op_array = CG(active_op_array);
8339
94.5k
  zend_op_array *op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
8340
94.5k
  zend_oparray_context orig_oparray_context;
8341
94.5k
  closure_info info;
8342
94.5k
  memset(&info, 0, sizeof(closure_info));
8343
8344
94.5k
  init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE);
8345
8346
94.5k
  if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
8347
0
    op_array->fn_flags |= ZEND_ACC_PRELOADED;
8348
0
  }
8349
8350
94.5k
  op_array->fn_flags |= (orig_op_array->fn_flags & ZEND_ACC_STRICT_TYPES);
8351
94.5k
  op_array->fn_flags |= decl->flags;
8352
94.5k
  op_array->line_start = decl->start_lineno;
8353
94.5k
  op_array->line_end = decl->end_lineno;
8354
94.5k
  if (decl->doc_comment) {
8355
288
    op_array->doc_comment = zend_string_copy(decl->doc_comment);
8356
288
  }
8357
8358
94.5k
  if (decl->kind == ZEND_AST_CLOSURE || decl->kind == ZEND_AST_ARROW_FUNC) {
8359
38.6k
    op_array->fn_flags |= ZEND_ACC_CLOSURE;
8360
38.6k
  }
8361
8362
94.5k
  if (is_hook) {
8363
5.11k
    zend_class_entry *ce = CG(active_class_entry);
8364
5.11k
    op_array->scope = ce;
8365
5.11k
    op_array->function_name = zend_string_copy(decl->name);
8366
89.4k
  } else if (is_method) {
8367
33.1k
    bool has_body = stmt_ast != NULL;
8368
33.1k
    lcname = zend_begin_method_decl(op_array, decl->name, has_body);
8369
56.3k
  } else {
8370
56.3k
    lcname = zend_begin_func_decl(result, op_array, decl, level);
8371
56.3k
    if (decl->kind == ZEND_AST_ARROW_FUNC) {
8372
21.7k
      find_implicit_binds(&info, params_ast, stmt_ast);
8373
21.7k
      compile_implicit_lexical_binds(&info, result, op_array);
8374
34.5k
    } else if (uses_ast) {
8375
1.58k
      zend_compile_closure_binding(result, op_array, uses_ast);
8376
1.58k
    }
8377
56.3k
  }
8378
8379
94.5k
  CG(active_op_array) = op_array;
8380
8381
94.5k
  if (decl->child[4]) {
8382
4.75k
    int target = ZEND_ATTRIBUTE_TARGET_FUNCTION;
8383
8384
4.75k
    if (is_method || is_hook) {
8385
540
      target = ZEND_ATTRIBUTE_TARGET_METHOD;
8386
540
    }
8387
8388
4.75k
    zend_compile_attributes(&op_array->attributes, decl->child[4], 0, target, 0);
8389
8390
4.75k
    zend_attribute *override_attribute = zend_get_attribute_str(
8391
4.75k
      op_array->attributes,
8392
4.75k
      "override",
8393
4.75k
      sizeof("override")-1
8394
4.75k
    );
8395
8396
4.75k
    if (override_attribute) {
8397
155
      op_array->fn_flags |= ZEND_ACC_OVERRIDE;
8398
155
    }
8399
8400
4.75k
    zend_attribute *deprecated_attribute = zend_get_attribute_str(
8401
4.75k
      op_array->attributes,
8402
4.75k
      "deprecated",
8403
4.75k
      sizeof("deprecated")-1
8404
4.75k
    );
8405
8406
4.75k
    if (deprecated_attribute) {
8407
294
      op_array->fn_flags |= ZEND_ACC_DEPRECATED;
8408
294
    }
8409
8410
4.75k
    zend_attribute *nodiscard_attribute = zend_get_attribute_str(
8411
4.75k
      op_array->attributes,
8412
4.75k
      "nodiscard",
8413
4.75k
      sizeof("nodiscard")-1
8414
4.75k
    );
8415
8416
4.75k
    if (nodiscard_attribute) {
8417
231
      op_array->fn_flags |= ZEND_ACC_NODISCARD;
8418
231
    }
8419
4.75k
  }
8420
8421
  /* Do not leak the class scope into free standing functions, even if they are dynamically
8422
   * defined inside a class method. This is necessary for correct handling of magic constants.
8423
   * For example __CLASS__ should always be "" inside a free standing function. */
8424
94.5k
  if (decl->kind == ZEND_AST_FUNC_DECL) {
8425
17.6k
    CG(active_class_entry) = NULL;
8426
17.6k
  }
8427
8428
94.5k
  if (level == FUNC_DECL_LEVEL_TOPLEVEL) {
8429
15.2k
    op_array->fn_flags |= ZEND_ACC_TOP_LEVEL;
8430
15.2k
  }
8431
8432
94.5k
  zend_oparray_context_begin(&orig_oparray_context, op_array);
8433
94.5k
  CG(context).active_property_info_name = property_info_name;
8434
94.5k
  CG(context).active_property_hook_kind = hook_kind;
8435
8436
94.5k
  {
8437
    /* Push a separator to the loop variable stack */
8438
94.5k
    zend_loop_var dummy_var;
8439
94.5k
    dummy_var.opcode = ZEND_RETURN;
8440
8441
94.5k
    zend_stack_push(&CG(loop_var_stack), (void *) &dummy_var);
8442
94.5k
  }
8443
8444
94.5k
  zend_compile_params(params_ast, return_type_ast,
8445
94.5k
    is_method && zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME) ? IS_STRING : 0);
8446
94.5k
  if (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) {
8447
4.55k
    zend_mark_function_as_generator();
8448
4.55k
    zend_emit_op(NULL, ZEND_GENERATOR_CREATE, NULL, NULL);
8449
4.55k
  }
8450
94.5k
  if (decl->kind == ZEND_AST_ARROW_FUNC) {
8451
21.6k
    zend_compile_implicit_closure_uses(&info);
8452
21.6k
    zend_hash_destroy(&info.uses);
8453
72.8k
  } else if (uses_ast) {
8454
1.55k
    zend_compile_closure_uses(uses_ast);
8455
1.55k
  }
8456
8457
94.5k
  if (ast->kind == ZEND_AST_ARROW_FUNC && decl->child[2]->kind != ZEND_AST_RETURN) {
8458
19.0k
    bool needs_return = true;
8459
19.0k
    if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
8460
1.81k
      zend_arg_info *return_info = CG(active_op_array)->arg_info - 1;
8461
1.81k
      needs_return = !ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_NEVER);
8462
1.81k
    }
8463
19.0k
    if (needs_return) {
8464
18.7k
      stmt_ast = zend_ast_create(ZEND_AST_RETURN, stmt_ast);
8465
18.7k
      decl->child[2] = stmt_ast;
8466
18.7k
    }
8467
19.0k
  }
8468
8469
94.5k
  if (op_array->fn_flags & ZEND_ACC_NODISCARD) {
8470
231
    if (is_hook) {
8471
6
      zend_error_noreturn(E_COMPILE_ERROR, "#[\\NoDiscard] is not supported for property hooks");
8472
6
    }
8473
8474
225
    if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
8475
144
      zend_arg_info *return_info = CG(active_op_array)->arg_info - 1;
8476
144
      if (ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_VOID)) {
8477
6
        zend_error_noreturn(E_COMPILE_ERROR,
8478
6
          "A void %s does not return a value, but #[\\NoDiscard] requires a return value",
8479
6
          CG(active_class_entry) != NULL ? "method" : "function");
8480
6
      }
8481
8482
138
      if (ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_NEVER)) {
8483
6
        zend_error_noreturn(E_COMPILE_ERROR,
8484
6
          "A never returning %s does not return a value, but #[\\NoDiscard] requires a return value",
8485
6
          CG(active_class_entry) != NULL ? "method" : "function");
8486
6
      }
8487
138
    }
8488
225
  }
8489
8490
94.5k
  zend_compile_stmt(stmt_ast);
8491
8492
94.5k
  if (is_method) {
8493
32.7k
    CG(zend_lineno) = decl->start_lineno;
8494
32.7k
    zend_check_magic_method_implementation(
8495
32.7k
      CG(active_class_entry), (zend_function *) op_array, lcname, E_COMPILE_ERROR);
8496
61.7k
  } else if (level == FUNC_DECL_LEVEL_TOPLEVEL) {
8497
    /* Only register the function after a successful compile */
8498
14.7k
    if (UNEXPECTED(zend_hash_add_ptr(CG(function_table), lcname, op_array) == NULL)) {
8499
102
      CG(zend_lineno) = decl->start_lineno;
8500
102
      do_bind_function_error(lcname, op_array, true);
8501
102
    }
8502
14.7k
  }
8503
8504
  /* put the implicit return on the really last line */
8505
94.4k
  CG(zend_lineno) = decl->end_lineno;
8506
8507
94.4k
  zend_do_extended_stmt();
8508
94.4k
  zend_emit_final_return(0);
8509
8510
94.4k
  pass_two(CG(active_op_array));
8511
94.4k
  zend_oparray_context_end(&orig_oparray_context);
8512
8513
  /* Pop the loop variable stack separator */
8514
94.4k
  zend_stack_del_top(&CG(loop_var_stack));
8515
8516
94.4k
  if (level == FUNC_DECL_LEVEL_TOPLEVEL) {
8517
14.5k
    zend_observer_function_declared_notify(op_array, lcname);
8518
14.5k
  }
8519
8520
94.4k
  if (lcname != NULL) {
8521
87.1k
    zend_string_release_ex(lcname, 0);
8522
87.1k
  }
8523
8524
94.4k
  CG(active_op_array) = orig_op_array;
8525
94.4k
  CG(active_class_entry) = orig_class_entry;
8526
8527
94.4k
  return op_array;
8528
94.5k
}
8529
8530
static zend_op_array *zend_compile_func_decl(znode *result, zend_ast *ast, enum func_decl_level level)
8531
89.4k
{
8532
89.4k
  return zend_compile_func_decl_ex(result, ast, level, /* property_info */ NULL, (zend_property_hook_kind)-1);
8533
89.4k
}
8534
8535
5.97k
zend_property_hook_kind zend_get_property_hook_kind_from_name(zend_string *name) {
8536
5.97k
  if (zend_string_equals_literal_ci(name, "get")) {
8537
3.77k
    return ZEND_PROPERTY_HOOK_GET;
8538
3.77k
  } else if (zend_string_equals_literal_ci(name, "set")) {
8539
2.03k
    return ZEND_PROPERTY_HOOK_SET;
8540
2.03k
  } else {
8541
169
    return (zend_property_hook_kind)-1;
8542
169
  }
8543
5.97k
}
8544
8545
static void zend_compile_property_hooks(
8546
    zend_property_info *prop_info, zend_string *prop_name,
8547
    zend_ast *prop_type_ast, zend_ast_list *hooks)
8548
4.43k
{
8549
4.43k
  zend_class_entry *ce = CG(active_class_entry);
8550
8551
4.43k
  if (prop_info->flags & ZEND_ACC_READONLY) {
8552
16
    zend_error_noreturn(E_COMPILE_ERROR, "Hooked properties cannot be readonly");
8553
16
  }
8554
8555
4.42k
  if (hooks->children == 0) {
8556
14
    zend_error_noreturn(E_COMPILE_ERROR, "Property hook list must not be empty");
8557
14
  }
8558
8559
9.47k
  for (uint32_t i = 0; i < hooks->children; i++) {
8560
5.39k
    zend_ast_decl *hook = (zend_ast_decl *) hooks->child[i];
8561
5.39k
    zend_string *name = hook->name;
8562
5.39k
    zend_ast *stmt_ast = hook->child[2];
8563
5.39k
    zend_ast **return_type_ast_ptr = NULL;
8564
5.39k
    zend_ast **value_type_ast_ptr = NULL;
8565
5.39k
    CG(zend_lineno) = hook->start_lineno;
8566
8567
    /* Non-private hooks are always public. This avoids having to copy the hook when inheriting
8568
     * hooks from protected properties to public ones. */
8569
5.39k
    uint32_t hook_visibility = (prop_info->flags & ZEND_ACC_PPP_MASK) != ZEND_ACC_PRIVATE ? ZEND_ACC_PUBLIC : ZEND_ACC_PRIVATE;
8570
5.39k
    hook->flags |= hook_visibility;
8571
8572
5.39k
    if (prop_info->flags & ZEND_ACC_STATIC) {
8573
30
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare hooks for static property");
8574
30
    }
8575
5.36k
    if ((hook->flags & ZEND_ACC_FINAL) && (hook->flags & ZEND_ACC_PRIVATE)) {
8576
6
      zend_error_noreturn(E_COMPILE_ERROR, "Property hook cannot be both final and private");
8577
6
    }
8578
5.36k
    if ((ce->ce_flags & ZEND_ACC_INTERFACE)
8579
5.36k
     || ((prop_info->flags & ZEND_ACC_ABSTRACT) && !stmt_ast)) {
8580
1.00k
      hook->flags |= ZEND_ACC_ABSTRACT;
8581
8582
1.00k
      if (stmt_ast) {
8583
7
        zend_error_noreturn(E_COMPILE_ERROR, "Abstract property hook cannot have body");
8584
7
      }
8585
998
      if (hook->flags & ZEND_ACC_PRIVATE) {
8586
6
        zend_error_noreturn(E_COMPILE_ERROR,
8587
6
          "Property hook cannot be both abstract and private");
8588
6
      }
8589
992
      if (hook->flags & ZEND_ACC_FINAL) {
8590
8
        zend_error_noreturn(E_COMPILE_ERROR, "Property hook cannot be both abstract and final");
8591
8
      }
8592
4.35k
    } else if (!stmt_ast) {
8593
28
      zend_error_noreturn(E_COMPILE_ERROR, "Non-abstract property hook must have a body");
8594
28
    }
8595
8596
5.31k
    zend_property_hook_kind hook_kind = zend_get_property_hook_kind_from_name(name);
8597
5.31k
    if (hook_kind == (zend_property_hook_kind)-1) {
8598
169
      zend_error_noreturn(E_COMPILE_ERROR,
8599
169
        "Unknown hook \"%s\" for property %s::$%s, expected \"get\" or \"set\"",
8600
169
        ZSTR_VAL(name), ZSTR_VAL(ce->name), ZSTR_VAL(prop_name));
8601
169
    }
8602
8603
5.14k
    if (stmt_ast && stmt_ast->kind == ZEND_AST_PROPERTY_HOOK_SHORT_BODY) {
8604
1.73k
      stmt_ast = stmt_ast->child[0];
8605
1.73k
      if (hook_kind == ZEND_PROPERTY_HOOK_GET) {
8606
1.43k
        stmt_ast = zend_ast_create(ZEND_AST_RETURN, stmt_ast);
8607
1.43k
      } else {
8608
304
        ZEND_ASSERT(hook_kind == ZEND_PROPERTY_HOOK_SET);
8609
304
        stmt_ast = zend_ast_create(ZEND_AST_ASSIGN,
8610
304
          zend_ast_create(ZEND_AST_PROP,
8611
304
            zend_ast_create(ZEND_AST_VAR, zend_ast_create_zval_from_str(ZSTR_KNOWN(ZEND_STR_THIS))),
8612
304
            zend_ast_create_zval_from_str(zend_copy_unmangled_prop_name(prop_info->name))),
8613
304
          stmt_ast);
8614
304
      }
8615
1.73k
      stmt_ast = zend_ast_create_list(1, ZEND_AST_STMT_LIST, stmt_ast);
8616
1.73k
      hook->child[2] = stmt_ast;
8617
1.73k
    }
8618
8619
5.14k
    if (hook_kind == ZEND_PROPERTY_HOOK_GET) {
8620
3.24k
      if (hook->child[0]) {
8621
6
        zend_error_noreturn(E_COMPILE_ERROR, "get hook of property %s::$%s must not have a parameter list",
8622
6
          ZSTR_VAL(ce->name), ZSTR_VAL(prop_name));
8623
6
      }
8624
8625
3.23k
      hook->child[0] = zend_ast_create_list(0, ZEND_AST_PARAM_LIST);
8626
8627
3.23k
      return_type_ast_ptr = &hook->child[3];
8628
3.23k
      *return_type_ast_ptr = prop_type_ast;
8629
3.23k
    } else if (hook_kind == ZEND_PROPERTY_HOOK_SET) {
8630
1.90k
      if (hook->child[0]) {
8631
183
        zend_ast_list *param_list = zend_ast_get_list(hook->child[0]);
8632
183
        if (param_list->children != 1) {
8633
1
          zend_error_noreturn(E_COMPILE_ERROR, "%s hook of property %s::$%s must accept exactly one parameters",
8634
1
            ZSTR_VAL(name), ZSTR_VAL(ce->name), ZSTR_VAL(prop_name));
8635
1
        }
8636
182
        zend_ast *value_param_ast = param_list->child[0];
8637
182
        if (value_param_ast->attr & ZEND_PARAM_REF) {
8638
6
          zend_error_noreturn(E_COMPILE_ERROR, "Parameter $%s of %s hook %s::$%s must not be pass-by-reference",
8639
6
            ZSTR_VAL(zend_ast_get_str(value_param_ast->child[1])), ZSTR_VAL(name), ZSTR_VAL(ce->name), ZSTR_VAL(prop_name));
8640
6
        }
8641
176
        if (value_param_ast->attr & ZEND_PARAM_VARIADIC) {
8642
6
          zend_error_noreturn(E_COMPILE_ERROR, "Parameter $%s of %s hook %s::$%s must not be variadic",
8643
6
            ZSTR_VAL(zend_ast_get_str(value_param_ast->child[1])), ZSTR_VAL(name), ZSTR_VAL(ce->name), ZSTR_VAL(prop_name));
8644
6
        }
8645
170
        if (value_param_ast->child[2]) {
8646
6
          zend_error_noreturn(E_COMPILE_ERROR, "Parameter $%s of %s hook %s::$%s must not have a default value",
8647
6
            ZSTR_VAL(zend_ast_get_str(value_param_ast->child[1])), ZSTR_VAL(name), ZSTR_VAL(ce->name), ZSTR_VAL(prop_name));
8648
6
        }
8649
164
        if ((prop_type_ast != NULL) != (value_param_ast->child[0] != NULL)) {
8650
6
          zend_hooked_property_variance_error_ex(zend_ast_get_str(value_param_ast->child[1]), ce->name, prop_info->name);
8651
6
        }
8652
1.71k
      } else {
8653
1.71k
        zend_ast *param_name_ast = zend_ast_create_zval_from_str(ZSTR_KNOWN(ZEND_STR_VALUE));
8654
1.71k
        zend_ast *param = zend_ast_create(
8655
1.71k
          ZEND_AST_PARAM, prop_type_ast, param_name_ast,
8656
1.71k
          /* expr */ NULL, /* doc_comment */ NULL, /* attributes */ NULL,
8657
1.71k
          /* hooks */ NULL);
8658
1.71k
        value_type_ast_ptr = &param->child[0];
8659
1.71k
        hook->child[0] = zend_ast_create_list(1, ZEND_AST_PARAM_LIST, param);
8660
1.71k
      }
8661
1.87k
      zend_ast *return_type = zend_ast_create_zval_from_str(ZSTR_KNOWN(ZEND_STR_VOID));
8662
1.87k
      return_type->attr = ZEND_NAME_NOT_FQ;
8663
1.87k
      hook->child[3] = return_type;
8664
1.87k
    } else {
8665
0
      ZEND_UNREACHABLE();
8666
0
    }
8667
8668
5.11k
    hook->name = zend_strpprintf(0, "$%s::%s", ZSTR_VAL(prop_name), ZSTR_VAL(name));
8669
8670
5.11k
    zend_function *func = (zend_function *) zend_compile_func_decl_ex(
8671
5.11k
      NULL, (zend_ast *) hook, FUNC_DECL_LEVEL_NESTED, prop_info->name, hook_kind);
8672
8673
5.11k
    func->common.prop_info = prop_info;
8674
8675
5.11k
    if (!prop_info->hooks) {
8676
4.10k
      prop_info->hooks = zend_arena_alloc(&CG(arena), ZEND_PROPERTY_HOOK_STRUCT_SIZE);
8677
4.10k
      memset(prop_info->hooks, 0, ZEND_PROPERTY_HOOK_STRUCT_SIZE);
8678
4.10k
    }
8679
8680
5.11k
    if (prop_info->hooks[hook_kind]) {
8681
42
      zend_error_noreturn(E_COMPILE_ERROR,
8682
42
        "Cannot redeclare property hook \"%s\"", ZSTR_VAL(name));
8683
42
    }
8684
5.07k
    prop_info->hooks[hook_kind] = func;
8685
8686
5.07k
    if (hook_kind == ZEND_PROPERTY_HOOK_SET) {
8687
1.83k
      switch (zend_verify_property_hook_variance(prop_info, func)) {
8688
1.76k
        case INHERITANCE_SUCCESS:
8689
1.76k
          break;
8690
63
        case INHERITANCE_UNRESOLVED:
8691
63
          ce->num_hooked_prop_variance_checks++;
8692
63
          break;
8693
8
        case INHERITANCE_ERROR:
8694
8
          zend_hooked_property_variance_error(prop_info);
8695
0
        case INHERITANCE_WARNING:
8696
0
          ZEND_UNREACHABLE();
8697
1.83k
      }
8698
1.83k
    }
8699
8700
5.06k
    zend_string_release(name);
8701
    /* Un-share type ASTs to avoid double-frees of zval nodes. */
8702
5.06k
    if (return_type_ast_ptr) {
8703
3.17k
      *return_type_ast_ptr = NULL;
8704
3.17k
    }
8705
5.06k
    if (value_type_ast_ptr) {
8706
1.68k
      *value_type_ast_ptr = NULL;
8707
1.68k
    }
8708
5.06k
  }
8709
8710
4.07k
  ce->num_hooked_props++;
8711
8712
  /* See zend_link_hooked_object_iter(). */
8713
4.07k
#ifndef ZEND_OPCACHE_SHM_REATTACHMENT
8714
4.07k
  if (!ce->get_iterator) {
8715
    /* Will be removed again, in case of Iterator or IteratorAggregate. */
8716
3.05k
    ce->get_iterator = zend_hooked_object_get_iterator;
8717
3.05k
  }
8718
4.07k
#endif
8719
8720
4.07k
  if (!prop_info->ce->parent_name) {
8721
2.53k
    zend_verify_hooked_property(ce, prop_info, prop_name);
8722
2.53k
  }
8723
4.07k
}
8724
8725
static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags, zend_ast *attr_ast) /* {{{ */
8726
22.0k
{
8727
22.0k
  zend_ast_list *list = zend_ast_get_list(ast);
8728
22.0k
  zend_class_entry *ce = CG(active_class_entry);
8729
22.0k
  uint32_t i, children = list->children;
8730
8731
22.0k
  if (ce->ce_flags & ZEND_ACC_ENUM) {
8732
14
    zend_error_noreturn(E_COMPILE_ERROR, "Enum %s cannot include properties", ZSTR_VAL(ce->name));
8733
14
  }
8734
8735
22.0k
  if ((flags & ZEND_ACC_FINAL) && (flags & ZEND_ACC_PRIVATE)) {
8736
6
    zend_error_noreturn(E_COMPILE_ERROR, "Property cannot be both final and private");
8737
6
  }
8738
8739
22.0k
  if (ce->ce_flags & ZEND_ACC_INTERFACE) {
8740
360
    if (flags & ZEND_ACC_FINAL) {
8741
6
      zend_error_noreturn(E_COMPILE_ERROR, "Property in interface cannot be final");
8742
6
    }
8743
354
    if (flags & (ZEND_ACC_PROTECTED|ZEND_ACC_PRIVATE)) {
8744
14
      zend_error_noreturn(E_COMPILE_ERROR, "Property in interface cannot be protected or private");
8745
14
    }
8746
340
    if (flags & ZEND_ACC_ABSTRACT) {
8747
6
      zend_error_noreturn(E_COMPILE_ERROR,
8748
6
        "Property in interface cannot be explicitly abstract. "
8749
6
        "All interface members are implicitly abstract");
8750
6
    }
8751
334
    flags |= ZEND_ACC_ABSTRACT;
8752
334
  }
8753
8754
44.0k
  for (i = 0; i < children; ++i) {
8755
22.2k
    zend_property_info *info;
8756
22.2k
    zend_ast *prop_ast = list->child[i];
8757
22.2k
    zend_ast *name_ast = prop_ast->child[0];
8758
22.2k
    zend_ast **value_ast_ptr = &prop_ast->child[1];
8759
22.2k
    zend_ast *doc_comment_ast = prop_ast->child[2];
8760
22.2k
    zend_ast *hooks_ast = prop_ast->child[3];
8761
22.2k
    zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast));
8762
22.2k
    zend_string *doc_comment = NULL;
8763
22.2k
    zval value_zv;
8764
22.2k
    zend_type type = ZEND_TYPE_INIT_NONE(0);
8765
22.2k
    flags |= zend_property_is_virtual(ce, name, hooks_ast, flags) ? ZEND_ACC_VIRTUAL : 0;
8766
8767
22.2k
    zend_string *old_active_property_info_name = CG(context).active_property_info_name;
8768
22.2k
    CG(context).active_property_info_name = name;
8769
8770
22.2k
    if (!hooks_ast) {
8771
17.9k
      if (ce->ce_flags & ZEND_ACC_INTERFACE) {
8772
1
        zend_error_noreturn(E_COMPILE_ERROR,
8773
1
          "Interfaces may only include hooked properties");
8774
1
      }
8775
17.9k
      if (flags & ZEND_ACC_ABSTRACT) {
8776
8
        zend_error_noreturn(E_COMPILE_ERROR,
8777
8
          "Only hooked properties may be declared abstract");
8778
8
      }
8779
17.9k
    }
8780
22.2k
    if ((flags & ZEND_ACC_ABSTRACT)) {
8781
954
      ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
8782
954
    }
8783
8784
22.2k
    if (type_ast) {
8785
9.76k
      type = zend_compile_typename(type_ast);
8786
8787
9.76k
      if (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_VOID|MAY_BE_NEVER|MAY_BE_CALLABLE)) {
8788
6
        zend_string *str = zend_type_to_string(type);
8789
6
        zend_error_noreturn(E_COMPILE_ERROR,
8790
6
          "Property %s::$%s cannot have type %s",
8791
6
          ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(str));
8792
6
      }
8793
9.76k
    }
8794
8795
    /* Doc comment has been appended as last element in ZEND_AST_PROP_ELEM ast */
8796
22.2k
    if (doc_comment_ast) {
8797
396
      doc_comment = zend_string_copy(zend_ast_get_str(doc_comment_ast));
8798
396
    }
8799
8800
22.2k
    if (zend_hash_exists(&ce->properties_info, name)) {
8801
44
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s",
8802
44
        ZSTR_VAL(ce->name), ZSTR_VAL(name));
8803
44
    }
8804
8805
22.2k
    if (*value_ast_ptr) {
8806
7.66k
      zend_const_expr_to_zval(&value_zv, value_ast_ptr, /* allow_dynamic */ false);
8807
8808
7.66k
      if (ZEND_TYPE_IS_SET(type) && !Z_CONSTANT(value_zv)
8809
7.66k
          && !zend_is_valid_default_value(type, &value_zv)) {
8810
87
        zend_string *str = zend_type_to_string(type);
8811
87
        if (Z_TYPE(value_zv) == IS_NULL && !ZEND_TYPE_IS_INTERSECTION(type)) {
8812
26
          ZEND_TYPE_FULL_MASK(type) |= MAY_BE_NULL;
8813
26
          zend_string *nullable_str = zend_type_to_string(type);
8814
8815
26
          zend_error_noreturn(E_COMPILE_ERROR,
8816
26
            "Default value for property of type %s may not be null. "
8817
26
            "Use the nullable type %s to allow null default value",
8818
26
            ZSTR_VAL(str), ZSTR_VAL(nullable_str));
8819
61
        } else {
8820
61
          zend_error_noreturn(E_COMPILE_ERROR,
8821
61
            "Cannot use %s as default value for property %s::$%s of type %s",
8822
61
            zend_zval_value_name(&value_zv),
8823
61
            ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(str));
8824
61
        }
8825
87
      }
8826
14.5k
    } else if (!ZEND_TYPE_IS_SET(type) && !hooks_ast) {
8827
3.61k
      ZVAL_NULL(&value_zv);
8828
10.9k
    } else {
8829
10.9k
      ZVAL_UNDEF(&value_zv);
8830
10.9k
    }
8831
8832
22.1k
    if ((ce->ce_flags & ZEND_ACC_READONLY_CLASS)) {
8833
42
      flags |= ZEND_ACC_READONLY;
8834
42
    }
8835
8836
22.1k
    if (flags & ZEND_ACC_READONLY) {
8837
533
      if (!ZEND_TYPE_IS_SET(type)) {
8838
21
        zend_error_noreturn(E_COMPILE_ERROR, "Readonly property %s::$%s must have type",
8839
21
          ZSTR_VAL(ce->name), ZSTR_VAL(name));
8840
21
      }
8841
512
      if (!Z_ISUNDEF(value_zv)) {
8842
6
        zend_error_noreturn(E_COMPILE_ERROR,
8843
6
          "Readonly property %s::$%s cannot have default value",
8844
6
          ZSTR_VAL(ce->name), ZSTR_VAL(name));
8845
6
      }
8846
506
      if (flags & ZEND_ACC_STATIC) {
8847
11
        zend_error_noreturn(E_COMPILE_ERROR,
8848
11
          "Static property %s::$%s cannot be readonly",
8849
11
          ZSTR_VAL(ce->name), ZSTR_VAL(name));
8850
11
      }
8851
506
    }
8852
8853
22.0k
    info = zend_declare_typed_property(ce, name, &value_zv, flags, doc_comment, type);
8854
8855
22.0k
    if (hooks_ast) {
8856
4.32k
      zend_compile_property_hooks(info, name, type_ast, zend_ast_get_list(hooks_ast));
8857
4.32k
    }
8858
8859
22.0k
    if (attr_ast) {
8860
170
      zend_compile_attributes(&info->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_PROPERTY, 0);
8861
170
    }
8862
8863
22.0k
    CG(context).active_property_info_name = old_active_property_info_name;
8864
22.0k
  }
8865
21.9k
}
8866
/* }}} */
8867
8868
static void zend_compile_prop_group(zend_ast *ast) /* {{{ */
8869
22.0k
{
8870
22.0k
  zend_ast *type_ast = ast->child[0];
8871
22.0k
  zend_ast *prop_ast = ast->child[1];
8872
22.0k
  zend_ast *attr_ast = ast->child[2];
8873
8874
22.0k
  zend_compile_prop_decl(prop_ast, type_ast, ast->attr, attr_ast);
8875
22.0k
}
8876
/* }}} */
8877
8878
static void zend_check_trait_alias_modifiers(uint32_t attr) /* {{{ */
8879
2.77k
{
8880
2.77k
  if (attr & ZEND_ACC_STATIC) {
8881
6
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"static\" as method modifier in trait alias");
8882
2.76k
  } else if (attr & ZEND_ACC_ABSTRACT) {
8883
7
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"abstract\" as method modifier in trait alias");
8884
7
  }
8885
2.77k
}
8886
/* }}} */
8887
8888
static void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_ast *attr_ast, zend_ast *type_ast)
8889
5.02k
{
8890
5.02k
  zend_ast_list *list = zend_ast_get_list(ast);
8891
5.02k
  zend_class_entry *ce = CG(active_class_entry);
8892
5.02k
  uint32_t i, children = list->children;
8893
8894
10.1k
  for (i = 0; i < children; ++i) {
8895
5.13k
    zend_class_constant *c;
8896
5.13k
    zend_ast *const_ast = list->child[i];
8897
5.13k
    zend_ast *name_ast = const_ast->child[0];
8898
5.13k
    zend_ast **value_ast_ptr = &const_ast->child[1];
8899
5.13k
    zend_ast *doc_comment_ast = const_ast->child[2];
8900
5.13k
    zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast));
8901
5.13k
    zend_string *doc_comment = doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL;
8902
5.13k
    zval value_zv;
8903
5.13k
    zend_type type = ZEND_TYPE_INIT_NONE(0);
8904
8905
5.13k
    if (type_ast) {
8906
1.49k
      type = zend_compile_typename(type_ast);
8907
8908
1.49k
      uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
8909
8910
1.49k
      if (type_mask != MAY_BE_ANY && (type_mask & (MAY_BE_CALLABLE|MAY_BE_VOID|MAY_BE_NEVER))) {
8911
6
        zend_string *type_str = zend_type_to_string(type);
8912
8913
6
        zend_error_noreturn(E_COMPILE_ERROR, "Class constant %s::%s cannot have type %s",
8914
6
          ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(type_str));
8915
6
      }
8916
1.49k
    }
8917
8918
5.12k
    if (UNEXPECTED((flags & ZEND_ACC_PRIVATE) && (flags & ZEND_ACC_FINAL))) {
8919
6
      zend_error_noreturn(
8920
6
        E_COMPILE_ERROR, "Private constant %s::%s cannot be final as it is not visible to other classes",
8921
6
        ZSTR_VAL(ce->name), ZSTR_VAL(name)
8922
6
      );
8923
6
    }
8924
8925
5.12k
    zend_const_expr_to_zval(&value_zv, value_ast_ptr, /* allow_dynamic */ false);
8926
8927
5.12k
    if (!Z_CONSTANT(value_zv) && ZEND_TYPE_IS_SET(type) && !zend_is_valid_default_value(type, &value_zv)) {
8928
29
      zend_string *type_str = zend_type_to_string(type);
8929
8930
29
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as value for class constant %s::%s of type %s",
8931
29
        zend_zval_type_name(&value_zv), ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(type_str));
8932
29
    }
8933
8934
5.09k
    c = zend_declare_typed_class_constant(ce, name, &value_zv, flags, doc_comment, type);
8935
8936
5.09k
    if (attr_ast) {
8937
240
      zend_compile_attributes(&c->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_CLASS_CONST, 0);
8938
8939
240
      zend_attribute *deprecated = zend_get_attribute_str(c->attributes, "deprecated", sizeof("deprecated")-1);
8940
8941
240
      if (deprecated) {
8942
103
        ZEND_CLASS_CONST_FLAGS(c) |= ZEND_ACC_DEPRECATED;
8943
        /* For deprecated constants, we need to flag the zval for recursion
8944
         * detection. Make sure the zval is separated out of shm. */
8945
103
        ce->ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS;
8946
103
        ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
8947
103
      }
8948
240
    }
8949
5.09k
  }
8950
5.02k
}
8951
8952
static void zend_compile_class_const_group(zend_ast *ast) /* {{{ */
8953
5.02k
{
8954
5.02k
  zend_ast *const_ast = ast->child[0];
8955
5.02k
  zend_ast *attr_ast = ast->child[1];
8956
5.02k
  zend_ast *type_ast = ast->child[2];
8957
8958
5.02k
  zend_compile_class_const_decl(const_ast, ast->attr, attr_ast, type_ast);
8959
5.02k
}
8960
/* }}} */
8961
8962
static void zend_compile_method_ref(zend_ast *ast, zend_trait_method_reference *method_ref) /* {{{ */
8963
3.49k
{
8964
3.49k
  zend_ast *class_ast = ast->child[0];
8965
3.49k
  zend_ast *method_ast = ast->child[1];
8966
8967
3.49k
  method_ref->method_name = zend_string_copy(zend_ast_get_str(method_ast));
8968
8969
3.49k
  if (class_ast) {
8970
1.67k
    method_ref->class_name = zend_resolve_const_class_name_reference(class_ast, "trait name");
8971
1.82k
  } else {
8972
1.82k
    method_ref->class_name = NULL;
8973
1.82k
  }
8974
3.49k
}
8975
/* }}} */
8976
8977
static void zend_compile_trait_precedence(zend_ast *ast) /* {{{ */
8978
740
{
8979
740
  zend_ast *method_ref_ast = ast->child[0];
8980
740
  zend_ast *insteadof_ast = ast->child[1];
8981
740
  zend_ast_list *insteadof_list = zend_ast_get_list(insteadof_ast);
8982
740
  uint32_t i;
8983
8984
740
  zend_trait_precedence *precedence = emalloc(sizeof(zend_trait_precedence) + (insteadof_list->children - 1) * sizeof(zend_string*));
8985
740
  zend_compile_method_ref(method_ref_ast, &precedence->trait_method);
8986
740
  precedence->num_excludes = insteadof_list->children;
8987
8988
1.78k
  for (i = 0; i < insteadof_list->children; ++i) {
8989
1.04k
    zend_ast *name_ast = insteadof_list->child[i];
8990
1.04k
    precedence->exclude_class_names[i] =
8991
1.04k
      zend_resolve_const_class_name_reference(name_ast, "trait name");
8992
1.04k
  }
8993
8994
740
  zend_add_to_list(&CG(active_class_entry)->trait_precedences, precedence);
8995
740
}
8996
/* }}} */
8997
8998
static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */
8999
2.77k
{
9000
2.77k
  zend_ast *method_ref_ast = ast->child[0];
9001
2.77k
  zend_ast *alias_ast = ast->child[1];
9002
2.77k
  uint32_t modifiers = ast->attr;
9003
9004
2.77k
  zend_trait_alias *alias;
9005
9006
2.77k
  zend_check_trait_alias_modifiers(modifiers);
9007
9008
2.77k
  alias = emalloc(sizeof(zend_trait_alias));
9009
2.77k
  zend_compile_method_ref(method_ref_ast, &alias->trait_method);
9010
2.77k
  alias->modifiers = modifiers;
9011
9012
2.77k
  if (alias_ast) {
9013
2.47k
    alias->alias = zend_string_copy(zend_ast_get_str(alias_ast));
9014
2.47k
  } else {
9015
292
    alias->alias = NULL;
9016
292
  }
9017
9018
2.77k
  zend_add_to_list(&CG(active_class_entry)->trait_aliases, alias);
9019
2.77k
}
9020
/* }}} */
9021
9022
static void zend_compile_use_trait(zend_ast *ast) /* {{{ */
9023
2.89k
{
9024
2.89k
  zend_ast_list *traits = zend_ast_get_list(ast->child[0]);
9025
2.89k
  zend_ast_list *adaptations = ast->child[1] ? zend_ast_get_list(ast->child[1]) : NULL;
9026
2.89k
  zend_class_entry *ce = CG(active_class_entry);
9027
2.89k
  uint32_t i;
9028
9029
2.89k
  ce->trait_names = erealloc(ce->trait_names, sizeof(zend_class_name) * (ce->num_traits + traits->children));
9030
9031
7.41k
  for (i = 0; i < traits->children; ++i) {
9032
4.52k
    zend_ast *trait_ast = traits->child[i];
9033
9034
4.52k
    if (ce->ce_flags & ZEND_ACC_INTERFACE) {
9035
6
      zend_string *name = zend_ast_get_str(trait_ast);
9036
6
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use traits inside of interfaces. "
9037
6
        "%s is used in %s", ZSTR_VAL(name), ZSTR_VAL(ce->name));
9038
6
    }
9039
9040
4.51k
    ce->trait_names[ce->num_traits].name =
9041
4.51k
      zend_resolve_const_class_name_reference(trait_ast, "trait name");
9042
4.51k
    ce->trait_names[ce->num_traits].lc_name = zend_string_tolower(ce->trait_names[ce->num_traits].name);
9043
4.51k
    ce->num_traits++;
9044
4.51k
  }
9045
9046
2.89k
  if (!adaptations) {
9047
1.93k
    return;
9048
1.93k
  }
9049
9050
4.44k
  for (i = 0; i < adaptations->children; ++i) {
9051
3.51k
    zend_ast *adaptation_ast = adaptations->child[i];
9052
3.51k
    switch (adaptation_ast->kind) {
9053
740
      case ZEND_AST_TRAIT_PRECEDENCE:
9054
740
        zend_compile_trait_precedence(adaptation_ast);
9055
740
        break;
9056
2.77k
      case ZEND_AST_TRAIT_ALIAS:
9057
2.77k
        zend_compile_trait_alias(adaptation_ast);
9058
2.77k
        break;
9059
3.51k
      EMPTY_SWITCH_DEFAULT_CASE()
9060
3.51k
    }
9061
3.51k
  }
9062
958
}
9063
/* }}} */
9064
9065
static void zend_compile_implements(zend_ast *ast) /* {{{ */
9066
2.88k
{
9067
2.88k
  zend_ast_list *list = zend_ast_get_list(ast);
9068
2.88k
  zend_class_entry *ce = CG(active_class_entry);
9069
2.88k
  zend_class_name *interface_names;
9070
2.88k
  uint32_t i;
9071
9072
2.88k
  interface_names = emalloc(sizeof(zend_class_name) * list->children);
9073
9074
7.07k
  for (i = 0; i < list->children; ++i) {
9075
4.19k
    zend_ast *class_ast = list->child[i];
9076
4.19k
    interface_names[i].name =
9077
4.19k
      zend_resolve_const_class_name_reference(class_ast, "interface name");
9078
4.19k
    interface_names[i].lc_name = zend_string_tolower(interface_names[i].name);
9079
4.19k
  }
9080
9081
2.88k
  ce->num_interfaces = list->children;
9082
2.88k
  ce->interface_names = interface_names;
9083
2.88k
}
9084
/* }}} */
9085
9086
static zend_string *zend_generate_anon_class_name(zend_ast_decl *decl)
9087
2.11k
{
9088
2.11k
  zend_string *filename = CG(active_op_array)->filename;
9089
2.11k
  uint32_t start_lineno = decl->start_lineno;
9090
9091
  /* Use parent or first interface as prefix. */
9092
2.11k
  zend_string *prefix = ZSTR_KNOWN(ZEND_STR_CLASS);
9093
2.11k
  if (decl->child[0]) {
9094
209
    prefix = zend_resolve_const_class_name_reference(decl->child[0], "class name");
9095
1.90k
  } else if (decl->child[1]) {
9096
687
    zend_ast_list *list = zend_ast_get_list(decl->child[1]);
9097
687
    prefix = zend_resolve_const_class_name_reference(list->child[0], "interface name");
9098
687
  }
9099
9100
2.11k
  zend_string *result = zend_strpprintf(0, "%s@anonymous%c%s:%" PRIu32 "$%" PRIx32,
9101
2.11k
    ZSTR_VAL(prefix), '\0', ZSTR_VAL(filename), start_lineno, CG(rtd_key_counter)++);
9102
2.11k
  zend_string_release(prefix);
9103
2.11k
  return zend_new_interned_string(result);
9104
2.11k
}
9105
9106
static void zend_compile_enum_backing_type(zend_class_entry *ce, zend_ast *enum_backing_type_ast)
9107
601
{
9108
601
  ZEND_ASSERT(ce->ce_flags & ZEND_ACC_ENUM);
9109
601
  zend_type type = zend_compile_typename(enum_backing_type_ast);
9110
601
  uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
9111
601
  if (ZEND_TYPE_IS_COMPLEX(type) || (type_mask != MAY_BE_LONG && type_mask != MAY_BE_STRING)) {
9112
72
    zend_string *type_string = zend_type_to_string(type);
9113
72
    zend_error_noreturn(E_COMPILE_ERROR,
9114
72
      "Enum backing type must be int or string, %s given",
9115
72
      ZSTR_VAL(type_string));
9116
72
  }
9117
529
  if (type_mask == MAY_BE_LONG) {
9118
281
    ce->enum_backing_type = IS_LONG;
9119
281
  } else {
9120
248
    ZEND_ASSERT(type_mask == MAY_BE_STRING);
9121
245
    ce->enum_backing_type = IS_STRING;
9122
245
  }
9123
526
  zend_type_release(type, 0);
9124
526
}
9125
9126
static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) /* {{{ */
9127
58.4k
{
9128
58.4k
  zend_ast_decl *decl = (zend_ast_decl *) ast;
9129
58.4k
  zend_ast *extends_ast = decl->child[0];
9130
58.4k
  zend_ast *implements_ast = decl->child[1];
9131
58.4k
  zend_ast *stmt_ast = decl->child[2];
9132
58.4k
  zend_ast *enum_backing_type_ast = decl->child[4];
9133
58.4k
  zend_string *name, *lcname;
9134
58.4k
  zend_class_entry *ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry));
9135
58.4k
  zend_op *opline;
9136
9137
58.4k
  zend_class_entry *original_ce = CG(active_class_entry);
9138
9139
58.4k
  if (EXPECTED((decl->flags & ZEND_ACC_ANON_CLASS) == 0)) {
9140
56.3k
    zend_string *unqualified_name = decl->name;
9141
9142
56.3k
    if (CG(active_class_entry)) {
9143
6
      zend_error_noreturn(E_COMPILE_ERROR, "Class declarations may not be nested");
9144
6
    }
9145
9146
56.3k
    const char *type = "a class name";
9147
56.3k
    if (decl->flags & ZEND_ACC_ENUM) {
9148
5.78k
      type = "an enum name";
9149
50.5k
    } else if (decl->flags & ZEND_ACC_INTERFACE) {
9150
3.13k
      type = "an interface name";
9151
47.4k
    } else if (decl->flags & ZEND_ACC_TRAIT) {
9152
3.40k
      type = "a trait name";
9153
3.40k
    }
9154
56.3k
    zend_assert_valid_class_name(unqualified_name, type);
9155
56.3k
    name = zend_prefix_with_ns(unqualified_name);
9156
56.3k
    name = zend_new_interned_string(name);
9157
56.3k
    lcname = zend_string_tolower(name);
9158
9159
56.3k
    if (FC(imports)) {
9160
693
      zend_string *import_name =
9161
693
        zend_hash_find_ptr_lc(FC(imports), unqualified_name);
9162
693
      if (import_name && !zend_string_equals_ci(lcname, import_name)) {
9163
12
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare class %s "
9164
12
            "(previously declared as local import)", ZSTR_VAL(name));
9165
12
      }
9166
693
    }
9167
9168
56.3k
    zend_register_seen_symbol(lcname, ZEND_SYMBOL_CLASS);
9169
56.3k
  } else {
9170
    /* Find an anon class name that is not in use yet. */
9171
2.11k
    name = NULL;
9172
2.11k
    lcname = NULL;
9173
2.11k
    do {
9174
2.11k
      zend_tmp_string_release(name);
9175
2.11k
      zend_tmp_string_release(lcname);
9176
2.11k
      name = zend_generate_anon_class_name(decl);
9177
2.11k
      lcname = zend_string_tolower(name);
9178
2.11k
    } while (zend_hash_exists(CG(class_table), lcname));
9179
2.11k
  }
9180
58.4k
  lcname = zend_new_interned_string(lcname);
9181
9182
58.4k
  ce->type = ZEND_USER_CLASS;
9183
58.4k
  ce->name = name;
9184
58.4k
  zend_initialize_class_data(ce, 1);
9185
58.4k
  if (!(decl->flags & ZEND_ACC_ANON_CLASS)) {
9186
56.2k
    zend_alloc_ce_cache(ce->name);
9187
56.2k
  }
9188
9189
58.4k
  if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
9190
0
    ce->ce_flags |= ZEND_ACC_PRELOADED;
9191
0
    ZEND_MAP_PTR_NEW(ce->static_members_table);
9192
0
    ZEND_MAP_PTR_NEW(ce->mutable_data);
9193
0
  }
9194
9195
58.4k
  ce->ce_flags |= decl->flags;
9196
58.4k
  ce->info.user.filename = zend_string_copy(zend_get_compiled_filename());
9197
58.4k
  ce->info.user.line_start = decl->start_lineno;
9198
58.4k
  ce->info.user.line_end = decl->end_lineno;
9199
9200
58.4k
  if (decl->doc_comment) {
9201
182
    ce->doc_comment = zend_string_copy(decl->doc_comment);
9202
182
  }
9203
9204
58.4k
  if (UNEXPECTED((decl->flags & ZEND_ACC_ANON_CLASS))) {
9205
    /* Serialization is not supported for anonymous classes */
9206
2.11k
    ce->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE;
9207
2.11k
  }
9208
9209
58.4k
  if (extends_ast) {
9210
13.8k
    ce->parent_name =
9211
13.8k
      zend_resolve_const_class_name_reference(extends_ast, "class name");
9212
13.8k
  }
9213
9214
58.4k
  CG(active_class_entry) = ce;
9215
9216
58.4k
  if (decl->child[3]) {
9217
2.55k
    zend_compile_attributes(&ce->attributes, decl->child[3], 0, ZEND_ATTRIBUTE_TARGET_CLASS, 0);
9218
2.55k
  }
9219
9220
58.4k
  if (implements_ast) {
9221
2.88k
    zend_compile_implements(implements_ast);
9222
2.88k
  }
9223
9224
58.4k
  if (ce->ce_flags & ZEND_ACC_ENUM) {
9225
5.76k
    if (enum_backing_type_ast != NULL) {
9226
601
      zend_compile_enum_backing_type(ce, enum_backing_type_ast);
9227
601
    }
9228
5.76k
    zend_enum_add_interfaces(ce);
9229
5.76k
    zend_enum_register_props(ce);
9230
5.76k
  }
9231
9232
58.4k
  zend_compile_stmt(stmt_ast);
9233
9234
  /* Reset lineno for final opcodes and errors */
9235
58.4k
  CG(zend_lineno) = ast->lineno;
9236
9237
58.4k
  if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
9238
69
    zend_verify_abstract_class(ce);
9239
69
  }
9240
9241
58.4k
  CG(active_class_entry) = original_ce;
9242
9243
58.4k
  if (toplevel) {
9244
51.3k
    ce->ce_flags |= ZEND_ACC_TOP_LEVEL;
9245
51.3k
  }
9246
9247
  /* We currently don't early-bind classes that implement interfaces or use traits */
9248
58.4k
  if (!ce->num_interfaces && !ce->num_traits && !ce->num_hooked_prop_variance_checks
9249
#ifdef ZEND_OPCACHE_SHM_REATTACHMENT
9250
   /* See zend_link_hooked_object_iter(). */
9251
   && !ce->num_hooked_props
9252
#endif
9253
58.4k
   && !(CG(compiler_options) & ZEND_COMPILE_WITHOUT_EXECUTION)) {
9254
45.0k
    if (toplevel) {
9255
41.4k
      if (extends_ast) {
9256
12.2k
        zend_class_entry *parent_ce = zend_lookup_class_ex(
9257
12.2k
          ce->parent_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
9258
9259
12.2k
        if (parent_ce
9260
12.2k
         && !zend_compile_ignore_class(parent_ce, ce->info.user.filename)) {
9261
11.0k
          if (zend_try_early_bind(ce, parent_ce, lcname, NULL)) {
9262
5.10k
            zend_string_release(lcname);
9263
5.10k
            return;
9264
5.10k
          }
9265
11.0k
        }
9266
29.2k
      } else if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) {
9267
21.2k
        zend_string_release(lcname);
9268
21.2k
        zend_build_properties_info_table(ce);
9269
21.2k
        zend_inheritance_check_override(ce);
9270
21.2k
        ce->ce_flags |= ZEND_ACC_LINKED;
9271
21.2k
        zend_observer_class_linked_notify(ce, lcname);
9272
21.2k
        return;
9273
21.2k
      } else {
9274
7.91k
        goto link_unbound;
9275
7.91k
      }
9276
41.4k
    } else if (!extends_ast) {
9277
10.6k
link_unbound:
9278
      /* Link unbound simple class */
9279
10.6k
      zend_build_properties_info_table(ce);
9280
10.6k
      zend_inheritance_check_override(ce);
9281
10.6k
      ce->ce_flags |= ZEND_ACC_LINKED;
9282
10.6k
    }
9283
45.0k
  }
9284
9285
32.0k
  opline = get_next_op();
9286
9287
32.0k
  if (ce->parent_name) {
9288
    /* Lowercased parent name */
9289
7.55k
    zend_string *lc_parent_name = zend_string_tolower(ce->parent_name);
9290
7.55k
    opline->op2_type = IS_CONST;
9291
7.55k
    LITERAL_STR(opline->op2, lc_parent_name);
9292
7.55k
  }
9293
9294
32.0k
  opline->op1_type = IS_CONST;
9295
  /* It's possible that `lcname` is not an interned string because it was not yet in the interned string table.
9296
   * However, by this point another thread may have caused `lcname` to be added in the interned string table.
9297
   * This will cause `lcname` to get freed once it is found in the interned string table. If we were to use
9298
   * LITERAL_STR() here we would not change the `lcname` pointer to the new value, and it would point to the
9299
   * now-freed string. This will cause issues when we use `lcname` in the code below. We solve this by using
9300
   * zend_add_literal_string() which gives us the new value. */
9301
32.0k
  opline->op1.constant = zend_add_literal_string(&lcname);
9302
9303
32.0k
  if (decl->flags & ZEND_ACC_ANON_CLASS) {
9304
2.07k
    opline->opcode = ZEND_DECLARE_ANON_CLASS;
9305
2.07k
    opline->extended_value = zend_alloc_cache_slot();
9306
2.07k
    zend_make_var_result(result, opline);
9307
2.07k
    if (!zend_hash_add_ptr(CG(class_table), lcname, ce)) {
9308
      /* We checked above that the class name is not used. This really shouldn't happen. */
9309
0
      zend_error_noreturn(E_ERROR,
9310
0
        "Runtime definition key collision for %s. This is a bug", ZSTR_VAL(name));
9311
0
    }
9312
29.9k
  } else {
9313
    /* Generate RTD keys until we find one that isn't in use yet. */
9314
29.9k
    zend_string *key = NULL;
9315
29.9k
    do {
9316
29.9k
      zend_tmp_string_release(key);
9317
29.9k
      key = zend_build_runtime_definition_key(lcname, decl->start_lineno);
9318
29.9k
    } while (!zend_hash_add_ptr(CG(class_table), key, ce));
9319
9320
    /* RTD key is placed after lcname literal in op1 */
9321
29.9k
    zend_add_literal_string(&key);
9322
9323
29.9k
    opline->opcode = ZEND_DECLARE_CLASS;
9324
29.9k
    if (toplevel
9325
29.9k
       && (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING)
9326
        /* We currently don't early-bind classes that implement interfaces or use traits */
9327
29.9k
       && !ce->num_interfaces && !ce->num_traits && !ce->num_hooked_prop_variance_checks
9328
29.9k
    ) {
9329
1.40k
      if (!extends_ast) {
9330
        /* Use empty string for classes without parents to avoid new handler, and special
9331
         * handling of zend_early_binding. */
9332
840
        opline->op2_type = IS_CONST;
9333
840
        LITERAL_STR(opline->op2, ZSTR_EMPTY_ALLOC());
9334
840
      }
9335
1.40k
      CG(active_op_array)->fn_flags |= ZEND_ACC_EARLY_BINDING;
9336
1.40k
      opline->opcode = ZEND_DECLARE_CLASS_DELAYED;
9337
1.40k
      opline->extended_value = zend_alloc_cache_slot();
9338
1.40k
      opline->result_type = IS_UNUSED;
9339
1.40k
      opline->result.opline_num = -1;
9340
1.40k
    }
9341
29.9k
  }
9342
32.0k
}
9343
/* }}} */
9344
9345
static void zend_compile_enum_case(zend_ast *ast)
9346
2.42k
{
9347
2.42k
  zend_class_entry *enum_class = CG(active_class_entry);
9348
2.42k
  if (!(enum_class->ce_flags & ZEND_ACC_ENUM)) {
9349
6
    zend_error_noreturn(E_COMPILE_ERROR, "Case can only be used in enums");
9350
6
  }
9351
9352
2.41k
  zend_string *enum_case_name = zval_make_interned_string(zend_ast_get_zval(ast->child[0]));
9353
2.41k
  zend_string *enum_class_name = enum_class->name;
9354
9355
2.41k
  zval class_name_zval;
9356
2.41k
  ZVAL_STR_COPY(&class_name_zval, enum_class_name);
9357
2.41k
  zend_ast *class_name_ast = zend_ast_create_zval(&class_name_zval);
9358
9359
2.41k
  zval case_name_zval;
9360
2.41k
  ZVAL_STR_COPY(&case_name_zval, enum_case_name);
9361
2.41k
  zend_ast *case_name_ast = zend_ast_create_zval(&case_name_zval);
9362
9363
2.41k
  zend_ast *case_value_ast = ast->child[1];
9364
  // Remove case_value_ast from the original AST to avoid freeing it, as it will be freed by zend_const_expr_to_zval
9365
2.41k
  ast->child[1] = NULL;
9366
2.41k
  if (enum_class->enum_backing_type != IS_UNDEF && case_value_ast == NULL) {
9367
9
    zend_error_noreturn(E_COMPILE_ERROR, "Case %s of backed enum %s must have a value",
9368
9
      ZSTR_VAL(enum_case_name),
9369
9
      ZSTR_VAL(enum_class_name));
9370
2.41k
  } else if (enum_class->enum_backing_type == IS_UNDEF && case_value_ast != NULL) {
9371
17
    zend_error_noreturn(E_COMPILE_ERROR, "Case %s of non-backed enum %s must not have a value",
9372
17
      ZSTR_VAL(enum_case_name),
9373
17
      ZSTR_VAL(enum_class_name));
9374
17
  }
9375
9376
2.39k
  zend_ast *const_enum_init_ast = zend_ast_create(ZEND_AST_CONST_ENUM_INIT, class_name_ast, case_name_ast, case_value_ast);
9377
9378
2.39k
  zval value_zv;
9379
2.39k
  zend_const_expr_to_zval(&value_zv, &const_enum_init_ast, /* allow_dynamic */ false);
9380
9381
  /* Doc comment has been appended as second last element in ZEND_AST_ENUM ast - attributes are conventionally last */
9382
2.39k
  zend_ast *doc_comment_ast = ast->child[2];
9383
2.39k
  zend_string *doc_comment = NULL;
9384
2.39k
  if (doc_comment_ast) {
9385
141
    doc_comment = zend_string_copy(zend_ast_get_str(doc_comment_ast));
9386
141
  }
9387
9388
2.39k
  zend_class_constant *c = zend_declare_class_constant_ex(enum_class, enum_case_name, &value_zv, ZEND_ACC_PUBLIC, doc_comment);
9389
2.39k
  ZEND_CLASS_CONST_FLAGS(c) |= ZEND_CLASS_CONST_IS_CASE;
9390
2.39k
  zend_ast_destroy(const_enum_init_ast);
9391
9392
2.39k
  zend_ast *attr_ast = ast->child[3];
9393
2.39k
  if (attr_ast) {
9394
155
    zend_compile_attributes(&c->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_CLASS_CONST, 0);
9395
9396
155
    zend_attribute *deprecated = zend_get_attribute_str(c->attributes, "deprecated", sizeof("deprecated")-1);
9397
9398
155
    if (deprecated) {
9399
13
      ZEND_CLASS_CONST_FLAGS(c) |= ZEND_ACC_DEPRECATED;
9400
13
    }
9401
155
  }
9402
2.39k
}
9403
9404
static HashTable *zend_get_import_ht(uint32_t type) /* {{{ */
9405
2.58k
{
9406
2.58k
  switch (type) {
9407
1.77k
    case ZEND_SYMBOL_CLASS:
9408
1.77k
      if (!FC(imports)) {
9409
1.33k
        FC(imports) = emalloc(sizeof(HashTable));
9410
1.33k
        zend_hash_init(FC(imports), 8, NULL, str_dtor, 0);
9411
1.33k
      }
9412
1.77k
      return FC(imports);
9413
449
    case ZEND_SYMBOL_FUNCTION:
9414
449
      if (!FC(imports_function)) {
9415
350
        FC(imports_function) = emalloc(sizeof(HashTable));
9416
350
        zend_hash_init(FC(imports_function), 8, NULL, str_dtor, 0);
9417
350
      }
9418
449
      return FC(imports_function);
9419
360
    case ZEND_SYMBOL_CONST:
9420
360
      if (!FC(imports_const)) {
9421
218
        FC(imports_const) = emalloc(sizeof(HashTable));
9422
218
        zend_hash_init(FC(imports_const), 8, NULL, str_dtor, 0);
9423
218
      }
9424
360
      return FC(imports_const);
9425
2.58k
    EMPTY_SWITCH_DEFAULT_CASE()
9426
2.58k
  }
9427
9428
0
  return NULL;
9429
2.58k
}
9430
/* }}} */
9431
9432
static char *zend_get_use_type_str(uint32_t type) /* {{{ */
9433
105
{
9434
105
  switch (type) {
9435
63
    case ZEND_SYMBOL_CLASS:
9436
63
      return "";
9437
20
    case ZEND_SYMBOL_FUNCTION:
9438
20
      return " function";
9439
22
    case ZEND_SYMBOL_CONST:
9440
22
      return " const";
9441
105
    EMPTY_SWITCH_DEFAULT_CASE()
9442
105
  }
9443
9444
0
  return " unknown";
9445
105
}
9446
/* }}} */
9447
9448
static void zend_check_already_in_use(uint32_t type, zend_string *old_name, zend_string *new_name, zend_string *check_name) /* {{{ */
9449
65
{
9450
65
  if (zend_string_equals_ci(old_name, check_name)) {
9451
26
    return;
9452
26
  }
9453
9454
39
  zend_error_noreturn(E_COMPILE_ERROR, "Cannot use%s %s as %s because the name "
9455
39
    "is already in use", zend_get_use_type_str(type), ZSTR_VAL(old_name), ZSTR_VAL(new_name));
9456
65
}
9457
/* }}} */
9458
9459
static void zend_compile_use(zend_ast *ast) /* {{{ */
9460
2.58k
{
9461
2.58k
  zend_ast_list *list = zend_ast_get_list(ast);
9462
2.58k
  uint32_t i;
9463
2.58k
  zend_string *current_ns = FC(current_namespace);
9464
2.58k
  uint32_t type = ast->attr;
9465
2.58k
  HashTable *current_import = zend_get_import_ht(type);
9466
2.58k
  bool case_sensitive = type == ZEND_SYMBOL_CONST;
9467
9468
5.24k
  for (i = 0; i < list->children; ++i) {
9469
2.74k
    zend_ast *use_ast = list->child[i];
9470
2.74k
    zend_ast *old_name_ast = use_ast->child[0];
9471
2.74k
    zend_ast *new_name_ast = use_ast->child[1];
9472
2.74k
    zend_string *old_name = zend_ast_get_str(old_name_ast);
9473
2.74k
    zend_string *new_name, *lookup_name;
9474
9475
2.74k
    if (new_name_ast) {
9476
502
      new_name = zend_string_copy(zend_ast_get_str(new_name_ast));
9477
2.24k
    } else {
9478
2.24k
      const char *unqualified_name;
9479
2.24k
      size_t unqualified_name_len;
9480
2.24k
      if (zend_get_unqualified_name(old_name, &unqualified_name, &unqualified_name_len)) {
9481
        /* The form "use A\B" is equivalent to "use A\B as B" */
9482
1.02k
        new_name = zend_string_init(unqualified_name, unqualified_name_len, 0);
9483
1.22k
      } else {
9484
1.22k
        new_name = zend_string_copy(old_name);
9485
9486
1.22k
        if (!current_ns) {
9487
581
          zend_error(E_WARNING, "The use statement with non-compound name '%s' "
9488
581
            "has no effect", ZSTR_VAL(new_name));
9489
581
        }
9490
1.22k
      }
9491
2.24k
    }
9492
9493
2.74k
    if (case_sensitive) {
9494
375
      lookup_name = zend_string_copy(new_name);
9495
2.37k
    } else {
9496
2.37k
      lookup_name = zend_string_tolower(new_name);
9497
2.37k
    }
9498
9499
2.74k
    if (type == ZEND_SYMBOL_CLASS && zend_is_reserved_class_name(new_name)) {
9500
26
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' "
9501
26
        "is a special class name", ZSTR_VAL(old_name), ZSTR_VAL(new_name), ZSTR_VAL(new_name));
9502
26
    }
9503
9504
2.72k
    if (current_ns) {
9505
1.44k
      zend_string *ns_name = zend_string_alloc(ZSTR_LEN(current_ns) + 1 + ZSTR_LEN(new_name), 0);
9506
1.44k
      zend_str_tolower_copy(ZSTR_VAL(ns_name), ZSTR_VAL(current_ns), ZSTR_LEN(current_ns));
9507
1.44k
      ZSTR_VAL(ns_name)[ZSTR_LEN(current_ns)] = '\\';
9508
1.44k
      memcpy(ZSTR_VAL(ns_name) + ZSTR_LEN(current_ns) + 1, ZSTR_VAL(lookup_name), ZSTR_LEN(lookup_name) + 1);
9509
9510
1.44k
      if (zend_have_seen_symbol(ns_name, type)) {
9511
34
        zend_check_already_in_use(type, old_name, new_name, ns_name);
9512
34
      }
9513
9514
1.44k
      zend_string_efree(ns_name);
9515
1.44k
    } else if (zend_have_seen_symbol(lookup_name, type)) {
9516
31
      zend_check_already_in_use(type, old_name, new_name, lookup_name);
9517
31
    }
9518
9519
2.72k
    zend_string_addref(old_name);
9520
2.72k
    old_name = zend_new_interned_string(old_name);
9521
2.72k
    if (!zend_hash_add_ptr(current_import, lookup_name, old_name)) {
9522
66
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use%s %s as %s because the name "
9523
66
        "is already in use", zend_get_use_type_str(type), ZSTR_VAL(old_name), ZSTR_VAL(new_name));
9524
66
    }
9525
9526
2.65k
    zend_string_release_ex(lookup_name, 0);
9527
2.65k
    zend_string_release_ex(new_name, 0);
9528
2.65k
  }
9529
2.58k
}
9530
/* }}} */
9531
9532
static void zend_compile_group_use(zend_ast *ast) /* {{{ */
9533
268
{
9534
268
  uint32_t i;
9535
268
  zend_string *ns = zend_ast_get_str(ast->child[0]);
9536
268
  zend_ast_list *list = zend_ast_get_list(ast->child[1]);
9537
9538
1.07k
  for (i = 0; i < list->children; i++) {
9539
809
    zend_ast *inline_use, *use = list->child[i];
9540
809
    zval *name_zval = zend_ast_get_zval(use->child[0]);
9541
809
    zend_string *name = Z_STR_P(name_zval);
9542
809
    zend_string *compound_ns = zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
9543
809
    zend_string_release_ex(name, 0);
9544
809
    ZVAL_STR(name_zval, compound_ns);
9545
809
    inline_use = zend_ast_create_list(1, ZEND_AST_USE, use);
9546
809
    inline_use->attr = ast->attr ? ast->attr : use->attr;
9547
809
    zend_compile_use(inline_use);
9548
809
  }
9549
268
}
9550
/* }}} */
9551
9552
static void zend_compile_const_decl(zend_ast *ast) /* {{{ */
9553
4.66k
{
9554
4.66k
  zend_ast_list *list = zend_ast_get_list(ast);
9555
4.66k
  uint32_t i;
9556
4.66k
  zend_ast *attributes_ast = NULL;
9557
4.66k
  zend_op *last_op = NULL;
9558
9.90k
  for (i = 0; i < list->children; ++i) {
9559
5.25k
    zend_ast *const_ast = list->child[i];
9560
5.25k
    if (const_ast->kind == ZEND_AST_ATTRIBUTE_LIST) {
9561
374
      ZEND_ASSERT(i == list->children - 1);
9562
374
      attributes_ast = const_ast;
9563
374
      continue;
9564
374
    }
9565
4.87k
    ZEND_ASSERT(const_ast->kind == ZEND_AST_CONST_ELEM);
9566
4.87k
    zend_ast *name_ast = const_ast->child[0];
9567
4.87k
    zend_ast **value_ast_ptr = &const_ast->child[1];
9568
4.87k
    zend_string *unqualified_name = zend_ast_get_str(name_ast);
9569
9570
4.87k
    zend_string *name;
9571
4.87k
    znode name_node, value_node;
9572
4.87k
    zval *value_zv = &value_node.u.constant;
9573
9574
4.87k
    value_node.op_type = IS_CONST;
9575
4.87k
    zend_const_expr_to_zval(value_zv, value_ast_ptr, /* allow_dynamic */ true);
9576
9577
4.87k
    if (zend_get_special_const(ZSTR_VAL(unqualified_name), ZSTR_LEN(unqualified_name))) {
9578
6
      zend_error_noreturn(E_COMPILE_ERROR,
9579
6
        "Cannot redeclare constant '%s'", ZSTR_VAL(unqualified_name));
9580
6
    }
9581
9582
4.87k
    name = zend_prefix_with_ns(unqualified_name);
9583
4.87k
    name = zend_new_interned_string(name);
9584
9585
4.87k
    if (FC(imports_const)) {
9586
225
      zend_string *import_name = zend_hash_find_ptr(FC(imports_const), unqualified_name);
9587
225
      if (import_name && !zend_string_equals(import_name, name)) {
9588
7
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare const %s because "
9589
7
          "the name is already in use", ZSTR_VAL(name));
9590
7
      }
9591
225
    }
9592
9593
4.86k
    name_node.op_type = IS_CONST;
9594
4.86k
    ZVAL_STR(&name_node.u.constant, name);
9595
9596
4.86k
    last_op = zend_emit_op(NULL, ZEND_DECLARE_CONST, &name_node, &value_node);
9597
9598
4.86k
    zend_register_seen_symbol(name, ZEND_SYMBOL_CONST);
9599
4.86k
  }
9600
4.65k
  if (attributes_ast == NULL) {
9601
4.19k
    return;
9602
4.19k
  }
9603
  /* Validate: attributes can only be applied to one constant at a time
9604
   * Since we store the AST for the attributes in the list of children,
9605
   * there should be exactly 2 children. */
9606
459
  if (list->children > 2) {
9607
6
    zend_error_noreturn(
9608
6
      E_COMPILE_ERROR,
9609
6
      "Cannot apply attributes to multiple constants at once"
9610
6
    );
9611
6
  }
9612
9613
453
  HashTable *attributes = NULL;
9614
453
  zend_compile_attributes(&attributes, list->child[1], 0, ZEND_ATTRIBUTE_TARGET_CONST, 0);
9615
9616
453
  ZEND_ASSERT(last_op != NULL);
9617
359
  last_op->opcode = ZEND_DECLARE_ATTRIBUTED_CONST;
9618
359
  znode attribs_node;
9619
359
  attribs_node.op_type = IS_CONST;
9620
359
  ZVAL_PTR(&attribs_node.u.constant, attributes);
9621
359
  zend_emit_op_data(&attribs_node);
9622
359
  CG(active_op_array)->fn_flags |= ZEND_ACC_PTR_OPS;
9623
359
}
9624
/* }}}*/
9625
9626
static void zend_compile_namespace(zend_ast *ast) /* {{{ */
9627
5.36k
{
9628
5.36k
  zend_ast *name_ast = ast->child[0];
9629
5.36k
  zend_ast *stmt_ast = ast->child[1];
9630
5.36k
  zend_string *name;
9631
5.36k
  bool with_bracket = stmt_ast != NULL;
9632
9633
  /* handle mixed syntax declaration or nested namespaces */
9634
5.36k
  if (!FC(has_bracketed_namespaces)) {
9635
3.73k
    if (FC(current_namespace)) {
9636
      /* previous namespace declarations were unbracketed */
9637
1.13k
      if (with_bracket) {
9638
6
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations "
9639
6
          "with unbracketed namespace declarations");
9640
6
      }
9641
1.13k
    }
9642
3.73k
  } else {
9643
    /* previous namespace declarations were bracketed */
9644
1.62k
    if (!with_bracket) {
9645
6
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations "
9646
6
        "with unbracketed namespace declarations");
9647
1.62k
    } else if (FC(current_namespace) || FC(in_namespace)) {
9648
7
      zend_error_noreturn(E_COMPILE_ERROR, "Namespace declarations cannot be nested");
9649
7
    }
9650
1.62k
  }
9651
9652
5.34k
  bool is_first_namespace = (!with_bracket && !FC(current_namespace))
9653
5.34k
    || (with_bracket && !FC(has_bracketed_namespaces));
9654
5.34k
  if (is_first_namespace && FAILURE == zend_is_first_statement(ast, /* allow_nop */ 1)) {
9655
29
    zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be "
9656
29
      "the very first statement or after any declare call in the script");
9657
29
  }
9658
9659
5.31k
  if (FC(current_namespace)) {
9660
1.12k
    zend_string_release_ex(FC(current_namespace), 0);
9661
1.12k
  }
9662
9663
5.31k
  if (name_ast) {
9664
4.62k
    name = zend_ast_get_str(name_ast);
9665
9666
4.62k
    if (zend_string_equals_literal_ci(name, "namespace")) {
9667
6
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", ZSTR_VAL(name));
9668
6
    }
9669
9670
4.61k
    FC(current_namespace) = zend_string_copy(name);
9671
4.61k
  } else {
9672
693
    FC(current_namespace) = NULL;
9673
693
  }
9674
9675
5.30k
  zend_reset_import_tables();
9676
9677
5.30k
  FC(in_namespace) = 1;
9678
5.30k
  if (with_bracket) {
9679
2.20k
    FC(has_bracketed_namespaces) = 1;
9680
2.20k
  }
9681
9682
5.30k
  if (stmt_ast) {
9683
2.20k
    zend_compile_top_stmt(stmt_ast);
9684
2.20k
    zend_end_namespace();
9685
2.20k
  }
9686
5.30k
}
9687
/* }}} */
9688
9689
static void zend_compile_halt_compiler(zend_ast *ast) /* {{{ */
9690
55
{
9691
55
  zend_ast *offset_ast = ast->child[0];
9692
55
  zend_long offset = Z_LVAL_P(zend_ast_get_zval(offset_ast));
9693
9694
55
  zend_string *filename, *name;
9695
55
  const char const_name[] = "__COMPILER_HALT_OFFSET__";
9696
9697
55
  if (FC(has_bracketed_namespaces) && FC(in_namespace)) {
9698
0
    zend_error_noreturn(E_COMPILE_ERROR,
9699
0
      "__HALT_COMPILER() can only be used from the outermost scope");
9700
0
  }
9701
9702
55
  filename = zend_get_compiled_filename();
9703
55
  name = zend_mangle_property_name(const_name, sizeof(const_name) - 1,
9704
55
    ZSTR_VAL(filename), ZSTR_LEN(filename), 0);
9705
9706
55
  zend_register_long_constant(ZSTR_VAL(name), ZSTR_LEN(name), offset, 0, 0);
9707
55
  zend_string_release_ex(name, 0);
9708
55
}
9709
/* }}} */
9710
9711
static bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */
9712
17.7k
{
9713
17.7k
  zend_op_array *op_array = CG(active_op_array);
9714
17.7k
  zend_class_entry *ce = CG(active_class_entry);
9715
9716
17.7k
  switch (ast->attr) {
9717
321
    case T_LINE:
9718
321
      ZVAL_LONG(zv, ast->lineno);
9719
321
      break;
9720
5.57k
    case T_FILE:
9721
5.57k
      ZVAL_STR_COPY(zv, CG(compiled_filename));
9722
5.57k
      break;
9723
2.31k
    case T_DIR:
9724
2.31k
    {
9725
2.31k
      zend_string *filename = CG(compiled_filename);
9726
2.31k
      zend_string *dirname = zend_string_init(ZSTR_VAL(filename), ZSTR_LEN(filename), 0);
9727
#ifdef ZEND_WIN32
9728
      ZSTR_LEN(dirname) = php_win32_ioutil_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname));
9729
#else
9730
2.31k
      ZSTR_LEN(dirname) = zend_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname));
9731
2.31k
#endif
9732
9733
2.31k
      if (zend_string_equals_literal(dirname, ".")) {
9734
1.82k
        dirname = zend_string_extend(dirname, MAXPATHLEN, 0);
9735
1.82k
#ifdef HAVE_GETCWD
9736
1.82k
        ZEND_IGNORE_VALUE(VCWD_GETCWD(ZSTR_VAL(dirname), MAXPATHLEN));
9737
#elif defined(HAVE_GETWD)
9738
        ZEND_IGNORE_VALUE(VCWD_GETWD(ZSTR_VAL(dirname)));
9739
#endif
9740
1.82k
        ZSTR_LEN(dirname) = strlen(ZSTR_VAL(dirname));
9741
1.82k
      }
9742
9743
2.31k
      ZVAL_STR(zv, dirname);
9744
2.31k
      break;
9745
0
    }
9746
1.47k
    case T_FUNC_C:
9747
1.47k
      if (op_array && op_array->function_name) {
9748
1.25k
        ZVAL_STR_COPY(zv, op_array->function_name);
9749
1.25k
      } else {
9750
220
        ZVAL_EMPTY_STRING(zv);
9751
220
      }
9752
1.47k
      break;
9753
358
    case T_PROPERTY_C: {
9754
358
      zend_string *prop_info_name = CG(context).active_property_info_name;
9755
358
      if (prop_info_name) {
9756
152
        ZVAL_STR(zv, zend_copy_unmangled_prop_name(prop_info_name));
9757
206
      } else {
9758
206
        ZVAL_EMPTY_STRING(zv);
9759
206
      }
9760
358
      break;
9761
0
    }
9762
4.51k
    case T_METHOD_C:
9763
      /* Detect whether we are directly inside a class (e.g. a class constant) and treat
9764
       * this as not being inside a function. */
9765
4.51k
      if (op_array && ce && !op_array->scope && !(op_array->fn_flags & ZEND_ACC_CLOSURE)) {
9766
211
        op_array = NULL;
9767
211
      }
9768
4.51k
      if (op_array && op_array->function_name) {
9769
3.95k
        if (op_array->scope) {
9770
3.47k
          ZVAL_NEW_STR(zv,
9771
3.47k
            zend_create_member_string(op_array->scope->name, op_array->function_name));
9772
3.47k
        } else {
9773
483
          ZVAL_STR_COPY(zv, op_array->function_name);
9774
483
        }
9775
3.95k
      } else {
9776
555
        ZVAL_EMPTY_STRING(zv);
9777
555
      }
9778
4.51k
      break;
9779
1.44k
    case T_CLASS_C:
9780
1.44k
      if (ce) {
9781
990
        if ((ce->ce_flags & ZEND_ACC_TRAIT) != 0) {
9782
591
          return 0;
9783
591
        } else {
9784
399
          ZVAL_STR_COPY(zv, ce->name);
9785
399
        }
9786
990
      } else {
9787
457
        ZVAL_EMPTY_STRING(zv);
9788
457
      }
9789
856
      break;
9790
856
    case T_TRAIT_C:
9791
694
      if (ce && (ce->ce_flags & ZEND_ACC_TRAIT) != 0) {
9792
198
        ZVAL_STR_COPY(zv, ce->name);
9793
496
      } else {
9794
496
        ZVAL_EMPTY_STRING(zv);
9795
496
      }
9796
694
      break;
9797
1.09k
    case T_NS_C:
9798
1.09k
      if (FC(current_namespace)) {
9799
824
        ZVAL_STR_COPY(zv, FC(current_namespace));
9800
824
      } else {
9801
270
        ZVAL_EMPTY_STRING(zv);
9802
270
      }
9803
1.09k
      break;
9804
17.7k
    EMPTY_SWITCH_DEFAULT_CASE()
9805
17.7k
  }
9806
9807
17.1k
  return 1;
9808
17.7k
}
9809
/* }}} */
9810
9811
ZEND_API bool zend_is_op_long_compatible(const zval *op)
9812
71.4k
{
9813
71.4k
  if (Z_TYPE_P(op) == IS_ARRAY) {
9814
272
    return false;
9815
272
  }
9816
9817
71.1k
  if (Z_TYPE_P(op) == IS_DOUBLE
9818
71.1k
    && !zend_is_long_compatible(Z_DVAL_P(op), zend_dval_to_lval(Z_DVAL_P(op)))) {
9819
15.4k
    return false;
9820
15.4k
  }
9821
9822
55.6k
  if (Z_TYPE_P(op) == IS_STRING) {
9823
9.82k
    double dval = 0;
9824
9.82k
    uint8_t is_num = is_numeric_str_function(Z_STR_P(op), NULL, &dval);
9825
9.82k
    if (is_num == 0 || (is_num == IS_DOUBLE && !zend_is_long_compatible(dval, zend_dval_to_lval(dval)))) {
9826
4.80k
      return false;
9827
4.80k
    }
9828
9.82k
  }
9829
9830
50.8k
  return true;
9831
55.6k
}
9832
9833
ZEND_API bool zend_binary_op_produces_error(uint32_t opcode, const zval *op1, const zval *op2) /* {{{ */
9834
244k
{
9835
244k
  if ((opcode == ZEND_CONCAT || opcode == ZEND_FAST_CONCAT)) {
9836
    /* Array to string warning. */
9837
40.0k
    return Z_TYPE_P(op1) == IS_ARRAY || Z_TYPE_P(op2) == IS_ARRAY;
9838
40.0k
  }
9839
9840
204k
  if (!(opcode == ZEND_ADD || opcode == ZEND_SUB || opcode == ZEND_MUL || opcode == ZEND_DIV
9841
204k
               || opcode == ZEND_POW || opcode == ZEND_MOD || opcode == ZEND_SL || opcode == ZEND_SR
9842
204k
               || opcode == ZEND_BW_OR || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR)) {
9843
    /* Only the numeric operations throw errors. */
9844
24.8k
    return 0;
9845
24.8k
  }
9846
9847
179k
  if (Z_TYPE_P(op1) == IS_ARRAY || Z_TYPE_P(op2) == IS_ARRAY) {
9848
11.4k
    if (opcode == ZEND_ADD && Z_TYPE_P(op1) == IS_ARRAY && Z_TYPE_P(op2) == IS_ARRAY) {
9849
      /* Adding two arrays is allowed. */
9850
6.53k
      return 0;
9851
6.53k
    }
9852
9853
    /* Numeric operators throw when one of the operands is an array. */
9854
4.93k
    return 1;
9855
11.4k
  }
9856
9857
  /* While basic arithmetic operators always produce numeric string errors,
9858
   * bitwise operators don't produce errors if both operands are strings */
9859
167k
  if ((opcode == ZEND_BW_OR || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR)
9860
167k
    && Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
9861
26.9k
    return 0;
9862
26.9k
  }
9863
9864
140k
  if (Z_TYPE_P(op1) == IS_STRING
9865
140k
    && !is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), NULL, NULL, 0)) {
9866
13.6k
    return 1;
9867
13.6k
  }
9868
9869
127k
  if (Z_TYPE_P(op2) == IS_STRING
9870
127k
    && !is_numeric_string(Z_STRVAL_P(op2), Z_STRLEN_P(op2), NULL, NULL, 0)) {
9871
4.37k
    return 1;
9872
4.37k
  }
9873
9874
122k
  if ((opcode == ZEND_MOD && zval_get_long(op2) == 0)
9875
122k
      || (opcode == ZEND_DIV && zval_get_double(op2) == 0.0)) {
9876
    /* Division by zero throws an error. */
9877
6.55k
    return 1;
9878
6.55k
  }
9879
116k
  if ((opcode == ZEND_POW) && zval_get_double(op1) == 0 && zval_get_double(op2) < 0) {
9880
    /* 0 ** (<0) throws a division by zero error. */
9881
263
    return 1;
9882
263
  }
9883
115k
  if ((opcode == ZEND_SL || opcode == ZEND_SR) && zval_get_long(op2) < 0) {
9884
    /* Shift by negative number throws an error. */
9885
643
    return 1;
9886
643
  }
9887
9888
  /* Operation which cast float/float-strings to integers might produce incompatible float to int errors */
9889
115k
  if (opcode == ZEND_SL || opcode == ZEND_SR || opcode == ZEND_BW_OR
9890
115k
      || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR || opcode == ZEND_MOD) {
9891
38.6k
    return !zend_is_op_long_compatible(op1) || !zend_is_op_long_compatible(op2);
9892
38.6k
  }
9893
9894
76.6k
  return 0;
9895
115k
}
9896
/* }}} */
9897
9898
static inline bool zend_try_ct_eval_binary_op(zval *result, uint32_t opcode, zval *op1, zval *op2) /* {{{ */
9899
199k
{
9900
199k
  if (zend_binary_op_produces_error(opcode, op1, op2)) {
9901
38.5k
    return 0;
9902
38.5k
  }
9903
9904
160k
  binary_op_type fn = get_binary_op(opcode);
9905
160k
  fn(result, op1, op2);
9906
160k
  return 1;
9907
199k
}
9908
/* }}} */
9909
9910
ZEND_API bool zend_unary_op_produces_error(uint32_t opcode, const zval *op)
9911
37.0k
{
9912
37.0k
  if (opcode == ZEND_BW_NOT) {
9913
    /* BW_NOT on string does not convert the string into an integer. */
9914
6.85k
    if (Z_TYPE_P(op) == IS_STRING) {
9915
1.82k
      return 0;
9916
1.82k
    }
9917
5.03k
    return Z_TYPE_P(op) <= IS_TRUE || !zend_is_op_long_compatible(op);
9918
6.85k
  }
9919
9920
30.1k
  return 0;
9921
37.0k
}
9922
9923
static inline bool zend_try_ct_eval_unary_op(zval *result, uint32_t opcode, zval *op) /* {{{ */
9924
36.5k
{
9925
36.5k
  if (zend_unary_op_produces_error(opcode, op)) {
9926
1.55k
    return 0;
9927
1.55k
  }
9928
9929
34.9k
  unary_op_type fn = get_unary_op(opcode);
9930
34.9k
  fn(result, op);
9931
34.9k
  return 1;
9932
36.5k
}
9933
/* }}} */
9934
9935
static inline bool zend_try_ct_eval_unary_pm(zval *result, zend_ast_kind kind, zval *op) /* {{{ */
9936
43.9k
{
9937
43.9k
  zval right;
9938
43.9k
  ZVAL_LONG(&right, (kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
9939
43.9k
  return zend_try_ct_eval_binary_op(result, ZEND_MUL, op, &right);
9940
43.9k
}
9941
/* }}} */
9942
9943
static inline void zend_ct_eval_greater(zval *result, zend_ast_kind kind, zval *op1, zval *op2) /* {{{ */
9944
9.60k
{
9945
9.60k
  binary_op_type fn = kind == ZEND_AST_GREATER
9946
9.60k
    ? is_smaller_function : is_smaller_or_equal_function;
9947
9.60k
  fn(result, op2, op1);
9948
9.60k
}
9949
/* }}} */
9950
9951
static bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */
9952
996k
{
9953
996k
  zend_ast_list *list = zend_ast_get_list(ast);
9954
996k
  zend_ast *last_elem_ast = NULL;
9955
996k
  uint32_t i;
9956
996k
  bool is_constant = 1;
9957
9958
996k
  if (ast->attr == ZEND_ARRAY_SYNTAX_LIST) {
9959
6
    zend_error(E_COMPILE_ERROR, "Cannot use list() as standalone expression");
9960
6
  }
9961
9962
  /* First ensure that *all* child nodes are constant and by-val */
9963
2.61M
  for (i = 0; i < list->children; ++i) {
9964
1.61M
    zend_ast *elem_ast = list->child[i];
9965
9966
1.61M
    if (elem_ast == NULL) {
9967
      /* Report error at line of last non-empty element */
9968
134
      if (last_elem_ast) {
9969
56
        CG(zend_lineno) = zend_ast_get_lineno(last_elem_ast);
9970
56
      }
9971
134
      zend_error(E_COMPILE_ERROR, "Cannot use empty array elements in arrays");
9972
134
    }
9973
9974
1.61M
    if (elem_ast->kind != ZEND_AST_UNPACK) {
9975
1.61M
      zend_eval_const_expr(&elem_ast->child[0]);
9976
1.61M
      zend_eval_const_expr(&elem_ast->child[1]);
9977
9978
1.61M
      if (elem_ast->attr /* by_ref */ || elem_ast->child[0]->kind != ZEND_AST_ZVAL
9979
1.61M
        || (elem_ast->child[1] && elem_ast->child[1]->kind != ZEND_AST_ZVAL)
9980
1.61M
      ) {
9981
956k
        is_constant = 0;
9982
956k
      }
9983
1.61M
    } else {
9984
3.40k
      zend_eval_const_expr(&elem_ast->child[0]);
9985
9986
3.40k
      if (elem_ast->child[0]->kind != ZEND_AST_ZVAL) {
9987
2.31k
        is_constant = 0;
9988
2.31k
      }
9989
3.40k
    }
9990
9991
1.61M
    last_elem_ast = elem_ast;
9992
1.61M
  }
9993
9994
996k
  if (!is_constant) {
9995
896k
    return 0;
9996
896k
  }
9997
9998
100k
  if (!list->children) {
9999
19.0k
    ZVAL_EMPTY_ARRAY(result);
10000
19.0k
    return 1;
10001
19.0k
  }
10002
10003
81.0k
  array_init_size(result, list->children);
10004
494k
  for (i = 0; i < list->children; ++i) {
10005
414k
    zend_ast *elem_ast = list->child[i];
10006
414k
    zend_ast *value_ast = elem_ast->child[0];
10007
414k
    zend_ast *key_ast;
10008
10009
414k
    zval *value = zend_ast_get_zval(value_ast);
10010
414k
    if (elem_ast->kind == ZEND_AST_UNPACK) {
10011
940
      if (Z_TYPE_P(value) == IS_ARRAY) {
10012
928
        HashTable *ht = Z_ARRVAL_P(value);
10013
928
        zval *val;
10014
928
        zend_string *key;
10015
10016
11.5k
        ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
10017
11.5k
          if (key) {
10018
840
            zend_hash_update(Z_ARRVAL_P(result), key, val);
10019
4.45k
          } else if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), val)) {
10020
14
            zval_ptr_dtor(result);
10021
14
            return 0;
10022
14
          }
10023
5.27k
          Z_TRY_ADDREF_P(val);
10024
5.27k
        } ZEND_HASH_FOREACH_END();
10025
10026
914
        continue;
10027
928
      } else {
10028
12
        zend_error_noreturn(E_COMPILE_ERROR, "Only arrays and Traversables can be unpacked, %s given", zend_zval_value_name(value));
10029
12
      }
10030
940
    }
10031
10032
413k
    Z_TRY_ADDREF_P(value);
10033
10034
413k
    key_ast = elem_ast->child[1];
10035
413k
    if (key_ast) {
10036
15.4k
      zval *key = zend_ast_get_zval(key_ast);
10037
15.4k
      switch (Z_TYPE_P(key)) {
10038
6.12k
        case IS_LONG:
10039
6.12k
          zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(key), value);
10040
6.12k
          break;
10041
7.36k
        case IS_STRING:
10042
7.36k
          zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(key), value);
10043
7.36k
          break;
10044
1.29k
        case IS_DOUBLE: {
10045
1.29k
          zend_long lval = zend_dval_to_lval(Z_DVAL_P(key));
10046
          /* Incompatible float will generate an error, leave this to run-time */
10047
1.29k
          if (!zend_is_long_compatible(Z_DVAL_P(key), lval)) {
10048
811
            zval_ptr_dtor_nogc(value);
10049
811
            zval_ptr_dtor(result);
10050
811
            return 0;
10051
811
          }
10052
481
          zend_hash_index_update(Z_ARRVAL_P(result), lval, value);
10053
481
          break;
10054
1.29k
        }
10055
256
        case IS_FALSE:
10056
256
          zend_hash_index_update(Z_ARRVAL_P(result), 0, value);
10057
256
          break;
10058
309
        case IS_TRUE:
10059
309
          zend_hash_index_update(Z_ARRVAL_P(result), 1, value);
10060
309
          break;
10061
79
        case IS_NULL:
10062
79
          zend_hash_update(Z_ARRVAL_P(result), ZSTR_EMPTY_ALLOC(), value);
10063
79
          break;
10064
3
        default:
10065
3
          zend_error_noreturn(E_COMPILE_ERROR, "Illegal offset type");
10066
0
          break;
10067
15.4k
      }
10068
398k
    } else if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), value)) {
10069
114
      zval_ptr_dtor_nogc(value);
10070
114
      zval_ptr_dtor(result);
10071
114
      return 0;
10072
114
    }
10073
413k
  }
10074
10075
80.1k
  return 1;
10076
81.0k
}
10077
/* }}} */
10078
10079
static void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */
10080
319k
{
10081
319k
  zend_ast *left_ast = ast->child[0];
10082
319k
  zend_ast *right_ast = ast->child[1];
10083
319k
  uint32_t opcode = ast->attr;
10084
10085
319k
  znode left_node, right_node;
10086
10087
319k
  zend_compile_expr(&left_node, left_ast);
10088
319k
  zend_compile_expr(&right_node, right_ast);
10089
10090
319k
  if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
10091
108k
    if (zend_try_ct_eval_binary_op(&result->u.constant, opcode,
10092
108k
        &left_node.u.constant, &right_node.u.constant)
10093
108k
    ) {
10094
101k
      result->op_type = IS_CONST;
10095
101k
      zval_ptr_dtor(&left_node.u.constant);
10096
101k
      zval_ptr_dtor(&right_node.u.constant);
10097
101k
      return;
10098
101k
    }
10099
108k
  }
10100
10101
218k
  do {
10102
218k
    if (opcode == ZEND_IS_EQUAL || opcode == ZEND_IS_NOT_EQUAL) {
10103
23.5k
      if (left_node.op_type == IS_CONST) {
10104
415
        if (Z_TYPE(left_node.u.constant) == IS_FALSE) {
10105
111
          opcode = (opcode == ZEND_IS_NOT_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
10106
111
          zend_emit_op_tmp(result, opcode, &right_node, NULL);
10107
111
          break;
10108
304
        } else if (Z_TYPE(left_node.u.constant) == IS_TRUE) {
10109
115
          opcode = (opcode == ZEND_IS_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
10110
115
          zend_emit_op_tmp(result, opcode, &right_node, NULL);
10111
115
          break;
10112
115
        }
10113
23.1k
      } else if (right_node.op_type == IS_CONST) {
10114
16.4k
        if (Z_TYPE(right_node.u.constant) == IS_FALSE) {
10115
797
          opcode = (opcode == ZEND_IS_NOT_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
10116
797
          zend_emit_op_tmp(result, opcode, &left_node, NULL);
10117
797
          break;
10118
15.6k
        } else if (Z_TYPE(right_node.u.constant) == IS_TRUE) {
10119
448
          opcode = (opcode == ZEND_IS_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
10120
448
          zend_emit_op_tmp(result, opcode, &left_node, NULL);
10121
448
          break;
10122
448
        }
10123
16.4k
      }
10124
194k
    } else if (opcode == ZEND_IS_IDENTICAL || opcode == ZEND_IS_NOT_IDENTICAL) {
10125
      /* convert $x === null to is_null($x) (i.e. ZEND_TYPE_CHECK opcode). Do the same thing for false/true. (covers IS_NULL, IS_FALSE, and IS_TRUE) */
10126
3.74k
      if (left_node.op_type == IS_CONST) {
10127
569
        if (Z_TYPE(left_node.u.constant) <= IS_TRUE && Z_TYPE(left_node.u.constant) >= IS_NULL) {
10128
291
          zend_op *opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &right_node, NULL);
10129
291
          opline->extended_value =
10130
291
            (opcode == ZEND_IS_IDENTICAL) ?
10131
70
              (1 << Z_TYPE(left_node.u.constant)) :
10132
291
              (MAY_BE_ANY - (1 << Z_TYPE(left_node.u.constant)));
10133
291
          return;
10134
291
        }
10135
3.17k
      } else if (right_node.op_type == IS_CONST) {
10136
1.70k
        if (Z_TYPE(right_node.u.constant) <= IS_TRUE && Z_TYPE(right_node.u.constant) >= IS_NULL) {
10137
699
          zend_op *opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &left_node, NULL);
10138
699
          opline->extended_value =
10139
699
            (opcode == ZEND_IS_IDENTICAL) ?
10140
321
              (1 << Z_TYPE(right_node.u.constant)) :
10141
699
              (MAY_BE_ANY - (1 << Z_TYPE(right_node.u.constant)));
10142
699
          return;
10143
699
        }
10144
1.70k
      }
10145
190k
    } else if (opcode == ZEND_CONCAT) {
10146
      /* convert constant operands to strings at compile-time */
10147
73.0k
      if (left_node.op_type == IS_CONST) {
10148
16.6k
        if (Z_TYPE(left_node.u.constant) == IS_ARRAY) {
10149
328
          zend_emit_op_tmp(&left_node, ZEND_CAST, &left_node, NULL)->extended_value = IS_STRING;
10150
16.3k
        } else {
10151
16.3k
          convert_to_string(&left_node.u.constant);
10152
16.3k
        }
10153
16.6k
      }
10154
73.0k
      if (right_node.op_type == IS_CONST) {
10155
24.8k
        if (Z_TYPE(right_node.u.constant) == IS_ARRAY) {
10156
150
          zend_emit_op_tmp(&right_node, ZEND_CAST, &right_node, NULL)->extended_value = IS_STRING;
10157
24.6k
        } else {
10158
24.6k
          convert_to_string(&right_node.u.constant);
10159
24.6k
        }
10160
24.8k
      }
10161
73.0k
      if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
10162
0
        opcode = ZEND_FAST_CONCAT;
10163
0
      }
10164
73.0k
    }
10165
215k
    zend_emit_op_tmp(result, opcode, &left_node, &right_node);
10166
215k
  } while (0);
10167
218k
}
10168
/* }}} */
10169
10170
/* We do not use zend_compile_binary_op for this because we want to retain the left-to-right
10171
 * evaluation order. */
10172
static void zend_compile_greater(znode *result, zend_ast *ast) /* {{{ */
10173
14.5k
{
10174
14.5k
  zend_ast *left_ast = ast->child[0];
10175
14.5k
  zend_ast *right_ast = ast->child[1];
10176
14.5k
  znode left_node, right_node;
10177
10178
14.5k
  ZEND_ASSERT(ast->kind == ZEND_AST_GREATER || ast->kind == ZEND_AST_GREATER_EQUAL);
10179
10180
14.5k
  zend_compile_expr(&left_node, left_ast);
10181
14.5k
  zend_compile_expr(&right_node, right_ast);
10182
10183
14.5k
  if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
10184
5.94k
    result->op_type = IS_CONST;
10185
5.94k
    zend_ct_eval_greater(&result->u.constant, ast->kind,
10186
5.94k
      &left_node.u.constant, &right_node.u.constant);
10187
5.94k
    zval_ptr_dtor(&left_node.u.constant);
10188
5.94k
    zval_ptr_dtor(&right_node.u.constant);
10189
5.94k
    return;
10190
5.94k
  }
10191
10192
8.60k
  zend_emit_op_tmp(result,
10193
8.60k
    ast->kind == ZEND_AST_GREATER ? ZEND_IS_SMALLER : ZEND_IS_SMALLER_OR_EQUAL,
10194
8.60k
    &right_node, &left_node);
10195
8.60k
}
10196
/* }}} */
10197
10198
static void zend_compile_unary_op(znode *result, zend_ast *ast) /* {{{ */
10199
52.4k
{
10200
52.4k
  zend_ast *expr_ast = ast->child[0];
10201
52.4k
  uint32_t opcode = ast->attr;
10202
10203
52.4k
  znode expr_node;
10204
52.4k
  zend_compile_expr(&expr_node, expr_ast);
10205
10206
52.4k
  if (expr_node.op_type == IS_CONST
10207
52.4k
      && zend_try_ct_eval_unary_op(&result->u.constant, opcode, &expr_node.u.constant)) {
10208
20.6k
    result->op_type = IS_CONST;
10209
20.6k
    zval_ptr_dtor(&expr_node.u.constant);
10210
20.6k
    return;
10211
20.6k
  }
10212
10213
31.8k
  zend_emit_op_tmp(result, opcode, &expr_node, NULL);
10214
31.8k
}
10215
/* }}} */
10216
10217
static void zend_compile_unary_pm(znode *result, zend_ast *ast) /* {{{ */
10218
41.9k
{
10219
41.9k
  zend_ast *expr_ast = ast->child[0];
10220
41.9k
  znode expr_node, right_node;
10221
10222
41.9k
  ZEND_ASSERT(ast->kind == ZEND_AST_UNARY_PLUS || ast->kind == ZEND_AST_UNARY_MINUS);
10223
10224
41.9k
  zend_compile_expr(&expr_node, expr_ast);
10225
10226
41.9k
  if (expr_node.op_type == IS_CONST
10227
41.9k
    && zend_try_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant)) {
10228
20.2k
    result->op_type = IS_CONST;
10229
20.2k
    zval_ptr_dtor(&expr_node.u.constant);
10230
20.2k
    return;
10231
20.2k
  }
10232
10233
21.6k
  right_node.op_type = IS_CONST;
10234
21.6k
  ZVAL_LONG(&right_node.u.constant, (ast->kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
10235
21.6k
  zend_emit_op_tmp(result, ZEND_MUL, &expr_node, &right_node);
10236
21.6k
}
10237
/* }}} */
10238
10239
static void zend_compile_short_circuiting(znode *result, zend_ast *ast) /* {{{ */
10240
12.8k
{
10241
12.8k
  zend_ast *left_ast = ast->child[0];
10242
12.8k
  zend_ast *right_ast = ast->child[1];
10243
10244
12.8k
  znode left_node, right_node;
10245
12.8k
  zend_op *opline_jmpz, *opline_bool;
10246
12.8k
  uint32_t opnum_jmpz;
10247
10248
12.8k
  ZEND_ASSERT(ast->kind == ZEND_AST_AND || ast->kind == ZEND_AST_OR);
10249
10250
12.8k
  zend_compile_expr(&left_node, left_ast);
10251
10252
12.8k
  if (left_node.op_type == IS_CONST) {
10253
3.03k
    if ((ast->kind == ZEND_AST_AND && !zend_is_true(&left_node.u.constant))
10254
3.03k
     || (ast->kind == ZEND_AST_OR && zend_is_true(&left_node.u.constant))) {
10255
1.49k
      result->op_type = IS_CONST;
10256
1.49k
      ZVAL_BOOL(&result->u.constant, zend_is_true(&left_node.u.constant));
10257
1.54k
    } else {
10258
1.54k
      zend_compile_expr(&right_node, right_ast);
10259
10260
1.54k
      if (right_node.op_type == IS_CONST) {
10261
1.01k
        result->op_type = IS_CONST;
10262
1.01k
        ZVAL_BOOL(&result->u.constant, zend_is_true(&right_node.u.constant));
10263
10264
1.01k
        zval_ptr_dtor(&right_node.u.constant);
10265
1.01k
      } else {
10266
523
        zend_emit_op_tmp(result, ZEND_BOOL, &right_node, NULL);
10267
523
      }
10268
1.54k
    }
10269
10270
3.03k
    zval_ptr_dtor(&left_node.u.constant);
10271
3.03k
    return;
10272
3.03k
  }
10273
10274
9.79k
  opnum_jmpz = get_next_op_number();
10275
9.79k
  opline_jmpz = zend_emit_op(NULL, ast->kind == ZEND_AST_AND ? ZEND_JMPZ_EX : ZEND_JMPNZ_EX,
10276
9.79k
    &left_node, NULL);
10277
10278
9.79k
  if (left_node.op_type == IS_TMP_VAR) {
10279
5.54k
    SET_NODE(opline_jmpz->result, &left_node);
10280
5.54k
    GET_NODE(result, opline_jmpz->result);
10281
5.54k
  } else {
10282
4.25k
    zend_make_tmp_result(result, opline_jmpz);
10283
4.25k
  }
10284
10285
9.79k
  zend_compile_expr(&right_node, right_ast);
10286
10287
9.79k
  opline_bool = zend_emit_op(NULL, ZEND_BOOL, &right_node, NULL);
10288
9.79k
  SET_NODE(opline_bool->result, result);
10289
10290
9.79k
  zend_update_jump_target_to_next(opnum_jmpz);
10291
9.79k
}
10292
/* }}} */
10293
10294
static void zend_compile_post_incdec(znode *result, zend_ast *ast) /* {{{ */
10295
10.2k
{
10296
10.2k
  zend_ast *var_ast = ast->child[0];
10297
10.2k
  ZEND_ASSERT(ast->kind == ZEND_AST_POST_INC || ast->kind == ZEND_AST_POST_DEC);
10298
10299
10.2k
  zend_ensure_writable_variable(var_ast);
10300
10301
10.2k
  if (var_ast->kind == ZEND_AST_PROP || var_ast->kind == ZEND_AST_NULLSAFE_PROP) {
10302
1.22k
    zend_op *opline = zend_compile_prop(NULL, var_ast, BP_VAR_RW, 0);
10303
1.22k
    opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ;
10304
1.22k
    zend_make_tmp_result(result, opline);
10305
9.03k
  } else if (var_ast->kind == ZEND_AST_STATIC_PROP) {
10306
561
    zend_op *opline = zend_compile_static_prop(NULL, var_ast, BP_VAR_RW, 0, 0);
10307
561
    opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_STATIC_PROP : ZEND_POST_DEC_STATIC_PROP;
10308
561
    zend_make_tmp_result(result, opline);
10309
8.47k
  } else {
10310
8.47k
    znode var_node;
10311
8.47k
    zend_op *opline = zend_compile_var(&var_node, var_ast, BP_VAR_RW, 0);
10312
8.47k
    if (opline && opline->opcode == ZEND_FETCH_DIM_RW) {
10313
276
      opline->extended_value = ZEND_FETCH_DIM_INCDEC;
10314
276
    }
10315
8.47k
    zend_emit_op_tmp(result, ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC : ZEND_POST_DEC,
10316
8.47k
      &var_node, NULL);
10317
8.47k
  }
10318
10.2k
}
10319
/* }}} */
10320
10321
static void zend_compile_pre_incdec(znode *result, zend_ast *ast) /* {{{ */
10322
6.93k
{
10323
6.93k
  zend_ast *var_ast = ast->child[0];
10324
6.93k
  ZEND_ASSERT(ast->kind == ZEND_AST_PRE_INC || ast->kind == ZEND_AST_PRE_DEC);
10325
10326
6.93k
  zend_ensure_writable_variable(var_ast);
10327
10328
6.93k
  if (var_ast->kind == ZEND_AST_PROP || var_ast->kind == ZEND_AST_NULLSAFE_PROP) {
10329
1.26k
    zend_op *opline = zend_compile_prop(result, var_ast, BP_VAR_RW, 0);
10330
1.26k
    opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ;
10331
1.26k
    opline->result_type = IS_TMP_VAR;
10332
1.26k
    result->op_type = IS_TMP_VAR;
10333
5.67k
  } else if (var_ast->kind == ZEND_AST_STATIC_PROP) {
10334
416
    zend_op *opline = zend_compile_static_prop(result, var_ast, BP_VAR_RW, 0, 0);
10335
416
    opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_STATIC_PROP : ZEND_PRE_DEC_STATIC_PROP;
10336
416
    opline->result_type = IS_TMP_VAR;
10337
416
    result->op_type = IS_TMP_VAR;
10338
5.25k
  } else {
10339
5.25k
    znode var_node;
10340
5.25k
    zend_op *opline = zend_compile_var(&var_node, var_ast, BP_VAR_RW, 0);
10341
5.25k
    if (opline && opline->opcode == ZEND_FETCH_DIM_RW) {
10342
297
      opline->extended_value = ZEND_FETCH_DIM_INCDEC;
10343
297
    }
10344
5.25k
    zend_emit_op_tmp(result, ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC : ZEND_PRE_DEC,
10345
5.25k
      &var_node, NULL);
10346
5.25k
  }
10347
6.93k
}
10348
/* }}} */
10349
10350
static void zend_compile_cast(znode *result, zend_ast *ast) /* {{{ */
10351
2.59k
{
10352
2.59k
  zend_ast *expr_ast = ast->child[0];
10353
2.59k
  znode expr_node;
10354
2.59k
  zend_op *opline;
10355
10356
2.59k
  zend_compile_expr(&expr_node, expr_ast);
10357
10358
2.59k
  if (ast->attr == _IS_BOOL) {
10359
108
    opline = zend_emit_op_tmp(result, ZEND_BOOL, &expr_node, NULL);
10360
2.48k
  } else if (ast->attr == IS_NULL) {
10361
15
    zend_error(E_COMPILE_ERROR, "The (unset) cast is no longer supported");
10362
2.47k
  } else {
10363
2.47k
    opline = zend_emit_op_tmp(result, ZEND_CAST, &expr_node, NULL);
10364
2.47k
    opline->extended_value = ast->attr;
10365
2.47k
  }
10366
2.59k
}
10367
/* }}} */
10368
10369
static void zend_compile_shorthand_conditional(znode *result, zend_ast *ast) /* {{{ */
10370
2.28k
{
10371
2.28k
  zend_ast *cond_ast = ast->child[0];
10372
2.28k
  zend_ast *false_ast = ast->child[2];
10373
10374
2.28k
  znode cond_node, false_node;
10375
2.28k
  zend_op *opline_qm_assign;
10376
2.28k
  uint32_t opnum_jmp_set;
10377
10378
2.28k
  ZEND_ASSERT(ast->child[1] == NULL);
10379
10380
2.28k
  zend_compile_expr(&cond_node, cond_ast);
10381
10382
2.28k
  opnum_jmp_set = get_next_op_number();
10383
2.28k
  zend_emit_op_tmp(result, ZEND_JMP_SET, &cond_node, NULL);
10384
10385
2.28k
  zend_compile_expr(&false_node, false_ast);
10386
10387
2.28k
  opline_qm_assign = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &false_node, NULL);
10388
2.28k
  SET_NODE(opline_qm_assign->result, result);
10389
10390
2.28k
  zend_update_jump_target_to_next(opnum_jmp_set);
10391
2.28k
}
10392
/* }}} */
10393
10394
static void zend_compile_conditional(znode *result, zend_ast *ast) /* {{{ */
10395
6.61k
{
10396
6.61k
  zend_ast *cond_ast = ast->child[0];
10397
6.61k
  zend_ast *true_ast = ast->child[1];
10398
6.61k
  zend_ast *false_ast = ast->child[2];
10399
10400
6.61k
  znode cond_node, true_node, false_node;
10401
6.61k
  zend_op *opline_qm_assign2;
10402
6.61k
  uint32_t opnum_jmpz, opnum_jmp;
10403
10404
6.61k
  if (cond_ast->kind == ZEND_AST_CONDITIONAL
10405
6.61k
      && cond_ast->attr != ZEND_PARENTHESIZED_CONDITIONAL) {
10406
550
    if (cond_ast->child[1]) {
10407
33
      if (true_ast) {
10408
23
        zend_error(E_COMPILE_ERROR,
10409
23
          "Unparenthesized `a ? b : c ? d : e` is not supported. "
10410
23
          "Use either `(a ? b : c) ? d : e` or `a ? b : (c ? d : e)`");
10411
23
      } else {
10412
10
        zend_error(E_COMPILE_ERROR,
10413
10
          "Unparenthesized `a ? b : c ?: d` is not supported. "
10414
10
          "Use either `(a ? b : c) ?: d` or `a ? b : (c ?: d)`");
10415
10
      }
10416
517
    } else {
10417
517
      if (true_ast) {
10418
6
        zend_error(E_COMPILE_ERROR,
10419
6
          "Unparenthesized `a ?: b ? c : d` is not supported. "
10420
6
          "Use either `(a ?: b) ? c : d` or `a ?: (b ? c : d)`");
10421
511
      } else {
10422
        /* This case is harmless:  (a ?: b) ?: c always produces the same result
10423
         * as a ?: (b ?: c). */
10424
511
      }
10425
517
    }
10426
550
  }
10427
10428
6.61k
  if (!true_ast) {
10429
2.28k
    zend_compile_shorthand_conditional(result, ast);
10430
2.28k
    return;
10431
2.28k
  }
10432
10433
4.33k
  zend_compile_expr(&cond_node, cond_ast);
10434
10435
4.33k
  opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
10436
10437
4.33k
  zend_compile_expr(&true_node, true_ast);
10438
10439
4.33k
  zend_emit_op_tmp(result, ZEND_QM_ASSIGN, &true_node, NULL);
10440
10441
4.33k
  opnum_jmp = zend_emit_jump(0);
10442
10443
4.33k
  zend_update_jump_target_to_next(opnum_jmpz);
10444
10445
4.33k
  zend_compile_expr(&false_node, false_ast);
10446
10447
4.33k
  opline_qm_assign2 = zend_emit_op(NULL, ZEND_QM_ASSIGN, &false_node, NULL);
10448
4.33k
  SET_NODE(opline_qm_assign2->result, result);
10449
10450
4.33k
  zend_update_jump_target_to_next(opnum_jmp);
10451
4.33k
}
10452
/* }}} */
10453
10454
static void zend_compile_coalesce(znode *result, zend_ast *ast) /* {{{ */
10455
12.7k
{
10456
12.7k
  zend_ast *expr_ast = ast->child[0];
10457
12.7k
  zend_ast *default_ast = ast->child[1];
10458
10459
12.7k
  znode expr_node, default_node;
10460
12.7k
  zend_op *opline;
10461
12.7k
  uint32_t opnum;
10462
10463
12.7k
  zend_compile_var(&expr_node, expr_ast, BP_VAR_IS, 0);
10464
10465
12.7k
  opnum = get_next_op_number();
10466
12.7k
  zend_emit_op_tmp(result, ZEND_COALESCE, &expr_node, NULL);
10467
10468
12.7k
  zend_compile_expr(&default_node, default_ast);
10469
10470
12.7k
  opline = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &default_node, NULL);
10471
12.7k
  SET_NODE(opline->result, result);
10472
10473
12.7k
  opline = &CG(active_op_array)->opcodes[opnum];
10474
12.7k
  opline->op2.opline_num = get_next_op_number();
10475
12.7k
}
10476
/* }}} */
10477
10478
53.6k
static void znode_dtor(zval *zv) {
10479
53.6k
  znode *node = Z_PTR_P(zv);
10480
53.6k
  if (node->op_type == IS_CONST) {
10481
7.93k
    zval_ptr_dtor_nogc(&node->u.constant);
10482
7.93k
  }
10483
53.6k
  efree(node);
10484
53.6k
}
10485
10486
static void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */
10487
9.30k
{
10488
9.30k
  zend_ast *var_ast = ast->child[0];
10489
9.30k
  zend_ast *default_ast = ast->child[1];
10490
10491
9.30k
  znode var_node_is, var_node_w, default_node, assign_node, *node;
10492
9.30k
  zend_op *opline;
10493
9.30k
  uint32_t coalesce_opnum;
10494
9.30k
  bool need_frees = 0;
10495
10496
  /* Remember expressions compiled during the initial BP_VAR_IS lookup,
10497
   * to avoid double-evaluation when we compile again with BP_VAR_W. */
10498
9.30k
  HashTable *orig_memoized_exprs = CG(memoized_exprs);
10499
9.30k
  const zend_memoize_mode orig_memoize_mode = CG(memoize_mode);
10500
10501
9.30k
  zend_ensure_writable_variable(var_ast);
10502
9.30k
  if (is_this_fetch(var_ast)) {
10503
6
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
10504
6
  }
10505
10506
9.29k
  ALLOC_HASHTABLE(CG(memoized_exprs));
10507
9.29k
  zend_hash_init(CG(memoized_exprs), 0, NULL, znode_dtor, 0);
10508
10509
9.29k
  CG(memoize_mode) = ZEND_MEMOIZE_COMPILE;
10510
9.29k
  zend_compile_var(&var_node_is, var_ast, BP_VAR_IS, 0);
10511
10512
9.29k
  coalesce_opnum = get_next_op_number();
10513
9.29k
  zend_emit_op_tmp(result, ZEND_COALESCE, &var_node_is, NULL);
10514
10515
9.29k
  CG(memoize_mode) = ZEND_MEMOIZE_NONE;
10516
9.29k
  if (var_ast->kind == ZEND_AST_DIM) {
10517
6.07k
    zend_compile_expr_with_potential_assign_to_self(&default_node, default_ast, var_ast);
10518
6.07k
  } else {
10519
3.22k
    zend_compile_expr(&default_node, default_ast);
10520
3.22k
  }
10521
10522
9.29k
  CG(memoize_mode) = ZEND_MEMOIZE_FETCH;
10523
9.29k
  zend_compile_var(&var_node_w, var_ast, BP_VAR_W, 0);
10524
10525
  /* Reproduce some of the zend_compile_assign() opcode fixup logic here. */
10526
9.29k
  opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
10527
  /* Treat $GLOBALS['x'] assignment like assignment to variable. */
10528
9.29k
  zend_ast_kind kind = is_global_var_fetch(var_ast) ? ZEND_AST_VAR : var_ast->kind;
10529
9.29k
  switch (kind) {
10530
1.58k
    case ZEND_AST_VAR:
10531
1.58k
      zend_emit_op_tmp(&assign_node, ZEND_ASSIGN, &var_node_w, &default_node);
10532
1.58k
      break;
10533
592
    case ZEND_AST_STATIC_PROP:
10534
592
      opline->opcode = ZEND_ASSIGN_STATIC_PROP;
10535
592
      opline->result_type = IS_TMP_VAR;
10536
592
      var_node_w.op_type = IS_TMP_VAR;
10537
592
      zend_emit_op_data(&default_node);
10538
592
      assign_node = var_node_w;
10539
592
      break;
10540
5.42k
    case ZEND_AST_DIM:
10541
5.42k
      opline->opcode = ZEND_ASSIGN_DIM;
10542
5.42k
      opline->result_type = IS_TMP_VAR;
10543
5.42k
      var_node_w.op_type = IS_TMP_VAR;
10544
5.42k
      zend_emit_op_data(&default_node);
10545
5.42k
      assign_node = var_node_w;
10546
5.42k
      break;
10547
1.21k
    case ZEND_AST_PROP:
10548
1.21k
    case ZEND_AST_NULLSAFE_PROP:
10549
1.21k
      opline->opcode = ZEND_ASSIGN_OBJ;
10550
1.21k
      opline->result_type = IS_TMP_VAR;
10551
1.21k
      var_node_w.op_type = IS_TMP_VAR;
10552
1.21k
      zend_emit_op_data(&default_node);
10553
1.21k
      assign_node = var_node_w;
10554
1.21k
      break;
10555
0
    EMPTY_SWITCH_DEFAULT_CASE();
10556
9.29k
  }
10557
10558
8.81k
  opline = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &assign_node, NULL);
10559
8.81k
  SET_NODE(opline->result, result);
10560
10561
34.2k
  ZEND_HASH_FOREACH_PTR(CG(memoized_exprs), node) {
10562
34.2k
    if (node->op_type == IS_TMP_VAR || node->op_type == IS_VAR) {
10563
5.33k
      need_frees = 1;
10564
5.33k
      break;
10565
5.33k
    }
10566
34.2k
  } ZEND_HASH_FOREACH_END();
10567
10568
  /* Free DUPed expressions if there are any */
10569
8.81k
  if (need_frees) {
10570
5.33k
    uint32_t jump_opnum = zend_emit_jump(0);
10571
5.33k
    zend_update_jump_target_to_next(coalesce_opnum);
10572
98.3k
    ZEND_HASH_FOREACH_PTR(CG(memoized_exprs), node) {
10573
98.3k
      if (node->op_type == IS_TMP_VAR || node->op_type == IS_VAR) {
10574
44.9k
        zend_emit_op(NULL, ZEND_FREE, node, NULL);
10575
44.9k
      }
10576
98.3k
    } ZEND_HASH_FOREACH_END();
10577
5.33k
    zend_update_jump_target_to_next(jump_opnum);
10578
5.33k
  } else {
10579
3.47k
    zend_update_jump_target_to_next(coalesce_opnum);
10580
3.47k
  }
10581
10582
8.81k
  zend_hash_destroy(CG(memoized_exprs));
10583
8.81k
  FREE_HASHTABLE(CG(memoized_exprs));
10584
8.81k
  CG(memoized_exprs) = orig_memoized_exprs;
10585
8.81k
  CG(memoize_mode) = orig_memoize_mode;
10586
8.81k
}
10587
/* }}} */
10588
10589
static void zend_compile_print(znode *result, zend_ast *ast) /* {{{ */
10590
3.68k
{
10591
3.68k
  zend_op *opline;
10592
3.68k
  zend_ast *expr_ast = ast->child[0];
10593
10594
3.68k
  znode expr_node;
10595
3.68k
  zend_compile_expr(&expr_node, expr_ast);
10596
10597
3.68k
  opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL);
10598
3.68k
  opline->extended_value = 1;
10599
10600
3.68k
  result->op_type = IS_CONST;
10601
3.68k
  ZVAL_LONG(&result->u.constant, 1);
10602
3.68k
}
10603
/* }}} */
10604
10605
static void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */
10606
5.51k
{
10607
5.51k
  zend_ast *value_ast = ast->child[0];
10608
5.51k
  zend_ast *key_ast = ast->child[1];
10609
10610
5.51k
  znode value_node, key_node;
10611
5.51k
  znode *value_node_ptr = NULL, *key_node_ptr = NULL;
10612
5.51k
  zend_op *opline;
10613
5.51k
  bool returns_by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
10614
10615
5.51k
  zend_mark_function_as_generator();
10616
10617
5.51k
  if (key_ast) {
10618
513
    zend_compile_expr(&key_node, key_ast);
10619
513
    key_node_ptr = &key_node;
10620
513
  }
10621
10622
5.51k
  if (value_ast) {
10623
4.29k
    if (returns_by_ref && zend_is_variable(value_ast)) {
10624
202
      zend_assert_not_short_circuited(value_ast);
10625
202
      zend_compile_var(&value_node, value_ast, BP_VAR_W, 1);
10626
4.09k
    } else {
10627
4.09k
      zend_compile_expr(&value_node, value_ast);
10628
4.09k
    }
10629
4.29k
    value_node_ptr = &value_node;
10630
4.29k
  }
10631
10632
5.51k
  opline = zend_emit_op(result, ZEND_YIELD, value_node_ptr, key_node_ptr);
10633
10634
5.51k
  if (value_ast && returns_by_ref && zend_is_call(value_ast)) {
10635
639
    opline->extended_value = ZEND_RETURNS_FUNCTION;
10636
639
  }
10637
5.51k
}
10638
/* }}} */
10639
10640
static void zend_compile_yield_from(znode *result, zend_ast *ast) /* {{{ */
10641
692
{
10642
692
  zend_ast *expr_ast = ast->child[0];
10643
692
  znode expr_node;
10644
10645
692
  zend_mark_function_as_generator();
10646
10647
692
  if (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
10648
8
    zend_error_noreturn(E_COMPILE_ERROR,
10649
8
      "Cannot use \"yield from\" inside a by-reference generator");
10650
8
  }
10651
10652
684
  zend_compile_expr(&expr_node, expr_ast);
10653
684
  zend_emit_op_tmp(result, ZEND_YIELD_FROM, &expr_node, NULL);
10654
684
}
10655
/* }}} */
10656
10657
static void zend_compile_instanceof(znode *result, zend_ast *ast) /* {{{ */
10658
723
{
10659
723
  zend_ast *obj_ast = ast->child[0];
10660
723
  zend_ast *class_ast = ast->child[1];
10661
10662
723
  znode obj_node, class_node;
10663
723
  zend_op *opline;
10664
10665
723
  zend_compile_expr(&obj_node, obj_ast);
10666
723
  if (obj_node.op_type == IS_CONST) {
10667
78
    zend_do_free(&obj_node);
10668
78
    result->op_type = IS_CONST;
10669
78
    ZVAL_FALSE(&result->u.constant);
10670
78
    return;
10671
78
  }
10672
10673
645
  zend_compile_class_ref(&class_node, class_ast,
10674
645
    ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_EXCEPTION | ZEND_FETCH_CLASS_SILENT);
10675
10676
645
  opline = zend_emit_op_tmp(result, ZEND_INSTANCEOF, &obj_node, NULL);
10677
10678
645
  if (class_node.op_type == IS_CONST) {
10679
470
    opline->op2_type = IS_CONST;
10680
470
    opline->op2.constant = zend_add_class_name_literal(
10681
470
      Z_STR(class_node.u.constant));
10682
470
    opline->extended_value = zend_alloc_cache_slot();
10683
470
  } else {
10684
175
    SET_NODE(opline->op2, &class_node);
10685
175
  }
10686
645
}
10687
/* }}} */
10688
10689
static void zend_compile_include_or_eval(znode *result, zend_ast *ast) /* {{{ */
10690
9.66k
{
10691
9.66k
  zend_ast *expr_ast = ast->child[0];
10692
9.66k
  znode expr_node;
10693
9.66k
  zend_op *opline;
10694
10695
9.66k
  zend_do_extended_fcall_begin();
10696
9.66k
  zend_compile_expr(&expr_node, expr_ast);
10697
10698
9.66k
  opline = zend_emit_op(result, ZEND_INCLUDE_OR_EVAL, &expr_node, NULL);
10699
9.66k
  opline->extended_value = ast->attr;
10700
10701
9.66k
  zend_do_extended_fcall_end();
10702
9.66k
}
10703
/* }}} */
10704
10705
static void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
10706
6.99k
{
10707
6.99k
  zend_ast *var_ast = ast->child[0];
10708
10709
6.99k
  znode var_node;
10710
6.99k
  zend_op *opline = NULL;
10711
10712
6.99k
  ZEND_ASSERT(ast->kind == ZEND_AST_ISSET || ast->kind == ZEND_AST_EMPTY);
10713
10714
6.99k
  if (!zend_is_variable(var_ast)) {
10715
356
    if (ast->kind == ZEND_AST_EMPTY) {
10716
      /* empty(expr) can be transformed to !expr */
10717
297
      zend_ast *not_ast = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, var_ast);
10718
297
      zend_compile_expr(result, not_ast);
10719
297
      return;
10720
297
    } else {
10721
59
      zend_error_noreturn(E_COMPILE_ERROR,
10722
59
        "Cannot use isset() on the result of an expression "
10723
59
        "(you can use \"null !== expression\" instead)");
10724
59
    }
10725
356
  }
10726
10727
6.64k
  if (is_globals_fetch(var_ast)) {
10728
220
    result->op_type = IS_CONST;
10729
220
    ZVAL_BOOL(&result->u.constant, ast->kind == ZEND_AST_ISSET);
10730
220
    return;
10731
220
  }
10732
10733
6.42k
  if (is_global_var_fetch(var_ast)) {
10734
390
    if (!var_ast->child[1]) {
10735
7
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
10736
7
    }
10737
10738
383
    zend_compile_expr(&var_node, var_ast->child[1]);
10739
383
    if (var_node.op_type == IS_CONST) {
10740
300
      convert_to_string(&var_node.u.constant);
10741
300
    }
10742
10743
383
    opline = zend_emit_op_tmp(result, ZEND_ISSET_ISEMPTY_VAR, &var_node, NULL);
10744
383
    opline->extended_value =
10745
383
      ZEND_FETCH_GLOBAL | (ast->kind == ZEND_AST_EMPTY ? ZEND_ISEMPTY : 0);
10746
383
    return;
10747
390
  }
10748
10749
6.03k
  zend_short_circuiting_mark_inner(var_ast);
10750
6.03k
  switch (var_ast->kind) {
10751
1.93k
    case ZEND_AST_VAR:
10752
1.93k
      if (is_this_fetch(var_ast)) {
10753
101
        opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_THIS, NULL, NULL);
10754
101
        CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
10755
1.83k
      } else if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) {
10756
1.19k
        opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_CV, &var_node, NULL);
10757
1.19k
      } else {
10758
641
        opline = zend_compile_simple_var_no_cv(result, var_ast, BP_VAR_IS, 0);
10759
641
        opline->opcode = ZEND_ISSET_ISEMPTY_VAR;
10760
641
      }
10761
1.93k
      break;
10762
2.92k
    case ZEND_AST_DIM:
10763
2.92k
      opline = zend_compile_dim(result, var_ast, BP_VAR_IS, /* by_ref */ false);
10764
2.92k
      opline->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ;
10765
2.92k
      break;
10766
800
    case ZEND_AST_PROP:
10767
1.04k
    case ZEND_AST_NULLSAFE_PROP:
10768
1.04k
      opline = zend_compile_prop(result, var_ast, BP_VAR_IS, 0);
10769
1.04k
      opline->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ;
10770
1.04k
      break;
10771
126
    case ZEND_AST_STATIC_PROP:
10772
126
      opline = zend_compile_static_prop(result, var_ast, BP_VAR_IS, 0, 0);
10773
126
      opline->opcode = ZEND_ISSET_ISEMPTY_STATIC_PROP;
10774
126
      break;
10775
6.03k
    EMPTY_SWITCH_DEFAULT_CASE()
10776
6.03k
  }
10777
10778
6.01k
  result->op_type = opline->result_type = IS_TMP_VAR;
10779
6.01k
  if (!(ast->kind == ZEND_AST_ISSET)) {
10780
1.45k
    opline->extended_value |= ZEND_ISEMPTY;
10781
1.45k
  }
10782
6.01k
}
10783
/* }}} */
10784
10785
static void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
10786
909k
{
10787
909k
  zend_ast *expr_ast = ast->child[0];
10788
909k
  znode silence_node;
10789
10790
909k
  zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL);
10791
10792
909k
  if (expr_ast->kind == ZEND_AST_VAR) {
10793
    /* For @$var we need to force a FETCH instruction, otherwise the CV access will
10794
     * happen outside the silenced section. */
10795
420
    zend_compile_simple_var_no_cv(result, expr_ast, BP_VAR_R, 0 );
10796
909k
  } else {
10797
909k
    zend_compile_expr(result, expr_ast);
10798
909k
  }
10799
10800
909k
  zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL);
10801
909k
}
10802
/* }}} */
10803
10804
static void zend_compile_shell_exec(znode *result, zend_ast *ast) /* {{{ */
10805
6.69k
{
10806
6.69k
  zend_ast *expr_ast = ast->child[0];
10807
10808
6.69k
  zval fn_name;
10809
6.69k
  zend_ast *name_ast, *args_ast, *call_ast;
10810
10811
6.69k
  ZVAL_STRING(&fn_name, "shell_exec");
10812
6.69k
  name_ast = zend_ast_create_zval(&fn_name);
10813
6.69k
  args_ast = zend_ast_create_list(1, ZEND_AST_ARG_LIST, expr_ast);
10814
6.69k
  call_ast = zend_ast_create(ZEND_AST_CALL, name_ast, args_ast);
10815
10816
6.69k
  zend_compile_expr(result, call_ast);
10817
10818
6.69k
  zval_ptr_dtor(&fn_name);
10819
6.69k
}
10820
/* }}} */
10821
10822
static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
10823
64.6k
{
10824
64.6k
  zend_ast_list *list = zend_ast_get_list(ast);
10825
64.6k
  zend_op *opline;
10826
64.6k
  uint32_t i, opnum_init = -1;
10827
64.6k
  bool packed = 1;
10828
10829
64.6k
  if (zend_try_ct_eval_array(&result->u.constant, ast)) {
10830
42.5k
    result->op_type = IS_CONST;
10831
42.5k
    return;
10832
42.5k
  }
10833
10834
  /* Empty arrays are handled at compile-time */
10835
22.0k
  ZEND_ASSERT(list->children > 0);
10836
10837
144k
  for (i = 0; i < list->children; ++i) {
10838
122k
    zend_ast *elem_ast = list->child[i];
10839
122k
    zend_ast *value_ast, *key_ast;
10840
122k
    bool by_ref;
10841
122k
    znode value_node, key_node, *key_node_ptr = NULL;
10842
10843
122k
    if (elem_ast == NULL) {
10844
0
      zend_error(E_COMPILE_ERROR, "Cannot use empty array elements in arrays");
10845
0
    }
10846
10847
122k
    value_ast = elem_ast->child[0];
10848
10849
122k
    if (elem_ast->kind == ZEND_AST_UNPACK) {
10850
671
      zend_compile_expr(&value_node, value_ast);
10851
671
      if (i == 0) {
10852
375
        opnum_init = get_next_op_number();
10853
375
        opline = zend_emit_op_tmp(result, ZEND_INIT_ARRAY, NULL, NULL);
10854
375
      }
10855
671
      opline = zend_emit_op(NULL, ZEND_ADD_ARRAY_UNPACK, &value_node, NULL);
10856
671
      SET_NODE(opline->result, result);
10857
671
      continue;
10858
671
    }
10859
10860
121k
    key_ast = elem_ast->child[1];
10861
121k
    by_ref = elem_ast->attr;
10862
10863
121k
    if (key_ast) {
10864
5.19k
      zend_compile_expr(&key_node, key_ast);
10865
5.19k
      zend_handle_numeric_op(&key_node);
10866
5.19k
      key_node_ptr = &key_node;
10867
5.19k
    }
10868
10869
121k
    if (by_ref) {
10870
528
      zend_ensure_writable_variable(value_ast);
10871
528
      zend_compile_var(&value_node, value_ast, BP_VAR_W, 1);
10872
121k
    } else {
10873
121k
      zend_compile_expr(&value_node, value_ast);
10874
121k
    }
10875
10876
121k
    if (i == 0) {
10877
21.2k
      opnum_init = get_next_op_number();
10878
21.2k
      opline = zend_emit_op_tmp(result, ZEND_INIT_ARRAY, &value_node, key_node_ptr);
10879
21.2k
      opline->extended_value = list->children << ZEND_ARRAY_SIZE_SHIFT;
10880
100k
    } else {
10881
100k
      opline = zend_emit_op(NULL, ZEND_ADD_ARRAY_ELEMENT,
10882
100k
        &value_node, key_node_ptr);
10883
100k
      SET_NODE(opline->result, result);
10884
100k
    }
10885
121k
    opline->extended_value |= by_ref;
10886
10887
121k
    if (key_ast && key_node.op_type == IS_CONST && Z_TYPE(key_node.u.constant) == IS_STRING) {
10888
2.30k
      packed = 0;
10889
2.30k
    }
10890
121k
  }
10891
10892
  /* Add a flag to INIT_ARRAY if we know this array cannot be packed */
10893
21.8k
  if (!packed) {
10894
1.54k
    ZEND_ASSERT(opnum_init != (uint32_t)-1);
10895
1.54k
    opline = &CG(active_op_array)->opcodes[opnum_init];
10896
1.54k
    opline->extended_value |= ZEND_ARRAY_NOT_PACKED;
10897
1.54k
  }
10898
21.8k
}
10899
/* }}} */
10900
10901
static void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */
10902
317k
{
10903
317k
  zend_ast *name_ast = ast->child[0];
10904
10905
317k
  zend_op *opline;
10906
10907
317k
  bool is_fully_qualified;
10908
317k
  zend_string *orig_name = zend_ast_get_str(name_ast);
10909
317k
  zend_string *resolved_name = zend_resolve_const_name(orig_name, name_ast->attr, &is_fully_qualified);
10910
10911
317k
  if (zend_string_equals_literal(resolved_name, "__COMPILER_HALT_OFFSET__") || (name_ast->attr != ZEND_NAME_RELATIVE && zend_string_equals_literal(orig_name, "__COMPILER_HALT_OFFSET__"))) {
10912
856
    zend_ast *last = CG(ast);
10913
10914
1.71k
    while (last && last->kind == ZEND_AST_STMT_LIST) {
10915
1.11k
      zend_ast_list *list = zend_ast_get_list(last);
10916
1.11k
      if (list->children == 0) {
10917
258
        break;
10918
258
      }
10919
857
      last = list->child[list->children-1];
10920
857
    }
10921
856
    if (last && last->kind == ZEND_AST_HALT_COMPILER) {
10922
177
      result->op_type = IS_CONST;
10923
177
      ZVAL_LONG(&result->u.constant, Z_LVAL_P(zend_ast_get_zval(last->child[0])));
10924
177
      zend_string_release_ex(resolved_name, 0);
10925
177
      return;
10926
177
    }
10927
856
  }
10928
10929
317k
  if (zend_try_ct_eval_const(&result->u.constant, resolved_name, is_fully_qualified)) {
10930
24.9k
    result->op_type = IS_CONST;
10931
24.9k
    zend_string_release_ex(resolved_name, 0);
10932
24.9k
    return;
10933
24.9k
  }
10934
10935
292k
  opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, NULL);
10936
292k
  opline->op2_type = IS_CONST;
10937
10938
292k
  if (is_fully_qualified || !FC(current_namespace)) {
10939
211k
    opline->op1.num = 0;
10940
211k
    opline->op2.constant = zend_add_const_name_literal(
10941
211k
      resolved_name, 0);
10942
211k
  } else {
10943
80.6k
    opline->op1.num = IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE;
10944
80.6k
    opline->op2.constant = zend_add_const_name_literal(
10945
80.6k
      resolved_name, 1);
10946
80.6k
  }
10947
292k
  opline->extended_value = zend_alloc_cache_slot();
10948
292k
}
10949
/* }}} */
10950
10951
static void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
10952
23.7k
{
10953
23.7k
  zend_ast *class_ast;
10954
23.7k
  zend_ast *const_ast;
10955
23.7k
  znode class_node, const_node;
10956
23.7k
  zend_op *opline;
10957
10958
23.7k
  zend_eval_const_expr(&ast->child[0]);
10959
23.7k
  zend_eval_const_expr(&ast->child[1]);
10960
10961
23.7k
  class_ast = ast->child[0];
10962
23.7k
  const_ast = ast->child[1];
10963
10964
23.7k
  if (class_ast->kind == ZEND_AST_ZVAL && const_ast->kind == ZEND_AST_ZVAL) {
10965
9.29k
    zval *const_zv = zend_ast_get_zval(const_ast);
10966
9.29k
    if (Z_TYPE_P(const_zv) == IS_STRING) {
10967
9.10k
      zend_string *const_str = Z_STR_P(const_zv);
10968
9.10k
      zend_string *resolved_name = zend_resolve_class_name_ast(class_ast);
10969
9.10k
      if (zend_try_ct_eval_class_const(&result->u.constant, resolved_name, const_str)) {
10970
278
        result->op_type = IS_CONST;
10971
278
        zend_string_release_ex(resolved_name, 0);
10972
278
        return;
10973
278
      }
10974
8.82k
      zend_string_release_ex(resolved_name, 0);
10975
8.82k
    }
10976
9.29k
  }
10977
10978
23.4k
  zend_compile_class_ref(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
10979
10980
23.4k
  zend_compile_expr(&const_node, const_ast);
10981
10982
23.4k
  opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_CONSTANT, NULL, &const_node);
10983
10984
23.4k
  zend_set_class_name_op1(opline, &class_node);
10985
10986
23.4k
  if (opline->op1_type == IS_CONST || opline->op2_type == IS_CONST) {
10987
22.8k
    opline->extended_value = zend_alloc_cache_slots(2);
10988
22.8k
  }
10989
23.4k
}
10990
/* }}} */
10991
10992
static void zend_compile_class_name(znode *result, zend_ast *ast) /* {{{ */
10993
4.70k
{
10994
4.70k
  zend_ast *class_ast = ast->child[0];
10995
10996
4.70k
  if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast)) {
10997
2.70k
    result->op_type = IS_CONST;
10998
2.70k
    return;
10999
2.70k
  }
11000
11001
1.99k
  if (class_ast->kind == ZEND_AST_ZVAL) {
11002
853
    zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
11003
853
    opline->op1.num = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
11004
1.13k
  } else {
11005
1.13k
    znode expr_node;
11006
1.13k
    zend_compile_expr(&expr_node, class_ast);
11007
1.13k
    if (expr_node.op_type == IS_CONST) {
11008
      /* Unlikely case that happen if class_ast is constant folded.
11009
       * Handle it here, to avoid needing a CONST specialization in the VM. */
11010
13
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"::class\" on %s",
11011
13
        zend_zval_value_name(&expr_node.u.constant));
11012
13
    }
11013
11014
1.12k
    zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, &expr_node, NULL);
11015
1.12k
  }
11016
1.99k
}
11017
/* }}} */
11018
11019
static zend_op *zend_compile_rope_add_ex(zend_op *opline, znode *result, uint32_t num, znode *elem_node) /* {{{ */
11020
269k
{
11021
269k
  if (num == 0) {
11022
35.9k
    result->op_type = IS_TMP_VAR;
11023
35.9k
    result->u.op.var = -1;
11024
35.9k
    opline->opcode = ZEND_ROPE_INIT;
11025
233k
  } else {
11026
233k
    opline->opcode = ZEND_ROPE_ADD;
11027
233k
    SET_NODE(opline->op1, result);
11028
233k
  }
11029
269k
  SET_NODE(opline->op2, elem_node);
11030
269k
  SET_NODE(opline->result, result);
11031
269k
  opline->extended_value = num;
11032
269k
  return opline;
11033
269k
}
11034
/* }}} */
11035
11036
static zend_op *zend_compile_rope_add(znode *result, uint32_t num, znode *elem_node) /* {{{ */
11037
253k
{
11038
253k
  zend_op *opline = get_next_op();
11039
11040
253k
  if (num == 0) {
11041
11.6k
    result->op_type = IS_TMP_VAR;
11042
11.6k
    result->u.op.var = -1;
11043
11.6k
    opline->opcode = ZEND_ROPE_INIT;
11044
242k
  } else {
11045
242k
    opline->opcode = ZEND_ROPE_ADD;
11046
242k
    SET_NODE(opline->op1, result);
11047
242k
  }
11048
253k
  SET_NODE(opline->op2, elem_node);
11049
253k
  SET_NODE(opline->result, result);
11050
253k
  opline->extended_value = num;
11051
253k
  return opline;
11052
253k
}
11053
/* }}} */
11054
11055
static void zend_compile_rope_finalize(znode *result, uint32_t rope_elements, zend_op *init_opline, zend_op *opline)
11056
47.6k
{
11057
47.6k
  if (rope_elements == 1) {
11058
2.13k
    if (opline->op2_type == IS_CONST) {
11059
92
      GET_NODE(result, opline->op2);
11060
92
      ZVAL_UNDEF(CT_CONSTANT(opline->op2));
11061
92
      SET_UNUSED(opline->op2);
11062
92
      MAKE_NOP(opline);
11063
2.04k
    } else {
11064
2.04k
      opline->opcode = ZEND_CAST;
11065
2.04k
      opline->extended_value = IS_STRING;
11066
2.04k
      opline->op1_type = opline->op2_type;
11067
2.04k
      opline->op1 = opline->op2;
11068
2.04k
      SET_UNUSED(opline->op2);
11069
2.04k
      zend_make_tmp_result(result, opline);
11070
2.04k
    }
11071
45.4k
  } else if (rope_elements == 2) {
11072
12.2k
    opline->opcode = ZEND_FAST_CONCAT;
11073
12.2k
    opline->extended_value = 0;
11074
12.2k
    opline->op1_type = init_opline->op2_type;
11075
12.2k
    opline->op1 = init_opline->op2;
11076
12.2k
    zend_make_tmp_result(result, opline);
11077
12.2k
    MAKE_NOP(init_opline);
11078
33.2k
  } else {
11079
33.2k
    uint32_t var;
11080
11081
33.2k
    init_opline->extended_value = rope_elements;
11082
33.2k
    opline->opcode = ZEND_ROPE_END;
11083
33.2k
    zend_make_tmp_result(result, opline);
11084
33.2k
    var = opline->op1.var = get_temporary_variable();
11085
11086
    /* Allocates the necessary number of zval slots to keep the rope */
11087
33.2k
    uint32_t i = ((rope_elements * sizeof(zend_string*)) + (sizeof(zval) - 1)) / sizeof(zval);
11088
263k
    while (i > 1) {
11089
230k
      get_temporary_variable();
11090
230k
      i--;
11091
230k
    }
11092
11093
    /* Update all the previous opcodes to use the same variable */
11094
708k
    while (opline != init_opline) {
11095
675k
      opline--;
11096
675k
      if (opline->opcode == ZEND_ROPE_ADD &&
11097
675k
          opline->result.var == (uint32_t)-1) {
11098
430k
        opline->op1.var = var;
11099
430k
        opline->result.var = var;
11100
430k
      } else if (opline->opcode == ZEND_ROPE_INIT &&
11101
244k
                 opline->result.var == (uint32_t)-1) {
11102
33.2k
        opline->result.var = var;
11103
33.2k
      }
11104
675k
    }
11105
33.2k
  }
11106
47.6k
}
11107
11108
static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
11109
47.0k
{
11110
47.0k
  uint32_t i, j;
11111
47.0k
  uint32_t rope_init_lineno = -1;
11112
47.0k
  zend_op *opline = NULL, *init_opline;
11113
47.0k
  znode elem_node, last_const_node;
11114
47.0k
  zend_ast_list *list = zend_ast_get_list(ast);
11115
47.0k
  uint32_t reserved_op_number = -1;
11116
11117
47.0k
  ZEND_ASSERT(list->children > 0);
11118
11119
47.0k
  j = 0;
11120
47.0k
  last_const_node.op_type = IS_UNUSED;
11121
569k
  for (i = 0; i < list->children; i++) {
11122
522k
    zend_ast *encaps_var = list->child[i];
11123
11124
522k
    if (encaps_var->attr & (ZEND_ENCAPS_VAR_DOLLAR_CURLY|ZEND_ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR)) {
11125
3.89k
      if ((encaps_var->kind == ZEND_AST_VAR || encaps_var->kind == ZEND_AST_DIM) && (encaps_var->attr & ZEND_ENCAPS_VAR_DOLLAR_CURLY)) {
11126
548
        zend_error(E_DEPRECATED, "Using ${var} in strings is deprecated, use {$var} instead");
11127
3.34k
      } else if (encaps_var->kind == ZEND_AST_VAR && (encaps_var->attr & ZEND_ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR)) {
11128
3.34k
        zend_error(E_DEPRECATED, "Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead");
11129
3.34k
      }
11130
3.89k
    }
11131
11132
522k
    zend_compile_expr(&elem_node, encaps_var);
11133
11134
522k
    if (elem_node.op_type == IS_CONST) {
11135
270k
      convert_to_string(&elem_node.u.constant);
11136
11137
270k
      if (Z_STRLEN(elem_node.u.constant) == 0) {
11138
729
        zval_ptr_dtor(&elem_node.u.constant);
11139
269k
      } else if (last_const_node.op_type == IS_CONST) {
11140
0
        concat_function(&last_const_node.u.constant, &last_const_node.u.constant, &elem_node.u.constant);
11141
0
        zval_ptr_dtor(&elem_node.u.constant);
11142
269k
      } else {
11143
269k
        last_const_node.op_type = IS_CONST;
11144
269k
        ZVAL_COPY_VALUE(&last_const_node.u.constant, &elem_node.u.constant);
11145
        /* Reserve place for ZEND_ROPE_ADD instruction */
11146
269k
        reserved_op_number = get_next_op_number();
11147
269k
        opline = get_next_op();
11148
269k
        opline->opcode = ZEND_NOP;
11149
269k
      }
11150
270k
      continue;
11151
270k
    } else {
11152
251k
      if (j == 0) {
11153
47.0k
        if (last_const_node.op_type == IS_CONST) {
11154
35.9k
          rope_init_lineno = reserved_op_number;
11155
35.9k
        } else {
11156
11.0k
          rope_init_lineno = get_next_op_number();
11157
11.0k
        }
11158
47.0k
      }
11159
251k
      if (last_const_node.op_type == IS_CONST) {
11160
231k
        opline = &CG(active_op_array)->opcodes[reserved_op_number];
11161
231k
        zend_compile_rope_add_ex(opline, result, j++, &last_const_node);
11162
231k
        last_const_node.op_type = IS_UNUSED;
11163
231k
      }
11164
251k
      opline = zend_compile_rope_add(result, j++, &elem_node);
11165
251k
    }
11166
522k
  }
11167
11168
47.0k
  if (j == 0) {
11169
0
    result->op_type = IS_CONST;
11170
0
    if (last_const_node.op_type == IS_CONST) {
11171
0
      ZVAL_COPY_VALUE(&result->u.constant, &last_const_node.u.constant);
11172
0
    } else {
11173
0
      ZVAL_EMPTY_STRING(&result->u.constant);
11174
      /* empty string */
11175
0
    }
11176
0
    CG(active_op_array)->last = reserved_op_number - 1;
11177
0
    return;
11178
47.0k
  } else if (last_const_node.op_type == IS_CONST) {
11179
38.5k
    opline = &CG(active_op_array)->opcodes[reserved_op_number];
11180
38.5k
    opline = zend_compile_rope_add_ex(opline, result, j++, &last_const_node);
11181
38.5k
  }
11182
47.0k
  init_opline = CG(active_op_array)->opcodes + rope_init_lineno;
11183
47.0k
  zend_compile_rope_finalize(result, j, init_opline, opline);
11184
47.0k
}
11185
/* }}} */
11186
11187
static void zend_compile_magic_const(znode *result, zend_ast *ast) /* {{{ */
11188
16.5k
{
11189
16.5k
  zend_op *opline;
11190
11191
16.5k
  if (zend_try_ct_eval_magic_const(&result->u.constant, ast)) {
11192
16.2k
    result->op_type = IS_CONST;
11193
16.2k
    return;
11194
16.2k
  }
11195
11196
259
  ZEND_ASSERT(ast->attr == T_CLASS_C &&
11197
259
              CG(active_class_entry) &&
11198
259
              (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != 0);
11199
11200
259
  opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
11201
259
  opline->op1.num = ZEND_FETCH_CLASS_SELF;
11202
259
}
11203
/* }}} */
11204
11205
static bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */
11206
51.6k
{
11207
51.6k
  return kind == ZEND_AST_ZVAL || kind == ZEND_AST_BINARY_OP
11208
51.6k
    || kind == ZEND_AST_GREATER || kind == ZEND_AST_GREATER_EQUAL
11209
51.6k
    || kind == ZEND_AST_AND || kind == ZEND_AST_OR
11210
51.6k
    || kind == ZEND_AST_UNARY_OP
11211
51.6k
    || kind == ZEND_AST_UNARY_PLUS || kind == ZEND_AST_UNARY_MINUS
11212
51.6k
    || kind == ZEND_AST_CAST
11213
51.6k
    || kind == ZEND_AST_CONDITIONAL || kind == ZEND_AST_DIM
11214
51.6k
    || kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM
11215
51.6k
    || kind == ZEND_AST_UNPACK
11216
51.6k
    || kind == ZEND_AST_CONST || kind == ZEND_AST_CLASS_CONST
11217
51.6k
    || kind == ZEND_AST_CLASS_NAME
11218
51.6k
    || kind == ZEND_AST_MAGIC_CONST || kind == ZEND_AST_COALESCE
11219
51.6k
    || kind == ZEND_AST_CONST_ENUM_INIT
11220
51.6k
    || kind == ZEND_AST_NEW || kind == ZEND_AST_ARG_LIST
11221
51.6k
    || kind == ZEND_AST_NAMED_ARG
11222
51.6k
    || kind == ZEND_AST_PROP || kind == ZEND_AST_NULLSAFE_PROP
11223
51.6k
    || kind == ZEND_AST_CLOSURE
11224
51.6k
    || kind == ZEND_AST_CALL || kind == ZEND_AST_STATIC_CALL || kind == ZEND_AST_CALLABLE_CONVERT;
11225
51.6k
}
11226
/* }}} */
11227
11228
static void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */
11229
2.84k
{
11230
2.84k
  zend_ast *ast = *ast_ptr;
11231
2.84k
  zend_ast *class_ast = ast->child[0];
11232
2.84k
  zend_string *class_name;
11233
2.84k
  int fetch_type;
11234
11235
2.84k
  if (class_ast->kind != ZEND_AST_ZVAL) {
11236
21
    zend_error_noreturn(E_COMPILE_ERROR,
11237
21
      "Dynamic class names are not allowed in compile-time class constant references");
11238
21
  }
11239
2.82k
  if (Z_TYPE_P(zend_ast_get_zval(class_ast)) != IS_STRING) {
11240
10
    zend_throw_error(NULL, "Class name must be a valid object or a string");
11241
10
  }
11242
11243
2.82k
  class_name = zend_ast_get_str(class_ast);
11244
2.82k
  fetch_type = zend_get_class_fetch_type(class_name);
11245
11246
2.82k
  if (ZEND_FETCH_CLASS_STATIC == fetch_type) {
11247
6
    zend_error_noreturn(E_COMPILE_ERROR,
11248
6
      "\"static::\" is not allowed in compile-time constants");
11249
6
  }
11250
11251
2.81k
  if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
11252
2.20k
    zend_string *tmp = zend_resolve_class_name_ast(class_ast);
11253
11254
2.20k
    zend_string_release_ex(class_name, 0);
11255
2.20k
    if (tmp != class_name) {
11256
384
      zval *zv = zend_ast_get_zval(class_ast);
11257
384
      ZVAL_STR(zv, tmp);
11258
384
      class_ast->attr = ZEND_NAME_FQ;
11259
384
    }
11260
2.20k
  }
11261
11262
2.81k
  ast->attr |= ZEND_FETCH_CLASS_EXCEPTION;
11263
2.81k
}
11264
/* }}} */
11265
11266
static void zend_compile_const_expr_class_name(zend_ast **ast_ptr) /* {{{ */
11267
128
{
11268
128
  zend_ast *ast = *ast_ptr;
11269
128
  zend_ast *class_ast = ast->child[0];
11270
128
  if (class_ast->kind != ZEND_AST_ZVAL) {
11271
6
    zend_error_noreturn(E_COMPILE_ERROR,
11272
6
      "(expression)::class cannot be used in constant expressions");
11273
6
  }
11274
11275
122
  zend_string *class_name = zend_ast_get_str(class_ast);
11276
122
  uint32_t fetch_type = zend_get_class_fetch_type(class_name);
11277
11278
122
  switch (fetch_type) {
11279
116
    case ZEND_FETCH_CLASS_SELF:
11280
116
    case ZEND_FETCH_CLASS_PARENT:
11281
      /* For the const-eval representation store the fetch type instead of the name. */
11282
116
      zend_string_release(class_name);
11283
116
      ast->child[0] = NULL;
11284
116
      ast->attr = fetch_type;
11285
116
      return;
11286
6
    case ZEND_FETCH_CLASS_STATIC:
11287
6
      zend_error_noreturn(E_COMPILE_ERROR,
11288
6
        "static::class cannot be used for compile-time class name resolution");
11289
0
      return;
11290
122
    EMPTY_SWITCH_DEFAULT_CASE()
11291
122
  }
11292
122
}
11293
11294
static void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */
11295
24.5k
{
11296
24.5k
  zend_ast *ast = *ast_ptr;
11297
24.5k
  zend_ast *name_ast = ast->child[0];
11298
24.5k
  zend_string *orig_name = zend_ast_get_str(name_ast);
11299
24.5k
  bool is_fully_qualified;
11300
24.5k
  zval result;
11301
24.5k
  zend_string *resolved_name;
11302
11303
24.5k
  CG(zend_lineno) = zend_ast_get_lineno(ast);
11304
11305
24.5k
  resolved_name = zend_resolve_const_name(
11306
24.5k
    orig_name, name_ast->attr, &is_fully_qualified);
11307
11308
24.5k
  if (zend_try_ct_eval_const(&result, resolved_name, is_fully_qualified)) {
11309
0
    zend_string_release_ex(resolved_name, 0);
11310
0
    zend_ast_destroy(ast);
11311
0
    *ast_ptr = zend_ast_create_zval(&result);
11312
0
    return;
11313
0
  }
11314
11315
24.5k
  zend_ast_destroy(ast);
11316
24.5k
  *ast_ptr = zend_ast_create_constant(resolved_name,
11317
24.5k
    !is_fully_qualified && FC(current_namespace) ? IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE : 0);
11318
24.5k
}
11319
/* }}} */
11320
11321
static void zend_compile_const_expr_magic_const(zend_ast **ast_ptr) /* {{{ */
11322
332
{
11323
332
  zend_ast *ast = *ast_ptr;
11324
11325
  /* Other cases already resolved by constant folding */
11326
332
  ZEND_ASSERT(ast->attr == T_CLASS_C);
11327
11328
332
  zend_ast_destroy(ast);
11329
332
  *ast_ptr = zend_ast_create(ZEND_AST_CONSTANT_CLASS);
11330
332
}
11331
/* }}} */
11332
11333
static void zend_compile_const_expr_class_reference(zend_ast *class_ast)
11334
1.10k
{
11335
1.10k
  if (class_ast->kind == ZEND_AST_CLASS) {
11336
1
    zend_error_noreturn(E_COMPILE_ERROR,
11337
1
      "Cannot use anonymous class in constant expression");
11338
1
  }
11339
1.10k
  if (class_ast->kind != ZEND_AST_ZVAL) {
11340
2
    zend_error_noreturn(E_COMPILE_ERROR,
11341
2
      "Cannot use dynamic class name in constant expression");
11342
2
  }
11343
11344
1.10k
  zend_string *class_name = zend_resolve_class_name_ast(class_ast);
11345
1.10k
  int fetch_type = zend_get_class_fetch_type(class_name);
11346
1.10k
  if (ZEND_FETCH_CLASS_STATIC == fetch_type) {
11347
6
    zend_error_noreturn(E_COMPILE_ERROR,
11348
6
      "\"static\" is not allowed in compile-time constants");
11349
6
  }
11350
11351
1.09k
  zval *class_ast_zv = zend_ast_get_zval(class_ast);
11352
1.09k
  zval_ptr_dtor_nogc(class_ast_zv);
11353
1.09k
  ZVAL_STR(class_ast_zv, class_name);
11354
1.09k
  class_ast->attr = fetch_type << ZEND_CONST_EXPR_NEW_FETCH_TYPE_SHIFT;
11355
1.09k
}
11356
11357
static void zend_compile_const_expr_new(zend_ast **ast_ptr)
11358
965
{
11359
965
  zend_ast *class_ast = (*ast_ptr)->child[0];
11360
965
  zend_compile_const_expr_class_reference(class_ast);
11361
965
}
11362
11363
static void zend_compile_const_expr_closure(zend_ast **ast_ptr)
11364
91
{
11365
91
  zend_ast_decl *closure_ast = (zend_ast_decl *) *ast_ptr;
11366
91
  zend_ast *uses_ast = closure_ast->child[1];
11367
91
  if (!(closure_ast->flags & ZEND_ACC_STATIC)) {
11368
12
    zend_error_noreturn(E_COMPILE_ERROR,
11369
12
      "Closures in constant expressions must be static");
11370
12
  }
11371
79
  if (uses_ast) {
11372
6
    zend_error_noreturn(E_COMPILE_ERROR,
11373
6
      "Cannot use(...) variables in constant expression");
11374
6
  }
11375
11376
73
  znode node;
11377
73
  zend_op_array *op = zend_compile_func_decl(&node, (zend_ast*)closure_ast, FUNC_DECL_LEVEL_CONSTEXPR);
11378
11379
73
  zend_ast_destroy(*ast_ptr);
11380
73
  *ast_ptr = zend_ast_create_op_array(op);
11381
73
}
11382
11383
static void zend_compile_const_expr_fcc(zend_ast **ast_ptr)
11384
737
{
11385
737
  zend_ast **args_ast;
11386
737
  switch ((*ast_ptr)->kind) {
11387
598
    case ZEND_AST_CALL:
11388
598
      args_ast = &(*ast_ptr)->child[1];
11389
598
      break;
11390
139
    case ZEND_AST_STATIC_CALL:
11391
139
      args_ast = &(*ast_ptr)->child[2];
11392
139
      break;
11393
0
    EMPTY_SWITCH_DEFAULT_CASE();
11394
737
  }
11395
737
  if ((*args_ast)->kind != ZEND_AST_CALLABLE_CONVERT) {
11396
30
    zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
11397
30
  }
11398
707
  ZEND_MAP_PTR_NEW(((zend_ast_fcc *)*args_ast)->fptr);
11399
11400
707
  switch ((*ast_ptr)->kind) {
11401
568
    case ZEND_AST_CALL: {
11402
568
      zend_ast *name_ast = (*ast_ptr)->child[0];
11403
568
      if (name_ast->kind != ZEND_AST_ZVAL) {
11404
14
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use dynamic function name in constant expression");
11405
14
      }
11406
554
      zval *name_ast_zv = zend_ast_get_zval(name_ast);
11407
554
      if (Z_TYPE_P(name_ast_zv) != IS_STRING) {
11408
6
        zend_error_noreturn(E_COMPILE_ERROR, "Illegal function name");
11409
6
      }
11410
548
      bool is_fully_qualified;
11411
548
      zend_string *name = zend_resolve_function_name(Z_STR_P(name_ast_zv), name_ast->attr, &is_fully_qualified);
11412
548
      zval_ptr_dtor_nogc(name_ast_zv);
11413
548
      ZVAL_STR(name_ast_zv, name);
11414
548
      if (is_fully_qualified) {
11415
185
        name_ast->attr = ZEND_NAME_FQ;
11416
185
      }
11417
548
      break;
11418
554
    }
11419
139
    case ZEND_AST_STATIC_CALL: {
11420
139
      zend_ast *class_ast = (*ast_ptr)->child[0];
11421
139
      zend_compile_const_expr_class_reference(class_ast);
11422
139
      zend_ast *method_ast = (*ast_ptr)->child[1];
11423
139
      if (method_ast->kind != ZEND_AST_ZVAL) {
11424
1
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use dynamic method name in constant expression");
11425
1
      }
11426
138
      if (Z_TYPE_P(zend_ast_get_zval(method_ast)) != IS_STRING) {
11427
0
        zend_error_noreturn(E_COMPILE_ERROR, "Illegal method name");
11428
0
      }
11429
138
      break;
11430
138
    }
11431
138
    EMPTY_SWITCH_DEFAULT_CASE();
11432
707
  }
11433
707
}
11434
11435
static void zend_compile_const_expr_args(zend_ast **ast_ptr)
11436
962
{
11437
962
  zend_ast_list *list = zend_ast_get_list(*ast_ptr);
11438
962
  bool uses_named_args = false;
11439
1.99k
  for (uint32_t i = 0; i < list->children; i++) {
11440
1.03k
    zend_ast *arg = list->child[i];
11441
1.03k
    if (arg->kind == ZEND_AST_UNPACK) {
11442
1
      zend_error_noreturn(E_COMPILE_ERROR,
11443
1
        "Argument unpacking in constant expressions is not supported");
11444
1
    }
11445
1.03k
    if (arg->kind == ZEND_AST_NAMED_ARG) {
11446
110
      uses_named_args = true;
11447
927
    } else if (uses_named_args) {
11448
4
      zend_error_noreturn(E_COMPILE_ERROR,
11449
4
        "Cannot use positional argument after named argument");
11450
4
    }
11451
1.03k
  }
11452
957
  if (uses_named_args) {
11453
87
    list->attr = 1;
11454
87
  }
11455
957
}
11456
11457
typedef struct {
11458
  /* Whether the value of this expression may differ on each evaluation. */
11459
  bool allow_dynamic;
11460
} const_expr_context;
11461
11462
static void zend_compile_const_expr(zend_ast **ast_ptr, void *context) /* {{{ */
11463
121k
{
11464
121k
  const_expr_context *ctx = (const_expr_context *) context;
11465
121k
  zend_ast *ast = *ast_ptr;
11466
121k
  if (ast == NULL || ast->kind == ZEND_AST_ZVAL) {
11467
69.6k
    return;
11468
69.6k
  }
11469
11470
51.6k
  if (!zend_is_allowed_in_const_expr(ast->kind)) {
11471
29
    zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
11472
29
  }
11473
11474
51.6k
  switch (ast->kind) {
11475
2.84k
    case ZEND_AST_CLASS_CONST:
11476
2.84k
      zend_compile_const_expr_class_const(ast_ptr);
11477
2.84k
      break;
11478
128
    case ZEND_AST_CLASS_NAME:
11479
128
      zend_compile_const_expr_class_name(ast_ptr);
11480
128
      break;
11481
24.5k
    case ZEND_AST_CONST:
11482
24.5k
      zend_compile_const_expr_const(ast_ptr);
11483
24.5k
      break;
11484
332
    case ZEND_AST_MAGIC_CONST:
11485
332
      zend_compile_const_expr_magic_const(ast_ptr);
11486
332
      break;
11487
457
    case ZEND_AST_CAST:
11488
457
      if (ast->attr == IS_OBJECT && !ctx->allow_dynamic) {
11489
6
        zend_error_noreturn(E_COMPILE_ERROR,
11490
6
          "Object casts are not supported in this context");
11491
6
      }
11492
451
      break;
11493
971
    case ZEND_AST_NEW:
11494
971
      if (!ctx->allow_dynamic) {
11495
6
        zend_error_noreturn(E_COMPILE_ERROR,
11496
6
          "New expressions are not supported in this context");
11497
6
      }
11498
965
      zend_compile_const_expr_new(ast_ptr);
11499
965
      break;
11500
962
    case ZEND_AST_ARG_LIST:
11501
962
      zend_compile_const_expr_args(ast_ptr);
11502
962
      break;
11503
91
    case ZEND_AST_CLOSURE:
11504
91
      zend_compile_const_expr_closure(ast_ptr);
11505
      /* Return, because we do not want to traverse the children. */
11506
91
      return;
11507
598
    case ZEND_AST_CALL:
11508
737
    case ZEND_AST_STATIC_CALL:
11509
737
      zend_compile_const_expr_fcc(ast_ptr);
11510
737
      break;
11511
51.6k
  }
11512
11513
51.4k
  zend_ast_apply(ast, zend_compile_const_expr, context);
11514
51.4k
}
11515
/* }}} */
11516
11517
void zend_const_expr_to_zval(zval *result, zend_ast **ast_ptr, bool allow_dynamic) /* {{{ */
11518
47.7k
{
11519
47.7k
  const_expr_context context;
11520
47.7k
  context.allow_dynamic = allow_dynamic;
11521
11522
47.7k
  zend_eval_const_expr(ast_ptr);
11523
47.7k
  zend_compile_const_expr(ast_ptr, &context);
11524
47.7k
  if ((*ast_ptr)->kind != ZEND_AST_ZVAL) {
11525
    /* Replace with compiled AST zval representation. */
11526
25.3k
    zval ast_zv;
11527
25.3k
    ZVAL_AST(&ast_zv, zend_ast_copy(*ast_ptr));
11528
25.3k
    zend_ast_destroy(*ast_ptr);
11529
25.3k
    *ast_ptr = zend_ast_create_zval(&ast_zv);
11530
25.3k
  }
11531
47.7k
  ZVAL_COPY(result, zend_ast_get_zval(*ast_ptr));
11532
47.7k
}
11533
/* }}} */
11534
11535
/* Same as compile_stmt, but with early binding */
11536
void zend_compile_top_stmt(zend_ast *ast) /* {{{ */
11537
762k
{
11538
762k
  if (!ast) {
11539
71.6k
    return;
11540
71.6k
  }
11541
11542
691k
  if (ast->kind == ZEND_AST_STMT_LIST) {
11543
128k
    zend_ast_list *list = zend_ast_get_list(ast);
11544
128k
    uint32_t i;
11545
785k
    for (i = 0; i < list->children; ++i) {
11546
657k
      zend_compile_top_stmt(list->child[i]);
11547
657k
    }
11548
128k
    return;
11549
128k
  }
11550
11551
562k
  if (ast->kind == ZEND_AST_FUNC_DECL) {
11552
15.2k
    CG(zend_lineno) = ast->lineno;
11553
15.2k
    zend_compile_func_decl(NULL, ast, FUNC_DECL_LEVEL_TOPLEVEL);
11554
15.2k
    CG(zend_lineno) = ((zend_ast_decl *) ast)->end_lineno;
11555
547k
  } else if (ast->kind == ZEND_AST_CLASS) {
11556
53.0k
    CG(zend_lineno) = ast->lineno;
11557
53.0k
    zend_compile_class_decl(NULL, ast, 1);
11558
53.0k
    CG(zend_lineno) = ((zend_ast_decl *) ast)->end_lineno;
11559
494k
  } else {
11560
494k
    zend_compile_stmt(ast);
11561
494k
  }
11562
562k
  if (ast->kind != ZEND_AST_NAMESPACE && ast->kind != ZEND_AST_HALT_COMPILER) {
11563
551k
    zend_verify_namespace();
11564
551k
  }
11565
562k
}
11566
/* }}} */
11567
11568
static void zend_compile_stmt(zend_ast *ast) /* {{{ */
11569
1.23M
{
11570
1.23M
  if (!ast) {
11571
16.4k
    return;
11572
16.4k
  }
11573
11574
1.21M
  CG(zend_lineno) = ast->lineno;
11575
11576
1.21M
  if ((CG(compiler_options) & ZEND_COMPILE_EXTENDED_STMT) && !zend_is_unticked_stmt(ast)) {
11577
0
    zend_do_extended_stmt();
11578
0
  }
11579
11580
1.21M
  switch (ast->kind) {
11581
311k
    case ZEND_AST_STMT_LIST:
11582
311k
      zend_compile_stmt_list(ast);
11583
311k
      break;
11584
2.24k
    case ZEND_AST_GLOBAL:
11585
2.24k
      zend_compile_global_var(ast);
11586
2.24k
      break;
11587
1.09k
    case ZEND_AST_STATIC:
11588
1.09k
      zend_compile_static_var(ast);
11589
1.09k
      break;
11590
6.19k
    case ZEND_AST_UNSET:
11591
6.19k
      zend_compile_unset(ast);
11592
6.19k
      break;
11593
38.0k
    case ZEND_AST_RETURN:
11594
38.0k
      zend_compile_return(ast);
11595
38.0k
      break;
11596
181k
    case ZEND_AST_ECHO:
11597
181k
      zend_compile_echo(ast);
11598
181k
      break;
11599
1.31k
    case ZEND_AST_BREAK:
11600
2.42k
    case ZEND_AST_CONTINUE:
11601
2.42k
      zend_compile_break_continue(ast);
11602
2.42k
      break;
11603
1.24k
    case ZEND_AST_GOTO:
11604
1.24k
      zend_compile_goto(ast);
11605
1.24k
      break;
11606
1.42k
    case ZEND_AST_LABEL:
11607
1.42k
      zend_compile_label(ast);
11608
1.42k
      break;
11609
1.55k
    case ZEND_AST_WHILE:
11610
1.55k
      zend_compile_while(ast);
11611
1.55k
      break;
11612
545
    case ZEND_AST_DO_WHILE:
11613
545
      zend_compile_do_while(ast);
11614
545
      break;
11615
17.9k
    case ZEND_AST_FOR:
11616
17.9k
      zend_compile_for(ast);
11617
17.9k
      break;
11618
18.6k
    case ZEND_AST_FOREACH:
11619
18.6k
      zend_compile_foreach(ast);
11620
18.6k
      break;
11621
19.1k
    case ZEND_AST_IF:
11622
19.1k
      zend_compile_if(ast);
11623
19.1k
      break;
11624
2.17k
    case ZEND_AST_SWITCH:
11625
2.17k
      zend_compile_switch(ast);
11626
2.17k
      break;
11627
44.9k
    case ZEND_AST_TRY:
11628
44.9k
      zend_compile_try(ast);
11629
44.9k
      break;
11630
1.56k
    case ZEND_AST_DECLARE:
11631
1.56k
      zend_compile_declare(ast);
11632
1.56k
      break;
11633
2.39k
    case ZEND_AST_FUNC_DECL:
11634
35.5k
    case ZEND_AST_METHOD:
11635
35.5k
      zend_compile_func_decl(NULL, ast, FUNC_DECL_LEVEL_NESTED);
11636
35.5k
      break;
11637
2.42k
    case ZEND_AST_ENUM_CASE:
11638
2.42k
      zend_compile_enum_case(ast);
11639
2.42k
      break;
11640
22.0k
    case ZEND_AST_PROP_GROUP:
11641
22.0k
      zend_compile_prop_group(ast);
11642
22.0k
      break;
11643
5.02k
    case ZEND_AST_CLASS_CONST_GROUP:
11644
5.02k
      zend_compile_class_const_group(ast);
11645
5.02k
      break;
11646
2.89k
    case ZEND_AST_USE_TRAIT:
11647
2.89k
      zend_compile_use_trait(ast);
11648
2.89k
      break;
11649
3.23k
    case ZEND_AST_CLASS:
11650
3.23k
      zend_compile_class_decl(NULL, ast, 0);
11651
3.23k
      break;
11652
268
    case ZEND_AST_GROUP_USE:
11653
268
      zend_compile_group_use(ast);
11654
268
      break;
11655
1.77k
    case ZEND_AST_USE:
11656
1.77k
      zend_compile_use(ast);
11657
1.77k
      break;
11658
4.66k
    case ZEND_AST_CONST_DECL:
11659
4.66k
      zend_compile_const_decl(ast);
11660
4.66k
      break;
11661
5.36k
    case ZEND_AST_NAMESPACE:
11662
5.36k
      zend_compile_namespace(ast);
11663
5.36k
      break;
11664
55
    case ZEND_AST_HALT_COMPILER:
11665
55
      zend_compile_halt_compiler(ast);
11666
55
      break;
11667
2.55k
    case ZEND_AST_THROW:
11668
2.55k
      zend_compile_expr(NULL, ast);
11669
2.55k
      break;
11670
330
    case ZEND_AST_CAST_VOID:
11671
330
      zend_compile_void_cast(NULL, ast);
11672
330
      break;
11673
475k
    default:
11674
475k
    {
11675
475k
      znode result;
11676
475k
      zend_compile_expr(&result, ast);
11677
475k
      zend_do_free(&result);
11678
475k
    }
11679
1.21M
  }
11680
11681
1.20M
  if (FC(declarables).ticks && !zend_is_unticked_stmt(ast)) {
11682
1.54k
    zend_emit_tick();
11683
1.54k
  }
11684
1.20M
}
11685
/* }}} */
11686
11687
static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */
11688
4.61M
{
11689
  /* CG(zend_lineno) = ast->lineno; */
11690
4.61M
  CG(zend_lineno) = zend_ast_get_lineno(ast);
11691
11692
4.61M
  if (CG(memoize_mode) != ZEND_MEMOIZE_NONE) {
11693
107k
    zend_compile_memoized_expr(result, ast);
11694
107k
    return;
11695
107k
  }
11696
11697
4.50M
  switch (ast->kind) {
11698
1.15M
    case ZEND_AST_ZVAL:
11699
1.15M
      ZVAL_COPY(&result->u.constant, zend_ast_get_zval(ast));
11700
1.15M
      result->op_type = IS_CONST;
11701
1.15M
      return;
11702
7.60k
    case ZEND_AST_ZNODE:
11703
7.60k
      *result = *zend_ast_get_znode(ast);
11704
7.60k
      return;
11705
492k
    case ZEND_AST_VAR:
11706
509k
    case ZEND_AST_DIM:
11707
532k
    case ZEND_AST_PROP:
11708
581k
    case ZEND_AST_NULLSAFE_PROP:
11709
586k
    case ZEND_AST_STATIC_PROP:
11710
764k
    case ZEND_AST_CALL:
11711
799k
    case ZEND_AST_METHOD_CALL:
11712
801k
    case ZEND_AST_NULLSAFE_METHOD_CALL:
11713
815k
    case ZEND_AST_STATIC_CALL:
11714
815k
    case ZEND_AST_PARENT_PROPERTY_HOOK_CALL:
11715
815k
      zend_compile_var(result, ast, BP_VAR_R, 0);
11716
815k
      return;
11717
273k
    case ZEND_AST_ASSIGN:
11718
273k
      zend_compile_assign(result, ast);
11719
273k
      return;
11720
13.5k
    case ZEND_AST_ASSIGN_REF:
11721
13.5k
      zend_compile_assign_ref(result, ast);
11722
13.5k
      return;
11723
84.1k
    case ZEND_AST_NEW:
11724
84.1k
      zend_compile_new(result, ast);
11725
84.1k
      return;
11726
774
    case ZEND_AST_CLONE:
11727
774
      zend_compile_clone(result, ast);
11728
774
      return;
11729
203k
    case ZEND_AST_ASSIGN_OP:
11730
203k
      zend_compile_compound_assign(result, ast);
11731
203k
      return;
11732
319k
    case ZEND_AST_BINARY_OP:
11733
319k
      zend_compile_binary_op(result, ast);
11734
319k
      return;
11735
11.1k
    case ZEND_AST_GREATER:
11736
14.5k
    case ZEND_AST_GREATER_EQUAL:
11737
14.5k
      zend_compile_greater(result, ast);
11738
14.5k
      return;
11739
52.4k
    case ZEND_AST_UNARY_OP:
11740
52.4k
      zend_compile_unary_op(result, ast);
11741
52.4k
      return;
11742
20.8k
    case ZEND_AST_UNARY_PLUS:
11743
41.9k
    case ZEND_AST_UNARY_MINUS:
11744
41.9k
      zend_compile_unary_pm(result, ast);
11745
41.9k
      return;
11746
9.17k
    case ZEND_AST_AND:
11747
12.8k
    case ZEND_AST_OR:
11748
12.8k
      zend_compile_short_circuiting(result, ast);
11749
12.8k
      return;
11750
7.08k
    case ZEND_AST_POST_INC:
11751
10.2k
    case ZEND_AST_POST_DEC:
11752
10.2k
      zend_compile_post_incdec(result, ast);
11753
10.2k
      return;
11754
4.84k
    case ZEND_AST_PRE_INC:
11755
6.93k
    case ZEND_AST_PRE_DEC:
11756
6.93k
      zend_compile_pre_incdec(result, ast);
11757
6.93k
      return;
11758
2.59k
    case ZEND_AST_CAST:
11759
2.59k
      zend_compile_cast(result, ast);
11760
2.59k
      return;
11761
6.61k
    case ZEND_AST_CONDITIONAL:
11762
6.61k
      zend_compile_conditional(result, ast);
11763
6.61k
      return;
11764
12.7k
    case ZEND_AST_COALESCE:
11765
12.7k
      zend_compile_coalesce(result, ast);
11766
12.7k
      return;
11767
9.30k
    case ZEND_AST_ASSIGN_COALESCE:
11768
9.30k
      zend_compile_assign_coalesce(result, ast);
11769
9.30k
      return;
11770
3.68k
    case ZEND_AST_PRINT:
11771
3.68k
      zend_compile_print(result, ast);
11772
3.68k
      return;
11773
5.51k
    case ZEND_AST_YIELD:
11774
5.51k
      zend_compile_yield(result, ast);
11775
5.51k
      return;
11776
692
    case ZEND_AST_YIELD_FROM:
11777
692
      zend_compile_yield_from(result, ast);
11778
692
      return;
11779
723
    case ZEND_AST_INSTANCEOF:
11780
723
      zend_compile_instanceof(result, ast);
11781
723
      return;
11782
9.66k
    case ZEND_AST_INCLUDE_OR_EVAL:
11783
9.66k
      zend_compile_include_or_eval(result, ast);
11784
9.66k
      return;
11785
5.24k
    case ZEND_AST_ISSET:
11786
6.99k
    case ZEND_AST_EMPTY:
11787
6.99k
      zend_compile_isset_or_empty(result, ast);
11788
6.99k
      return;
11789
909k
    case ZEND_AST_SILENCE:
11790
909k
      zend_compile_silence(result, ast);
11791
909k
      return;
11792
6.69k
    case ZEND_AST_SHELL_EXEC:
11793
6.69k
      zend_compile_shell_exec(result, ast);
11794
6.69k
      return;
11795
64.6k
    case ZEND_AST_ARRAY:
11796
64.6k
      zend_compile_array(result, ast);
11797
64.6k
      return;
11798
317k
    case ZEND_AST_CONST:
11799
317k
      zend_compile_const(result, ast);
11800
317k
      return;
11801
23.7k
    case ZEND_AST_CLASS_CONST:
11802
23.7k
      zend_compile_class_const(result, ast);
11803
23.7k
      return;
11804
4.70k
    case ZEND_AST_CLASS_NAME:
11805
4.70k
      zend_compile_class_name(result, ast);
11806
4.70k
      return;
11807
47.0k
    case ZEND_AST_ENCAPS_LIST:
11808
47.0k
      zend_compile_encaps_list(result, ast);
11809
47.0k
      return;
11810
16.5k
    case ZEND_AST_MAGIC_CONST:
11811
16.5k
      zend_compile_magic_const(result, ast);
11812
16.5k
      return;
11813
16.8k
    case ZEND_AST_CLOSURE:
11814
38.5k
    case ZEND_AST_ARROW_FUNC:
11815
38.5k
      zend_compile_func_decl(result, ast, FUNC_DECL_LEVEL_NESTED);
11816
38.5k
      return;
11817
3.13k
    case ZEND_AST_THROW:
11818
3.13k
      zend_compile_throw(result, ast);
11819
3.13k
      return;
11820
2.52k
    case ZEND_AST_MATCH:
11821
2.52k
      zend_compile_match(result, ast);
11822
2.52k
      return;
11823
364
    case ZEND_AST_PIPE:
11824
364
      zend_compile_pipe(result, ast);
11825
364
      return;
11826
0
    default:
11827
0
      ZEND_ASSERT(0 /* not supported */);
11828
4.50M
  }
11829
4.50M
}
11830
/* }}} */
11831
11832
static void zend_compile_expr(znode *result, zend_ast *ast)
11833
4.61M
{
11834
4.61M
  zend_check_stack_limit();
11835
11836
4.61M
  uint32_t checkpoint = zend_short_circuiting_checkpoint();
11837
4.61M
  zend_compile_expr_inner(result, ast);
11838
4.61M
  zend_short_circuiting_commit(checkpoint, result, ast);
11839
4.61M
}
11840
11841
static zend_op *zend_compile_var_inner(znode *result, zend_ast *ast, uint32_t type, bool by_ref)
11842
1.01M
{
11843
1.01M
  CG(zend_lineno) = zend_ast_get_lineno(ast);
11844
11845
1.01M
  if (CG(memoize_mode) != ZEND_MEMOIZE_NONE) {
11846
20.3k
    switch (ast->kind) {
11847
952
      case ZEND_AST_CALL:
11848
1.50k
      case ZEND_AST_METHOD_CALL:
11849
1.50k
      case ZEND_AST_NULLSAFE_METHOD_CALL:
11850
1.83k
      case ZEND_AST_STATIC_CALL:
11851
1.83k
        zend_compile_memoized_expr(result, ast);
11852
        /* This might not actually produce an opcode, e.g. for expressions evaluated at comptime. */
11853
1.83k
        return NULL;
11854
20.3k
    }
11855
20.3k
  }
11856
11857
1.01M
  switch (ast->kind) {
11858
542k
    case ZEND_AST_VAR:
11859
542k
      return zend_compile_simple_var(result, ast, type, 0);
11860
36.0k
    case ZEND_AST_DIM:
11861
36.0k
      return zend_compile_dim(result, ast, type, by_ref);
11862
32.8k
    case ZEND_AST_PROP:
11863
82.1k
    case ZEND_AST_NULLSAFE_PROP:
11864
82.1k
      return zend_compile_prop(result, ast, type, by_ref);
11865
8.25k
    case ZEND_AST_STATIC_PROP:
11866
8.25k
      return zend_compile_static_prop(result, ast, type, by_ref, 0);
11867
242k
    case ZEND_AST_CALL:
11868
242k
      zend_compile_call(result, ast, type);
11869
242k
      return NULL;
11870
0
    case ZEND_AST_PARENT_PROPERTY_HOOK_CALL:
11871
0
      zend_compile_parent_property_hook_call(result, ast, type);
11872
0
      return NULL;
11873
49.8k
    case ZEND_AST_METHOD_CALL:
11874
53.1k
    case ZEND_AST_NULLSAFE_METHOD_CALL:
11875
53.1k
      zend_compile_method_call(result, ast, type);
11876
53.1k
      return NULL;
11877
16.0k
    case ZEND_AST_STATIC_CALL:
11878
16.0k
      zend_compile_static_call(result, ast, type);
11879
16.0k
      return NULL;
11880
8.15k
    case ZEND_AST_ZNODE:
11881
8.15k
      *result = *zend_ast_get_znode(ast);
11882
8.15k
      return NULL;
11883
24.0k
    default:
11884
24.0k
      if (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) {
11885
188
        zend_error_noreturn(E_COMPILE_ERROR,
11886
188
          "Cannot use temporary expression in write context");
11887
188
      }
11888
11889
23.8k
      zend_compile_expr(result, ast);
11890
23.8k
      return NULL;
11891
1.01M
  }
11892
1.01M
}
11893
11894
static zend_op *zend_compile_var(znode *result, zend_ast *ast, uint32_t type, bool by_ref) /* {{{ */
11895
1.01M
{
11896
1.01M
  zend_check_stack_limit();
11897
11898
1.01M
  uint32_t checkpoint = zend_short_circuiting_checkpoint();
11899
1.01M
  zend_op *opcode = zend_compile_var_inner(result, ast, type, by_ref);
11900
1.01M
  zend_short_circuiting_commit(checkpoint, result, ast);
11901
1.01M
  return opcode;
11902
1.01M
}
11903
11904
static zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type, bool by_ref) /* {{{ */
11905
711k
{
11906
711k
  zend_check_stack_limit();
11907
11908
711k
  switch (ast->kind) {
11909
571k
    case ZEND_AST_VAR:
11910
571k
      return zend_compile_simple_var(result, ast, type, 1);
11911
87.2k
    case ZEND_AST_DIM:
11912
87.2k
      return zend_delayed_compile_dim(result, ast, type, by_ref);
11913
19.7k
    case ZEND_AST_PROP:
11914
22.2k
    case ZEND_AST_NULLSAFE_PROP:
11915
22.2k
    {
11916
22.2k
      zend_op *opline = zend_delayed_compile_prop(result, ast, type);
11917
22.2k
      if (by_ref) {
11918
803
        opline->extended_value |= ZEND_FETCH_REF;
11919
803
      }
11920
22.2k
      return opline;
11921
19.7k
    }
11922
6.08k
    case ZEND_AST_STATIC_PROP:
11923
6.08k
      return zend_compile_static_prop(result, ast, type, by_ref, 1);
11924
23.8k
    default:
11925
23.8k
      return zend_compile_var(result, ast, type, 0);
11926
711k
  }
11927
711k
}
11928
/* }}} */
11929
11930
bool zend_try_ct_eval_cast(zval *result, uint32_t type, zval *op1)
11931
13.4k
{
11932
13.4k
  switch (type) {
11933
27
    case _IS_BOOL:
11934
27
      ZVAL_BOOL(result, zval_is_true(op1));
11935
27
      return true;
11936
709
    case IS_LONG:
11937
709
      ZVAL_LONG(result, zval_get_long(op1));
11938
709
      return true;
11939
198
    case IS_DOUBLE:
11940
198
      ZVAL_DOUBLE(result, zval_get_double(op1));
11941
198
      return true;
11942
11.7k
    case IS_STRING:
11943
      /* Conversion from double to string takes into account run-time
11944
         'precision' setting and cannot be evaluated at compile-time */
11945
11.7k
      if (Z_TYPE_P(op1) != IS_ARRAY && Z_TYPE_P(op1) != IS_DOUBLE) {
11946
11.0k
        ZVAL_STR(result, zval_get_string(op1));
11947
11.0k
        return true;
11948
11.0k
      }
11949
634
      break;
11950
634
    case IS_ARRAY:
11951
144
      ZVAL_COPY(result, op1);
11952
144
      convert_to_array(result);
11953
144
      return true;
11954
13.4k
  }
11955
1.30k
  return false;
11956
13.4k
}
11957
11958
static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
11959
4.85M
{
11960
4.85M
  zend_ast *ast = *ast_ptr;
11961
4.85M
  zval result;
11962
11963
4.85M
  if (!ast) {
11964
1.39M
    return;
11965
1.39M
  }
11966
11967
3.45M
  zend_check_stack_limit();
11968
11969
3.45M
  switch (ast->kind) {
11970
161k
    case ZEND_AST_BINARY_OP:
11971
161k
      zend_eval_const_expr(&ast->child[0]);
11972
161k
      zend_eval_const_expr(&ast->child[1]);
11973
161k
      if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
11974
114k
        return;
11975
114k
      }
11976
11977
46.8k
      if (!zend_try_ct_eval_binary_op(&result, ast->attr,
11978
46.8k
          zend_ast_get_zval(ast->child[0]), zend_ast_get_zval(ast->child[1]))
11979
46.8k
      ) {
11980
24.5k
        return;
11981
24.5k
      }
11982
22.3k
      break;
11983
29.8k
    case ZEND_AST_GREATER:
11984
30.2k
    case ZEND_AST_GREATER_EQUAL:
11985
30.2k
      zend_eval_const_expr(&ast->child[0]);
11986
30.2k
      zend_eval_const_expr(&ast->child[1]);
11987
30.2k
      if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
11988
26.6k
        return;
11989
26.6k
      }
11990
11991
3.66k
      zend_ct_eval_greater(&result, ast->kind,
11992
3.66k
        zend_ast_get_zval(ast->child[0]), zend_ast_get_zval(ast->child[1]));
11993
3.66k
      break;
11994
1.95k
    case ZEND_AST_AND:
11995
2.94k
    case ZEND_AST_OR:
11996
2.94k
    {
11997
2.94k
      bool child0_is_true, child1_is_true;
11998
2.94k
      zend_eval_const_expr(&ast->child[0]);
11999
2.94k
      zend_eval_const_expr(&ast->child[1]);
12000
2.94k
      if (ast->child[0]->kind != ZEND_AST_ZVAL) {
12001
1.32k
        return;
12002
1.32k
      }
12003
12004
1.61k
      child0_is_true = zend_is_true(zend_ast_get_zval(ast->child[0]));
12005
1.61k
      if (child0_is_true == (ast->kind == ZEND_AST_OR)) {
12006
414
        ZVAL_BOOL(&result, ast->kind == ZEND_AST_OR);
12007
414
        break;
12008
414
      }
12009
12010
1.20k
      if (ast->child[1]->kind != ZEND_AST_ZVAL) {
12011
541
        return;
12012
541
      }
12013
12014
661
      child1_is_true = zend_is_true(zend_ast_get_zval(ast->child[1]));
12015
661
      if (ast->kind == ZEND_AST_OR) {
12016
212
        ZVAL_BOOL(&result, child0_is_true || child1_is_true);
12017
449
      } else {
12018
449
        ZVAL_BOOL(&result, child0_is_true && child1_is_true);
12019
449
      }
12020
661
      break;
12021
1.20k
    }
12022
86.9k
    case ZEND_AST_UNARY_OP:
12023
86.9k
      zend_eval_const_expr(&ast->child[0]);
12024
86.9k
      if (ast->child[0]->kind != ZEND_AST_ZVAL) {
12025
71.5k
        return;
12026
71.5k
      }
12027
12028
15.4k
      if (!zend_try_ct_eval_unary_op(&result, ast->attr, zend_ast_get_zval(ast->child[0]))) {
12029
1.12k
        return;
12030
1.12k
      }
12031
14.2k
      break;
12032
28.5k
    case ZEND_AST_UNARY_PLUS:
12033
51.6k
    case ZEND_AST_UNARY_MINUS:
12034
51.6k
      zend_eval_const_expr(&ast->child[0]);
12035
51.6k
      if (ast->child[0]->kind != ZEND_AST_ZVAL) {
12036
29.9k
        return;
12037
29.9k
      }
12038
12039
21.6k
      if (!zend_try_ct_eval_unary_pm(&result, ast->kind, zend_ast_get_zval(ast->child[0]))) {
12040
4.72k
        return;
12041
4.72k
      }
12042
16.9k
      break;
12043
16.9k
    case ZEND_AST_COALESCE:
12044
      /* Set isset fetch indicator here, opcache disallows runtime altering of the AST */
12045
1.64k
      if (ast->child[0]->kind == ZEND_AST_DIM) {
12046
615
        ast->child[0]->attr |= ZEND_DIM_IS;
12047
615
      }
12048
1.64k
      zend_eval_const_expr(&ast->child[0]);
12049
12050
1.64k
      if (ast->child[0]->kind != ZEND_AST_ZVAL) {
12051
        /* ensure everything was compile-time evaluated at least once */
12052
1.12k
        zend_eval_const_expr(&ast->child[1]);
12053
1.12k
        return;
12054
1.12k
      }
12055
12056
524
      if (Z_TYPE_P(zend_ast_get_zval(ast->child[0])) == IS_NULL) {
12057
196
        zend_eval_const_expr(&ast->child[1]);
12058
196
        *ast_ptr = ast->child[1];
12059
196
        ast->child[1] = NULL;
12060
196
        zend_ast_destroy(ast);
12061
328
      } else {
12062
328
        *ast_ptr = ast->child[0];
12063
328
        ast->child[0] = NULL;
12064
328
        zend_ast_destroy(ast);
12065
328
      }
12066
524
      return;
12067
2.73k
    case ZEND_AST_CONDITIONAL:
12068
2.73k
    {
12069
2.73k
      zend_ast **child, *child_ast;
12070
2.73k
      zend_eval_const_expr(&ast->child[0]);
12071
2.73k
      if (ast->child[0]->kind != ZEND_AST_ZVAL) {
12072
        /* ensure everything was compile-time evaluated at least once */
12073
2.32k
        if (ast->child[1]) {
12074
745
          zend_eval_const_expr(&ast->child[1]);
12075
745
        }
12076
2.32k
        zend_eval_const_expr(&ast->child[2]);
12077
2.32k
        return;
12078
2.32k
      }
12079
12080
414
      child = &ast->child[2 - zend_is_true(zend_ast_get_zval(ast->child[0]))];
12081
414
      if (*child == NULL) {
12082
282
        child--;
12083
282
      }
12084
414
      child_ast = *child;
12085
414
      *child = NULL;
12086
414
      zend_ast_destroy(ast);
12087
414
      *ast_ptr = child_ast;
12088
414
      zend_eval_const_expr(ast_ptr);
12089
414
      return;
12090
2.73k
    }
12091
301k
    case ZEND_AST_DIM:
12092
301k
    {
12093
      /* constant expression should be always read context ... */
12094
301k
      zval *container, *dim;
12095
12096
301k
      if (ast->child[1] == NULL) {
12097
42
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
12098
42
      }
12099
12100
      /* Set isset fetch indicator here, opcache disallows runtime altering of the AST */
12101
301k
      if ((ast->attr & ZEND_DIM_IS) && ast->child[0]->kind == ZEND_AST_DIM) {
12102
852
        ast->child[0]->attr |= ZEND_DIM_IS;
12103
852
      }
12104
12105
301k
      zend_eval_const_expr(&ast->child[0]);
12106
301k
      zend_eval_const_expr(&ast->child[1]);
12107
301k
      if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
12108
291k
        return;
12109
291k
      }
12110
12111
10.0k
      container = zend_ast_get_zval(ast->child[0]);
12112
10.0k
      dim = zend_ast_get_zval(ast->child[1]);
12113
12114
10.0k
      if (Z_TYPE_P(container) == IS_ARRAY) {
12115
7.53k
        zval *el;
12116
7.53k
        if (Z_TYPE_P(dim) == IS_LONG) {
12117
1.60k
          el = zend_hash_index_find(Z_ARR_P(container), Z_LVAL_P(dim));
12118
1.60k
          if (el) {
12119
652
            ZVAL_COPY(&result, el);
12120
952
          } else {
12121
952
            return;
12122
952
          }
12123
5.93k
        } else if (Z_TYPE_P(dim) == IS_STRING) {
12124
5.27k
          el = zend_symtable_find(Z_ARR_P(container), Z_STR_P(dim));
12125
5.27k
          if (el) {
12126
288
            ZVAL_COPY(&result, el);
12127
4.98k
          } else {
12128
4.98k
            return;
12129
4.98k
          }
12130
5.27k
        } else {
12131
663
          return; /* warning... handle at runtime */
12132
663
        }
12133
7.53k
      } else if (Z_TYPE_P(container) == IS_STRING) {
12134
1.85k
        zend_long offset;
12135
1.85k
        uint8_t c;
12136
1.85k
        if (Z_TYPE_P(dim) == IS_LONG) {
12137
569
          offset = Z_LVAL_P(dim);
12138
1.28k
        } else if (Z_TYPE_P(dim) != IS_STRING || is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), &offset, NULL, 1) != IS_LONG) {
12139
722
          return;
12140
722
        }
12141
1.13k
        if (offset < 0 || (size_t)offset >= Z_STRLEN_P(container)) {
12142
1.02k
          return;
12143
1.02k
        }
12144
109
        c = (uint8_t) Z_STRVAL_P(container)[offset];
12145
109
        ZVAL_CHAR(&result, c);
12146
628
      } else if (Z_TYPE_P(container) <= IS_FALSE) {
12147
27
        return; /* warning... handle at runtime */
12148
601
      } else {
12149
601
        return;
12150
601
      }
12151
1.04k
      break;
12152
10.0k
    }
12153
929k
    case ZEND_AST_ARRAY:
12154
929k
      if (!zend_try_ct_eval_array(&result, ast)) {
12155
875k
        return;
12156
875k
      }
12157
54.3k
      break;
12158
54.3k
    case ZEND_AST_MAGIC_CONST:
12159
1.27k
      if (!zend_try_ct_eval_magic_const(&result, ast)) {
12160
332
        return;
12161
332
      }
12162
940
      break;
12163
213k
    case ZEND_AST_CONST:
12164
213k
    {
12165
213k
      zend_ast *name_ast = ast->child[0];
12166
213k
      bool is_fully_qualified;
12167
213k
      zend_string *resolved_name = zend_resolve_const_name(
12168
213k
        zend_ast_get_str(name_ast), name_ast->attr, &is_fully_qualified);
12169
12170
213k
      if (!zend_try_ct_eval_const(&result, resolved_name, is_fully_qualified)) {
12171
207k
        zend_string_release_ex(resolved_name, 0);
12172
207k
        return;
12173
207k
      }
12174
12175
5.87k
      zend_string_release_ex(resolved_name, 0);
12176
5.87k
      break;
12177
213k
    }
12178
177k
    case ZEND_AST_CLASS_CONST:
12179
177k
    {
12180
177k
      zend_ast *class_ast;
12181
177k
      zend_ast *name_ast;
12182
177k
      zend_string *resolved_name;
12183
12184
177k
      zend_eval_const_expr(&ast->child[0]);
12185
177k
      zend_eval_const_expr(&ast->child[1]);
12186
12187
177k
      if (UNEXPECTED(ast->child[1]->kind != ZEND_AST_ZVAL
12188
177k
        || Z_TYPE_P(zend_ast_get_zval(ast->child[1])) != IS_STRING)) {
12189
3.27k
        return;
12190
3.27k
      }
12191
12192
173k
      class_ast = ast->child[0];
12193
173k
      name_ast = ast->child[1];
12194
12195
173k
      if (class_ast->kind != ZEND_AST_ZVAL || name_ast->kind != ZEND_AST_ZVAL) {
12196
163k
        return;
12197
163k
      }
12198
12199
9.81k
      resolved_name = zend_resolve_class_name_ast(class_ast);
12200
9.81k
      if (!zend_try_ct_eval_class_const(&result, resolved_name, zend_ast_get_str(name_ast))) {
12201
9.52k
        zend_string_release_ex(resolved_name, 0);
12202
9.52k
        return;
12203
9.52k
      }
12204
12205
292
      zend_string_release_ex(resolved_name, 0);
12206
292
      break;
12207
9.81k
    }
12208
2.25k
    case ZEND_AST_CLASS_NAME:
12209
2.25k
    {
12210
2.25k
      zend_ast *class_ast = ast->child[0];
12211
2.25k
      if (!zend_try_compile_const_expr_resolve_class_name(&result, class_ast)) {
12212
1.04k
        return;
12213
1.04k
      }
12214
1.20k
      break;
12215
2.25k
    }
12216
    // TODO: We should probably use zend_ast_apply to recursively walk nodes without
12217
    // special handling. It is required that all nodes that are part of a const expr
12218
    // are visited. Probably we should be distinguishing evaluation of const expr and
12219
    // normal exprs here.
12220
4.28k
    case ZEND_AST_ARG_LIST:
12221
4.28k
    {
12222
4.28k
      zend_ast_list *list = zend_ast_get_list(ast);
12223
6.28k
      for (uint32_t i = 0; i < list->children; i++) {
12224
1.99k
        zend_eval_const_expr(&list->child[i]);
12225
1.99k
      }
12226
4.28k
      return;
12227
2.25k
    }
12228
4.28k
    case ZEND_AST_NEW:
12229
4.28k
      zend_eval_const_expr(&ast->child[0]);
12230
4.28k
      zend_eval_const_expr(&ast->child[1]);
12231
4.28k
      return;
12232
337
    case ZEND_AST_NAMED_ARG:
12233
337
      zend_eval_const_expr(&ast->child[1]);
12234
337
      return;
12235
2.39k
    case ZEND_AST_CONST_ENUM_INIT:
12236
2.39k
      zend_eval_const_expr(&ast->child[2]);
12237
2.39k
      return;
12238
913
    case ZEND_AST_PROP:
12239
1.48k
    case ZEND_AST_NULLSAFE_PROP:
12240
1.48k
      zend_eval_const_expr(&ast->child[0]);
12241
1.48k
      zend_eval_const_expr(&ast->child[1]);
12242
1.48k
      return;
12243
1.57k
    case ZEND_AST_CAST:
12244
1.57k
      zend_eval_const_expr(&ast->child[0]);
12245
1.57k
      if (ast->child[0]->kind == ZEND_AST_ZVAL
12246
1.57k
       && zend_try_ct_eval_cast(&result, ast->attr, zend_ast_get_zval(ast->child[0]))) {
12247
778
        break;
12248
778
      }
12249
800
      return;
12250
1.47M
    default:
12251
1.47M
      return;
12252
3.45M
  }
12253
12254
122k
  zend_ast_destroy(ast);
12255
122k
  *ast_ptr = zend_ast_create_zval(&result);
12256
122k
}
12257
/* }}} */