Coverage Report

Created: 2025-09-27 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/Zend/zend_compile.c
Line
Count
Source
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
26.4M
#define SET_NODE(target, src) do { \
43
26.4M
    target ## _type = (src)->op_type; \
44
26.4M
    if ((src)->op_type == IS_CONST) { \
45
3.50M
      target.constant = zend_add_literal(&(src)->u.constant); \
46
22.9M
    } else { \
47
22.9M
      target = (src)->u.op; \
48
22.9M
    } \
49
26.4M
  } while (0)
50
51
18.6M
#define GET_NODE(target, src) do { \
52
18.6M
    (target)->op_type = src ## _type; \
53
18.6M
    if ((target)->op_type == IS_CONST) { \
54
426
      ZVAL_COPY_VALUE(&(target)->u.constant, CT_CONSTANT(src)); \
55
18.6M
    } else { \
56
18.6M
      (target)->u.op = src; \
57
18.6M
    } \
58
18.6M
  } while (0)
59
60
38.4M
#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
6.24M
static inline uint32_t zend_alloc_cache_slots(unsigned count) {
70
6.24M
  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
6.24M
  zend_op_array *op_array = CG(active_op_array);
78
6.24M
  uint32_t ret = op_array->cache_size;
79
6.24M
  op_array->cache_size += count * sizeof(void*);
80
6.24M
  return ret;
81
6.24M
}
82
83
5.96M
static inline uint32_t zend_alloc_cache_slot(void) {
84
5.96M
  return zend_alloc_cache_slots(1);
85
5.96M
}
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
32.2M
{
120
32.2M
  if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {
121
0
    zend_stack_limit_error();
122
0
  }
123
32.2M
}
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
37.9M
{
132
37.9M
  MAKE_NOP(op);
133
37.9M
  op->extended_value = 0;
134
37.9M
  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
37.9M
}
144
145
static zend_always_inline uint32_t get_next_op_number(void)
146
6.47M
{
147
6.47M
  return CG(active_op_array)->last;
148
6.47M
}
149
150
static zend_op *get_next_op(void)
151
37.6M
{
152
37.6M
  zend_op_array *op_array = CG(active_op_array);
153
37.6M
  uint32_t next_op_num = op_array->last++;
154
37.6M
  zend_op *next_op;
155
156
37.6M
  if (UNEXPECTED(next_op_num >= CG(context).opcodes_size)) {
157
272k
    CG(context).opcodes_size *= 4;
158
272k
    op_array->opcodes = erealloc(op_array->opcodes, CG(context).opcodes_size * sizeof(zend_op));
159
272k
  }
160
161
37.6M
  next_op = &(op_array->opcodes[next_op_num]);
162
163
37.6M
  init_op(next_op);
164
165
37.6M
  return next_op;
166
37.6M
}
167
168
static zend_brk_cont_element *get_next_brk_cont_element(void)
169
90.6k
{
170
90.6k
  CG(context).last_brk_cont++;
171
90.6k
  CG(context).brk_cont_array = erealloc(CG(context).brk_cont_array, sizeof(zend_brk_cont_element) * CG(context).last_brk_cont);
172
90.6k
  return &CG(context).brk_cont_array[CG(context).last_brk_cont-1];
173
90.6k
}
174
175
static zend_string *zend_build_runtime_definition_key(zend_string *name, uint32_t start_lineno) /* {{{ */
176
82.2k
{
177
82.2k
  zend_string *filename = CG(active_op_array)->filename;
178
82.2k
  zend_string *result = zend_strpprintf(0, "%c%s%s:%" PRIu32 "$%" PRIx32,
179
82.2k
    '\0', ZSTR_VAL(name), ZSTR_VAL(filename), start_lineno, CG(rtd_key_counter)++);
180
82.2k
  return zend_new_interned_string(result);
181
82.2k
}
182
/* }}} */
183
184
static bool zend_get_unqualified_name(const zend_string *name, const char **result, size_t *result_len) /* {{{ */
185
5.85M
{
186
5.85M
  const char *ns_separator = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
187
5.85M
  if (ns_separator != NULL) {
188
5.41M
    *result = ns_separator + 1;
189
5.41M
    *result_len = ZSTR_VAL(name) + ZSTR_LEN(name) - *result;
190
5.41M
    return 1;
191
5.41M
  }
192
193
442k
  return 0;
194
5.85M
}
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
296k
{
226
296k
  const struct reserved_class_name *reserved = reserved_class_names;
227
228
296k
  const char *uqname = ZSTR_VAL(name);
229
296k
  size_t uqname_len = ZSTR_LEN(name);
230
296k
  zend_get_unqualified_name(name, &uqname, &uqname_len);
231
232
5.34M
  for (; reserved->name; ++reserved) {
233
5.04M
    if (uqname_len == reserved->len
234
215k
      && zend_binary_strcasecmp(uqname, uqname_len, reserved->name, reserved->len) == 0
235
5.04M
    ) {
236
131
      return 1;
237
131
    }
238
5.04M
  }
239
240
296k
  return 0;
241
296k
}
242
/* }}} */
243
244
void zend_assert_valid_class_name(const zend_string *name, const char *type) /* {{{ */
245
295k
{
246
295k
  if (zend_is_reserved_class_name(name)) {
247
99
    zend_error_noreturn(E_COMPILE_ERROR,
248
99
      "Cannot use \"%s\" as %s as it is reserved", ZSTR_VAL(name), type);
249
99
  }
250
295k
  if (zend_string_equals_literal(name, "_")) {
251
370
    zend_error(E_DEPRECATED, "Using \"_\" as %s is deprecated since 8.4", type);
252
370
  }
253
295k
}
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
450k
{
294
450k
  const builtin_type_info *info = &builtin_types[0];
295
296
4.95M
  for (; info->name; ++info) {
297
4.76M
    if (ZSTR_LEN(name) == info->name_len
298
338k
      && zend_binary_strcasecmp(ZSTR_VAL(name), ZSTR_LEN(name), info->name, info->name_len) == 0
299
4.76M
    ) {
300
265k
      return info->type;
301
265k
    }
302
4.76M
  }
303
304
185k
  return 0;
305
450k
}
306
/* }}} */
307
308
static zend_always_inline bool zend_is_confusable_type(const zend_string *name, const char **correct_name) /* {{{ */
309
184k
{
310
184k
  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
922k
  for (; info->name; ++info) {
315
738k
    if (zend_string_equals_cstr(name, info->name, info->name_len)) {
316
914
      *correct_name = info->correct_name;
317
914
      return 1;
318
914
    }
319
738k
  }
320
321
183k
  return 0;
322
184k
}
323
/* }}} */
324
325
914
static bool zend_is_not_imported(zend_string *name) {
326
  /* Assuming "name" is unqualified here. */
327
914
  return !FC(imports) || zend_hash_find_ptr_lc(FC(imports), name) == NULL;
328
914
}
329
330
void zend_oparray_context_begin(zend_oparray_context *prev_context, zend_op_array *op_array) /* {{{ */
331
806k
{
332
806k
  *prev_context = CG(context);
333
806k
  CG(context).prev = CG(context).op_array ? prev_context : NULL;
334
806k
  CG(context).op_array = op_array;
335
806k
  CG(context).opcodes_size = INITIAL_OP_ARRAY_SIZE;
336
806k
  CG(context).vars_size = 0;
337
806k
  CG(context).literals_size = 0;
338
806k
  CG(context).fast_call_var = -1;
339
806k
  CG(context).try_catch_offset = -1;
340
806k
  CG(context).current_brk_cont = -1;
341
806k
  CG(context).last_brk_cont = 0;
342
806k
  CG(context).has_assigned_to_http_response_header = false;
343
806k
  CG(context).brk_cont_array = NULL;
344
806k
  CG(context).labels = NULL;
345
806k
  CG(context).in_jmp_frameless_branch = false;
346
806k
  CG(context).active_property_info_name = NULL;
347
806k
  CG(context).active_property_hook_kind = (zend_property_hook_kind)-1;
348
806k
}
349
/* }}} */
350
351
void zend_oparray_context_end(zend_oparray_context *prev_context) /* {{{ */
352
797k
{
353
797k
  if (CG(context).brk_cont_array) {
354
39.6k
    efree(CG(context).brk_cont_array);
355
39.6k
    CG(context).brk_cont_array = NULL;
356
39.6k
  }
357
797k
  if (CG(context).labels) {
358
2.97k
    zend_hash_destroy(CG(context).labels);
359
2.97k
    FREE_HASHTABLE(CG(context).labels);
360
2.97k
    CG(context).labels = NULL;
361
2.97k
  }
362
797k
  CG(context) = *prev_context;
363
797k
}
364
/* }}} */
365
366
static void zend_reset_import_tables(void) /* {{{ */
367
95.7k
{
368
95.7k
  if (FC(imports)) {
369
688
    zend_hash_destroy(FC(imports));
370
688
    efree(FC(imports));
371
688
    FC(imports) = NULL;
372
688
  }
373
374
95.7k
  if (FC(imports_function)) {
375
398
    zend_hash_destroy(FC(imports_function));
376
398
    efree(FC(imports_function));
377
398
    FC(imports_function) = NULL;
378
398
  }
379
380
95.7k
  if (FC(imports_const)) {
381
144
    zend_hash_destroy(FC(imports_const));
382
144
    efree(FC(imports_const));
383
144
    FC(imports_const) = NULL;
384
144
  }
385
386
95.7k
  zend_hash_clean(&FC(seen_symbols));
387
95.7k
}
388
/* }}} */
389
390
90.4k
static void zend_end_namespace(void) /* {{{ */ {
391
90.4k
  FC(in_namespace) = 0;
392
90.4k
  zend_reset_import_tables();
393
90.4k
  if (FC(current_namespace)) {
394
3.58k
    zend_string_release_ex(FC(current_namespace), 0);
395
3.58k
    FC(current_namespace) = NULL;
396
3.58k
  }
397
90.4k
}
398
/* }}} */
399
400
void zend_file_context_begin(zend_file_context *prev_context) /* {{{ */
401
95.4k
{
402
95.4k
  *prev_context = CG(file_context);
403
95.4k
  FC(imports) = NULL;
404
95.4k
  FC(imports_function) = NULL;
405
95.4k
  FC(imports_const) = NULL;
406
95.4k
  FC(current_namespace) = NULL;
407
95.4k
  FC(in_namespace) = 0;
408
95.4k
  FC(has_bracketed_namespaces) = 0;
409
95.4k
  FC(declarables).ticks = 0;
410
95.4k
  zend_hash_init(&FC(seen_symbols), 8, NULL, NULL, 0);
411
95.4k
}
412
/* }}} */
413
414
void zend_file_context_end(zend_file_context *prev_context) /* {{{ */
415
88.7k
{
416
88.7k
  zend_end_namespace();
417
88.7k
  zend_hash_destroy(&FC(seen_symbols));
418
88.7k
  CG(file_context) = *prev_context;
419
88.7k
}
420
/* }}} */
421
422
void zend_init_compiler_data_structures(void) /* {{{ */
423
284k
{
424
284k
  zend_stack_init(&CG(loop_var_stack), sizeof(zend_loop_var));
425
284k
  zend_stack_init(&CG(delayed_oplines_stack), sizeof(zend_op));
426
284k
  zend_stack_init(&CG(short_circuiting_opnums), sizeof(uint32_t));
427
284k
  CG(active_class_entry) = NULL;
428
284k
  CG(in_compilation) = 0;
429
284k
  CG(skip_shebang) = 0;
430
431
284k
  CG(encoding_declared) = 0;
432
284k
  CG(memoized_exprs) = NULL;
433
284k
  CG(memoize_mode) = ZEND_MEMOIZE_NONE;
434
284k
}
435
/* }}} */
436
437
781k
static void zend_register_seen_symbol(zend_string *name, uint32_t kind) {
438
781k
  zval *zv = zend_hash_find(&FC(seen_symbols), name);
439
781k
  if (zv) {
440
699k
    Z_LVAL_P(zv) |= kind;
441
699k
  } else {
442
81.9k
    zval tmp;
443
81.9k
    ZVAL_LONG(&tmp, kind);
444
81.9k
    zend_hash_add_new(&FC(seen_symbols), name, &tmp);
445
81.9k
  }
446
781k
}
447
448
2.06k
static bool zend_have_seen_symbol(zend_string *name, uint32_t kind) {
449
2.06k
  zval *zv = zend_hash_find(&FC(seen_symbols), name);
450
2.06k
  return zv && (Z_LVAL_P(zv) & kind) != 0;
451
2.06k
}
452
453
void init_compiler(void) /* {{{ */
454
278k
{
455
278k
  CG(arena) = zend_arena_create(64 * 1024);
456
278k
  CG(active_op_array) = NULL;
457
278k
  memset(&CG(context), 0, sizeof(CG(context)));
458
278k
  zend_init_compiler_data_structures();
459
278k
  zend_init_rsrc_list();
460
278k
  zend_stream_init();
461
278k
  CG(unclean_shutdown) = 0;
462
463
278k
  CG(delayed_variance_obligations) = NULL;
464
278k
  CG(delayed_autoloads) = NULL;
465
278k
  CG(unlinked_uses) = NULL;
466
278k
  CG(current_linking_class) = NULL;
467
278k
}
468
/* }}} */
469
470
void shutdown_compiler(void) /* {{{ */
471
284k
{
472
  /* Reset filename before destroying the arena, as file cache may use arena allocated strings. */
473
284k
  zend_restore_compiled_filename(NULL);
474
475
284k
  zend_stack_destroy(&CG(loop_var_stack));
476
284k
  zend_stack_destroy(&CG(delayed_oplines_stack));
477
284k
  zend_stack_destroy(&CG(short_circuiting_opnums));
478
479
284k
  if (CG(delayed_variance_obligations)) {
480
258
    zend_hash_destroy(CG(delayed_variance_obligations));
481
258
    FREE_HASHTABLE(CG(delayed_variance_obligations));
482
258
    CG(delayed_variance_obligations) = NULL;
483
258
  }
484
284k
  if (CG(delayed_autoloads)) {
485
262
    zend_hash_destroy(CG(delayed_autoloads));
486
262
    FREE_HASHTABLE(CG(delayed_autoloads));
487
262
    CG(delayed_autoloads) = NULL;
488
262
  }
489
284k
  if (CG(unlinked_uses)) {
490
243
    zend_hash_destroy(CG(unlinked_uses));
491
243
    FREE_HASHTABLE(CG(unlinked_uses));
492
243
    CG(unlinked_uses) = NULL;
493
243
  }
494
284k
  CG(current_linking_class) = NULL;
495
284k
}
496
/* }}} */
497
498
ZEND_API zend_string *zend_set_compiled_filename(zend_string *new_compiled_filename) /* {{{ */
499
160k
{
500
160k
  CG(compiled_filename) = zend_string_copy(new_compiled_filename);
501
160k
  return new_compiled_filename;
502
160k
}
503
/* }}} */
504
505
ZEND_API void zend_restore_compiled_filename(zend_string *original_compiled_filename) /* {{{ */
506
613k
{
507
613k
  if (CG(compiled_filename)) {
508
160k
    zend_string_release(CG(compiled_filename));
509
160k
    CG(compiled_filename) = NULL;
510
160k
  }
511
613k
  CG(compiled_filename) = original_compiled_filename;
512
613k
}
513
/* }}} */
514
515
ZEND_API zend_string *zend_get_compiled_filename(void) /* {{{ */
516
1.34M
{
517
1.34M
  return CG(compiled_filename);
518
1.34M
}
519
/* }}} */
520
521
ZEND_API int zend_get_compiled_lineno(void) /* {{{ */
522
256k
{
523
256k
  return CG(zend_lineno);
524
256k
}
525
/* }}} */
526
527
ZEND_API bool zend_is_compiling(void) /* {{{ */
528
3.21M
{
529
3.21M
  return CG(in_compilation);
530
3.21M
}
531
/* }}} */
532
533
static zend_always_inline uint32_t get_temporary_variable(void) /* {{{ */
534
18.8M
{
535
18.8M
  return (uint32_t)CG(active_op_array)->T++;
536
18.8M
}
537
/* }}} */
538
539
1.96M
static int lookup_cv(zend_string *name) /* {{{ */{
540
1.96M
  zend_op_array *op_array = CG(active_op_array);
541
1.96M
  int i = 0;
542
1.96M
  zend_ulong hash_value = zend_string_hash_val(name);
543
544
9.06M
  while (i < op_array->last_var) {
545
7.76M
    if (ZSTR_H(op_array->vars[i]) == hash_value
546
672k
     && zend_string_equals(op_array->vars[i], name)) {
547
670k
      return EX_NUM_TO_VAR(i);
548
670k
    }
549
7.09M
    i++;
550
7.09M
  }
551
1.29M
  i = op_array->last_var;
552
1.29M
  op_array->last_var++;
553
1.29M
  if (op_array->last_var > CG(context).vars_size) {
554
724k
    CG(context).vars_size += 16; /* FIXME */
555
724k
    op_array->vars = erealloc(op_array->vars, CG(context).vars_size * sizeof(zend_string*));
556
724k
  }
557
558
1.29M
  op_array->vars[i] = zend_string_copy(name);
559
1.29M
  return EX_NUM_TO_VAR(i);
560
1.96M
}
561
/* }}} */
562
563
zend_string *zval_make_interned_string(zval *zv)
564
20.8M
{
565
20.8M
  ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
566
20.8M
  Z_STR_P(zv) = zend_new_interned_string(Z_STR_P(zv));
567
20.8M
  if (ZSTR_IS_INTERNED(Z_STR_P(zv))) {
568
3.53M
    Z_TYPE_FLAGS_P(zv) = 0;
569
3.53M
  }
570
20.8M
  return Z_STR_P(zv);
571
20.8M
}
572
573
/* Common part of zend_add_literal and zend_append_individual_literal */
574
static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int literal_position) /* {{{ */
575
20.2M
{
576
20.2M
  zval *lit = CT_CONSTANT_EX(op_array, literal_position);
577
20.2M
  if (Z_TYPE_P(zv) == IS_STRING) {
578
19.0M
    zval_make_interned_string(zv);
579
19.0M
  }
580
20.2M
  ZVAL_COPY_VALUE(lit, zv);
581
20.2M
  Z_EXTRA_P(lit) = 0;
582
20.2M
}
583
/* }}} */
584
585
/* Is used while compiling a function, using the context to keep track
586
   of an approximate size to avoid to relocate to often.
587
   Literals are truncated to actual size in the second compiler pass (pass_two()). */
588
static int zend_add_literal(zval *zv) /* {{{ */
589
20.2M
{
590
20.2M
  zend_op_array *op_array = CG(active_op_array);
591
20.2M
  int i = op_array->last_literal;
592
20.2M
  op_array->last_literal++;
593
20.2M
  if (i >= CG(context).literals_size) {
594
3.51M
    while (i >= CG(context).literals_size) {
595
1.75M
      CG(context).literals_size += 16; /* FIXME */
596
1.75M
    }
597
1.75M
    op_array->literals = (zval*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zval));
598
1.75M
  }
599
20.2M
  zend_insert_literal(op_array, zv, i);
600
20.2M
  return i;
601
20.2M
}
602
/* }}} */
603
604
static inline int zend_add_literal_string(zend_string **str) /* {{{ */
605
16.7M
{
606
16.7M
  int ret;
607
16.7M
  zval zv;
608
16.7M
  ZVAL_STR(&zv, *str);
609
16.7M
  ret = zend_add_literal(&zv);
610
16.7M
  *str = Z_STR(zv);
611
16.7M
  return ret;
612
16.7M
}
613
/* }}} */
614
615
static int zend_add_func_name_literal(zend_string *name) /* {{{ */
616
180k
{
617
  /* Original name */
618
180k
  int ret = zend_add_literal_string(&name);
619
620
  /* Lowercased name */
621
180k
  zend_string *lc_name = zend_string_tolower(name);
622
180k
  zend_add_literal_string(&lc_name);
623
624
180k
  return ret;
625
180k
}
626
/* }}} */
627
628
static int zend_add_ns_func_name_literal(zend_string *name) /* {{{ */
629
1.46M
{
630
1.46M
  const char *unqualified_name;
631
1.46M
  size_t unqualified_name_len;
632
633
  /* Original name */
634
1.46M
  int ret = zend_add_literal_string(&name);
635
636
  /* Lowercased name */
637
1.46M
  zend_string *lc_name = zend_string_tolower(name);
638
1.46M
  zend_add_literal_string(&lc_name);
639
640
  /* Lowercased unqualified name */
641
1.46M
  if (zend_get_unqualified_name(name, &unqualified_name, &unqualified_name_len)) {
642
1.46M
    lc_name = zend_string_alloc(unqualified_name_len, 0);
643
1.46M
    zend_str_tolower_copy(ZSTR_VAL(lc_name), unqualified_name, unqualified_name_len);
644
1.46M
    zend_add_literal_string(&lc_name);
645
1.46M
  }
646
647
1.46M
  return ret;
648
1.46M
}
649
/* }}} */
650
651
static int zend_add_class_name_literal(zend_string *name) /* {{{ */
652
155k
{
653
  /* Original name */
654
155k
  int ret = zend_add_literal_string(&name);
655
656
  /* Lowercased name */
657
155k
  zend_string *lc_name = zend_string_tolower(name);
658
155k
  zend_add_literal_string(&lc_name);
659
660
155k
  return ret;
661
155k
}
662
/* }}} */
663
664
static int zend_add_const_name_literal(zend_string *name, bool unqualified) /* {{{ */
665
3.89M
{
666
3.89M
  zend_string *tmp_name;
667
668
3.89M
  int ret = zend_add_literal_string(&name);
669
670
3.89M
  size_t ns_len = 0, after_ns_len = ZSTR_LEN(name);
671
3.89M
  const char *after_ns = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
672
3.89M
  if (after_ns) {
673
3.69M
    after_ns += 1;
674
3.69M
    ns_len = after_ns - ZSTR_VAL(name) - 1;
675
3.69M
    after_ns_len = ZSTR_LEN(name) - ns_len - 1;
676
677
    /* lowercased namespace name & original constant name */
678
3.69M
    tmp_name = zend_string_init(ZSTR_VAL(name), ZSTR_LEN(name), 0);
679
3.69M
    zend_str_tolower(ZSTR_VAL(tmp_name), ns_len);
680
3.69M
    zend_add_literal_string(&tmp_name);
681
682
3.69M
    if (!unqualified) {
683
3.73k
      return ret;
684
3.73k
    }
685
3.69M
  } else {
686
198k
    after_ns = ZSTR_VAL(name);
687
198k
  }
688
689
  /* original unqualified constant name */
690
3.89M
  tmp_name = zend_string_init(after_ns, after_ns_len, 0);
691
3.89M
  zend_add_literal_string(&tmp_name);
692
693
3.89M
  return ret;
694
3.89M
}
695
/* }}} */
696
697
42.3k
#define LITERAL_STR(op, str) do { \
698
42.3k
    zval _c; \
699
42.3k
    ZVAL_STR(&_c, str); \
700
42.3k
    op.constant = zend_add_literal(&_c); \
701
42.3k
  } while (0)
702
703
void zend_stop_lexing(void)
704
68
{
705
68
  if (LANG_SCNG(on_event)) {
706
0
    LANG_SCNG(on_event)(ON_STOP, END, 0, NULL, 0, LANG_SCNG(on_event_context));
707
0
  }
708
709
68
  LANG_SCNG(yy_cursor) = LANG_SCNG(yy_limit);
710
68
}
711
712
static inline void zend_begin_loop(
713
    uint8_t free_opcode, const znode *loop_var, bool is_switch) /* {{{ */
714
90.6k
{
715
90.6k
  zend_brk_cont_element *brk_cont_element;
716
90.6k
  int parent = CG(context).current_brk_cont;
717
90.6k
  zend_loop_var info = {0};
718
719
90.6k
  CG(context).current_brk_cont = CG(context).last_brk_cont;
720
90.6k
  brk_cont_element = get_next_brk_cont_element();
721
90.6k
  brk_cont_element->parent = parent;
722
90.6k
  brk_cont_element->is_switch = is_switch;
723
724
90.6k
  if (loop_var && (loop_var->op_type & (IS_VAR|IS_TMP_VAR))) {
725
47.7k
    uint32_t start = get_next_op_number();
726
727
47.7k
    info.opcode = free_opcode;
728
47.7k
    info.var_type = loop_var->op_type;
729
47.7k
    info.var_num = loop_var->u.op.var;
730
47.7k
    brk_cont_element->start = start;
731
47.7k
  } else {
732
42.9k
    info.opcode = ZEND_NOP;
733
    /* The start field is used to free temporary variables in case of exceptions.
734
     * We won't try to free something of we don't have loop variable.  */
735
42.9k
    brk_cont_element->start = -1;
736
42.9k
  }
737
738
90.6k
  zend_stack_push(&CG(loop_var_stack), &info);
739
90.6k
}
740
/* }}} */
741
742
static inline void zend_end_loop(int cont_addr, const znode *var_node) /* {{{ */
743
90.4k
{
744
90.4k
  uint32_t end = get_next_op_number();
745
90.4k
  zend_brk_cont_element *brk_cont_element
746
90.4k
    = &CG(context).brk_cont_array[CG(context).current_brk_cont];
747
90.4k
  brk_cont_element->cont = cont_addr;
748
90.4k
  brk_cont_element->brk = end;
749
90.4k
  CG(context).current_brk_cont = brk_cont_element->parent;
750
751
90.4k
  zend_stack_del_top(&CG(loop_var_stack));
752
90.4k
}
753
/* }}} */
754
755
static void zend_do_free(znode *op1) /* {{{ */
756
1.92M
{
757
1.92M
  if (op1->op_type == IS_TMP_VAR) {
758
1.00M
    zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
759
760
1.03M
    while (opline->opcode == ZEND_END_SILENCE ||
761
1.02M
           opline->opcode == ZEND_OP_DATA) {
762
38.7k
      opline--;
763
38.7k
    }
764
765
1.00M
    if (opline->result_type == IS_TMP_VAR && opline->result.var == op1->u.op.var) {
766
992k
      switch (opline->opcode) {
767
1.51k
        case ZEND_BOOL:
768
6.55k
        case ZEND_BOOL_NOT:
769
          /* boolean results don't have to be freed */
770
6.55k
          return;
771
53
        case ZEND_POST_INC_STATIC_PROP:
772
317
        case ZEND_POST_DEC_STATIC_PROP:
773
622
        case ZEND_POST_INC_OBJ:
774
797
        case ZEND_POST_DEC_OBJ:
775
5.65k
        case ZEND_POST_INC:
776
6.11k
        case ZEND_POST_DEC:
777
          /* convert $i++ to ++$i */
778
6.11k
          opline->opcode -= 2;
779
6.11k
          SET_UNUSED(opline->result);
780
6.11k
          return;
781
116k
        case ZEND_ASSIGN:
782
126k
        case ZEND_ASSIGN_DIM:
783
137k
        case ZEND_ASSIGN_OBJ:
784
139k
        case ZEND_ASSIGN_STATIC_PROP:
785
175k
        case ZEND_ASSIGN_OP:
786
177k
        case ZEND_ASSIGN_DIM_OP:
787
178k
        case ZEND_ASSIGN_OBJ_OP:
788
180k
        case ZEND_ASSIGN_STATIC_PROP_OP:
789
180k
        case ZEND_PRE_INC_STATIC_PROP:
790
180k
        case ZEND_PRE_DEC_STATIC_PROP:
791
180k
        case ZEND_PRE_INC_OBJ:
792
181k
        case ZEND_PRE_DEC_OBJ:
793
182k
        case ZEND_PRE_INC:
794
183k
        case ZEND_PRE_DEC:
795
183k
          SET_UNUSED(opline->result);
796
183k
          return;
797
992k
      }
798
992k
    }
799
800
804k
    zend_emit_op(NULL, ZEND_FREE, op1, NULL);
801
926k
  } else if (op1->op_type == IS_VAR) {
802
849k
    zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
803
881k
    while (opline->opcode == ZEND_END_SILENCE ||
804
880k
        opline->opcode == ZEND_EXT_FCALL_END ||
805
880k
        opline->opcode == ZEND_OP_DATA) {
806
31.8k
      opline--;
807
31.8k
    }
808
849k
    if (opline->result_type == IS_VAR
809
832k
      && opline->result.var == op1->u.op.var) {
810
832k
      if (opline->opcode == ZEND_FETCH_THIS) {
811
0
        opline->opcode = ZEND_NOP;
812
0
      }
813
832k
      if (!ZEND_OP_IS_FRAMELESS_ICALL(opline->opcode)) {
814
576k
        SET_UNUSED(opline->result);
815
576k
      } else {
816
        /* Frameless calls usually use the return value, so always emit a free. This should be
817
         * faster than checking RETURN_VALUE_USED inside the handler. */
818
        // FIXME: We may actually look at the function signature to determine whether a free
819
        // is necessary.
820
256k
        zend_emit_op(NULL, ZEND_FREE, op1, NULL);
821
256k
      }
822
832k
    } else {
823
63.0k
      while (opline >= CG(active_op_array)->opcodes) {
824
63.0k
        if ((opline->opcode == ZEND_FETCH_LIST_R ||
825
61.0k
             opline->opcode == ZEND_FETCH_LIST_W ||
826
58.0k
             opline->opcode == ZEND_EXT_STMT) &&
827
4.95k
            opline->op1_type == IS_VAR &&
828
4.95k
            opline->op1.var == op1->u.op.var) {
829
4.11k
          zend_emit_op(NULL, ZEND_FREE, op1, NULL);
830
4.11k
          return;
831
4.11k
        }
832
58.9k
        if (opline->result_type == IS_VAR
833
19.4k
          && opline->result.var == op1->u.op.var) {
834
13.2k
          if (opline->opcode == ZEND_NEW) {
835
13.2k
            zend_emit_op(NULL, ZEND_FREE, op1, NULL);
836
13.2k
          }
837
13.2k
          break;
838
13.2k
        }
839
45.6k
        opline--;
840
45.6k
      }
841
17.3k
    }
842
849k
  } else if (op1->op_type == IS_CONST) {
843
    /* Destroy value without using GC: When opcache moves arrays into SHM it will
844
     * free the zend_array structure, so references to it from outside the op array
845
     * become invalid. GC would cause such a reference in the root buffer. */
846
74.6k
    zval_ptr_dtor_nogc(&op1->u.constant);
847
74.6k
  }
848
1.92M
}
849
/* }}} */
850
851
852
static const char *zend_modifier_token_to_string(uint32_t token)
853
115
{
854
115
  switch (token) {
855
7
    case T_PUBLIC:
856
7
      return "public";
857
6
    case T_PROTECTED:
858
6
      return "protected";
859
1
    case T_PRIVATE:
860
1
      return "private";
861
24
    case T_STATIC:
862
24
      return "static";
863
23
    case T_FINAL:
864
23
      return "final";
865
32
    case T_READONLY:
866
32
      return "readonly";
867
14
    case T_ABSTRACT:
868
14
      return "abstract";
869
1
    case T_PUBLIC_SET:
870
1
      return "public(set)";
871
1
    case T_PROTECTED_SET:
872
1
      return "protected(set)";
873
6
    case T_PRIVATE_SET:
874
6
      return "private(set)";
875
115
    EMPTY_SWITCH_DEFAULT_CASE()
876
115
  }
877
115
}
878
879
uint32_t zend_modifier_token_to_flag(zend_modifier_target target, uint32_t token)
880
61.5k
{
881
61.5k
  switch (token) {
882
39.2k
    case T_PUBLIC:
883
39.2k
      if (target != ZEND_MODIFIER_TARGET_PROPERTY_HOOK) {
884
39.2k
        return ZEND_ACC_PUBLIC;
885
39.2k
      }
886
7
      break;
887
2.40k
    case T_PROTECTED:
888
2.40k
      if (target != ZEND_MODIFIER_TARGET_PROPERTY_HOOK) {
889
2.39k
        return ZEND_ACC_PROTECTED;
890
2.39k
      }
891
6
      break;
892
4.84k
    case T_PRIVATE:
893
4.84k
      if (target != ZEND_MODIFIER_TARGET_PROPERTY_HOOK) {
894
4.84k
        return ZEND_ACC_PRIVATE;
895
4.84k
      }
896
1
      break;
897
1.15k
    case T_READONLY:
898
1.15k
      if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
899
1.13k
        return ZEND_ACC_READONLY;
900
1.13k
      }
901
20
      break;
902
1.25k
    case T_ABSTRACT:
903
1.25k
      if (target == ZEND_MODIFIER_TARGET_METHOD || target == ZEND_MODIFIER_TARGET_PROPERTY) {
904
1.25k
        return ZEND_ACC_ABSTRACT;
905
1.25k
      }
906
3
      break;
907
1.44k
    case T_FINAL:
908
1.44k
      return ZEND_ACC_FINAL;
909
10.0k
    case T_STATIC:
910
10.0k
      if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_METHOD) {
911
9.99k
        return ZEND_ACC_STATIC;
912
9.99k
      }
913
13
      break;
914
383
    case T_PUBLIC_SET:
915
383
      if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
916
382
        return ZEND_ACC_PUBLIC_SET;
917
382
      }
918
1
      break;
919
225
    case T_PROTECTED_SET:
920
225
      if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
921
224
        return ZEND_ACC_PROTECTED_SET;
922
224
      }
923
1
      break;
924
614
    case T_PRIVATE_SET:
925
614
      if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
926
608
        return ZEND_ACC_PRIVATE_SET;
927
608
      }
928
6
      break;
929
61.5k
  }
930
931
58
  char *member;
932
58
  if (target == ZEND_MODIFIER_TARGET_PROPERTY) {
933
0
    member = "property";
934
58
  } else if (target == ZEND_MODIFIER_TARGET_METHOD) {
935
16
    member = "method";
936
42
  } else if (target == ZEND_MODIFIER_TARGET_CONSTANT) {
937
7
    member = "class constant";
938
35
  } else if (target == ZEND_MODIFIER_TARGET_CPP) {
939
8
    member = "parameter";
940
27
  } else if (target == ZEND_MODIFIER_TARGET_PROPERTY_HOOK) {
941
27
    member = "property hook";
942
27
  } else {
943
0
    ZEND_UNREACHABLE();
944
0
  }
945
946
58
  zend_throw_exception_ex(zend_ce_compile_error, 0,
947
58
    "Cannot use the %s modifier on a %s", zend_modifier_token_to_string(token), member);
948
58
  return 0;
949
58
}
950
951
uint32_t zend_modifier_list_to_flags(zend_modifier_target target, zend_ast *modifiers)
952
52.4k
{
953
52.4k
  uint32_t flags = 0;
954
52.4k
  zend_ast_list *modifier_list = zend_ast_get_list(modifiers);
955
956
112k
  for (uint32_t i = 0; i < modifier_list->children; i++) {
957
60.7k
    uint32_t token = (uint32_t) Z_LVAL_P(zend_ast_get_zval(modifier_list->child[i]));
958
60.7k
    uint32_t new_flag = zend_modifier_token_to_flag(target, token);
959
60.7k
    if (!new_flag) {
960
50
      return 0;
961
50
    }
962
    /* Don't error immediately for duplicate flags, we want to prioritize the errors from zend_add_member_modifier(). */
963
60.7k
    bool duplicate_flag = (flags & new_flag);
964
60.6k
    flags = zend_add_member_modifier(flags, new_flag, target);
965
60.6k
    if (!flags) {
966
71
      return 0;
967
71
    }
968
60.5k
    if (duplicate_flag) {
969
57
      zend_throw_exception_ex(zend_ce_compile_error, 0,
970
57
        "Multiple %s modifiers are not allowed", zend_modifier_token_to_string(token));
971
57
      return 0;
972
57
    }
973
60.5k
  }
974
975
52.2k
  return flags;
976
52.4k
}
977
978
uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
979
211
{
980
211
  uint32_t new_flags = flags | new_flag;
981
211
  if ((flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flag & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
982
2
    zend_throw_exception(zend_ce_compile_error,
983
2
      "Multiple abstract modifiers are not allowed", 0);
984
2
    return 0;
985
2
  }
986
209
  if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
987
10
    zend_throw_exception(zend_ce_compile_error, "Multiple final modifiers are not allowed", 0);
988
10
    return 0;
989
10
  }
990
199
  if ((flags & ZEND_ACC_READONLY_CLASS) && (new_flag & ZEND_ACC_READONLY_CLASS)) {
991
8
    zend_throw_exception(zend_ce_compile_error, "Multiple readonly modifiers are not allowed", 0);
992
8
    return 0;
993
8
  }
994
191
  if ((new_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flags & ZEND_ACC_FINAL)) {
995
8
    zend_throw_exception(zend_ce_compile_error,
996
8
      "Cannot use the final modifier on an abstract class", 0);
997
8
    return 0;
998
8
  }
999
183
  return new_flags;
1000
191
}
1001
/* }}} */
1002
1003
uint32_t zend_add_anonymous_class_modifier(uint32_t flags, uint32_t new_flag)
1004
93
{
1005
93
  uint32_t new_flags = flags | new_flag;
1006
93
  if (new_flag & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
1007
7
    zend_throw_exception(zend_ce_compile_error,
1008
7
      "Cannot use the abstract modifier on an anonymous class", 0);
1009
7
    return 0;
1010
7
  }
1011
86
  if (new_flag & ZEND_ACC_FINAL) {
1012
7
    zend_throw_exception(zend_ce_compile_error, "Cannot use the final modifier on an anonymous class", 0);
1013
7
    return 0;
1014
7
  }
1015
79
  if ((flags & ZEND_ACC_READONLY_CLASS) && (new_flag & ZEND_ACC_READONLY_CLASS)) {
1016
7
    zend_throw_exception(zend_ce_compile_error, "Multiple readonly modifiers are not allowed", 0);
1017
7
    return 0;
1018
7
  }
1019
72
  return new_flags;
1020
79
}
1021
1022
uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag, zend_modifier_target target) /* {{{ */
1023
60.6k
{
1024
60.6k
  uint32_t new_flags = flags | new_flag;
1025
60.6k
  if ((flags & ZEND_ACC_PPP_MASK) && (new_flag & ZEND_ACC_PPP_MASK)) {
1026
40
    zend_throw_exception(zend_ce_compile_error,
1027
40
      "Multiple access type modifiers are not allowed", 0);
1028
40
    return 0;
1029
40
  }
1030
60.6k
  if ((new_flags & ZEND_ACC_ABSTRACT) && (new_flags & ZEND_ACC_FINAL)) {
1031
14
    if (target == ZEND_MODIFIER_TARGET_METHOD) {
1032
7
      zend_throw_exception(zend_ce_compile_error,
1033
7
        "Cannot use the final modifier on an abstract method", 0);
1034
7
      return 0;
1035
7
    }
1036
7
    if (target == ZEND_MODIFIER_TARGET_PROPERTY) {
1037
7
      zend_throw_exception(zend_ce_compile_error,
1038
7
        "Cannot use the final modifier on an abstract property", 0);
1039
7
      return 0;
1040
7
    }
1041
7
  }
1042
60.6k
  if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
1043
29.8k
    if ((flags & ZEND_ACC_PPP_SET_MASK) && (new_flag & ZEND_ACC_PPP_SET_MASK)) {
1044
17
      zend_throw_exception(zend_ce_compile_error,
1045
17
        "Multiple access type modifiers are not allowed", 0);
1046
17
      return 0;
1047
17
    }
1048
29.8k
  }
1049
60.5k
  return new_flags;
1050
60.6k
}
1051
/* }}} */
1052
1053
20.4k
ZEND_API zend_string *zend_create_member_string(zend_string *class_name, zend_string *member_name) {
1054
20.4k
  return zend_string_concat3(
1055
20.4k
    ZSTR_VAL(class_name), ZSTR_LEN(class_name),
1056
20.4k
    "::", sizeof("::") - 1,
1057
20.4k
    ZSTR_VAL(member_name), ZSTR_LEN(member_name));
1058
20.4k
}
1059
1060
7.16M
static zend_string *zend_concat_names(char *name1, size_t name1_len, char *name2, size_t name2_len) {
1061
7.16M
  return zend_string_concat3(name1, name1_len, "\\", 1, name2, name2_len);
1062
7.16M
}
1063
1064
7.93M
static zend_string *zend_prefix_with_ns(zend_string *name) {
1065
7.93M
  if (FC(current_namespace)) {
1066
7.16M
    zend_string *ns = FC(current_namespace);
1067
7.16M
    return zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
1068
7.16M
  } else {
1069
770k
    return zend_string_copy(name);
1070
770k
  }
1071
7.93M
}
1072
1073
static zend_string *zend_resolve_non_class_name(
1074
  zend_string *name, uint32_t type, bool *is_fully_qualified,
1075
  bool case_sensitive, HashTable *current_import_sub
1076
5.81M
) {
1077
5.81M
  char *compound;
1078
5.81M
  *is_fully_qualified = false;
1079
1080
5.81M
  if (ZSTR_VAL(name)[0] == '\\') {
1081
    /* Remove \ prefix (only relevant if this is a string rather than a label) */
1082
572
    *is_fully_qualified = true;
1083
572
    return zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
1084
572
  }
1085
1086
5.81M
  if (type == ZEND_NAME_FQ) {
1087
63.6k
    *is_fully_qualified = true;
1088
63.6k
    return zend_string_copy(name);
1089
63.6k
  }
1090
1091
5.75M
  if (type == ZEND_NAME_RELATIVE) {
1092
1.05k
    *is_fully_qualified = true;
1093
1.05k
    return zend_prefix_with_ns(name);
1094
1.05k
  }
1095
1096
5.75M
  if (current_import_sub) {
1097
    /* If an unqualified name is a function/const alias, replace it. */
1098
1.61k
    zend_string *import_name;
1099
1.61k
    if (case_sensitive) {
1100
1.18k
      import_name = zend_hash_find_ptr(current_import_sub, name);
1101
1.18k
    } else {
1102
424
      import_name = zend_hash_find_ptr_lc(current_import_sub, name);
1103
424
    }
1104
1105
1.61k
    if (import_name) {
1106
553
      *is_fully_qualified = true;
1107
553
      return zend_string_copy(import_name);
1108
553
    }
1109
1.61k
  }
1110
1111
5.75M
  compound = memchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
1112
5.75M
  if (compound) {
1113
7.75k
    *is_fully_qualified = true;
1114
7.75k
  }
1115
1116
5.75M
  if (compound && FC(imports)) {
1117
    /* If the first part of a qualified name is an alias, substitute it. */
1118
2.58k
    size_t len = compound - ZSTR_VAL(name);
1119
2.58k
    zend_string *import_name = zend_hash_str_find_ptr_lc(FC(imports), ZSTR_VAL(name), len);
1120
1121
2.58k
    if (import_name) {
1122
340
      return zend_concat_names(
1123
340
        ZSTR_VAL(import_name), ZSTR_LEN(import_name), ZSTR_VAL(name) + len + 1, ZSTR_LEN(name) - len - 1);
1124
340
    }
1125
2.58k
  }
1126
1127
5.75M
  return zend_prefix_with_ns(name);
1128
5.75M
}
1129
/* }}} */
1130
1131
static zend_string *zend_resolve_function_name(zend_string *name, uint32_t type, bool *is_fully_qualified)
1132
1.71M
{
1133
1.71M
  return zend_resolve_non_class_name(
1134
1.71M
    name, type, is_fully_qualified, false, FC(imports_function));
1135
1.71M
}
1136
1137
static zend_string *zend_resolve_const_name(zend_string *name, uint32_t type, bool *is_fully_qualified)
1138
4.10M
{
1139
4.10M
  return zend_resolve_non_class_name(
1140
4.10M
    name, type, is_fully_qualified, true, FC(imports_const));
1141
4.10M
}
1142
1143
static zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
1144
2.06M
{
1145
2.06M
  char *compound;
1146
1147
2.06M
  if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
1148
2.87k
    if (type == ZEND_NAME_FQ) {
1149
7
      zend_error_noreturn(E_COMPILE_ERROR,
1150
7
        "'\\%s' is an invalid class name", ZSTR_VAL(name));
1151
7
    }
1152
2.86k
    if (type == ZEND_NAME_RELATIVE) {
1153
0
      zend_error_noreturn(E_COMPILE_ERROR,
1154
0
        "'namespace\\%s' is an invalid class name", ZSTR_VAL(name));
1155
0
    }
1156
2.86k
    ZEND_ASSERT(type == ZEND_NAME_NOT_FQ);
1157
2.86k
    return zend_string_copy(name);
1158
2.86k
  }
1159
1160
2.06M
  if (type == ZEND_NAME_RELATIVE) {
1161
501
    return zend_prefix_with_ns(name);
1162
501
  }
1163
1164
2.06M
  if (type == ZEND_NAME_FQ) {
1165
14.6k
    if (ZSTR_VAL(name)[0] == '\\') {
1166
      /* Remove \ prefix (only relevant if this is a string rather than a label) */
1167
122
      name = zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
1168
122
      if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
1169
0
        zend_error_noreturn(E_COMPILE_ERROR,
1170
0
          "'\\%s' is an invalid class name", ZSTR_VAL(name));
1171
0
      }
1172
122
      return name;
1173
122
    }
1174
1175
14.4k
    return zend_string_copy(name);
1176
14.6k
  }
1177
1178
2.04M
  if (FC(imports)) {
1179
3.32k
    compound = memchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
1180
3.32k
    if (compound) {
1181
      /* If the first part of a qualified name is an alias, substitute it. */
1182
882
      size_t len = compound - ZSTR_VAL(name);
1183
882
      zend_string *import_name =
1184
882
        zend_hash_str_find_ptr_lc(FC(imports), ZSTR_VAL(name), len);
1185
1186
882
      if (import_name) {
1187
400
        return zend_concat_names(
1188
400
          ZSTR_VAL(import_name), ZSTR_LEN(import_name), ZSTR_VAL(name) + len + 1, ZSTR_LEN(name) - len - 1);
1189
400
      }
1190
2.44k
    } else {
1191
      /* If an unqualified name is an alias, replace it. */
1192
2.44k
      zend_string *import_name
1193
2.44k
        = zend_hash_find_ptr_lc(FC(imports), name);
1194
1195
2.44k
      if (import_name) {
1196
907
        return zend_string_copy(import_name);
1197
907
      }
1198
2.44k
    }
1199
3.32k
  }
1200
1201
  /* If not fully qualified and not an alias, prepend the current namespace */
1202
2.04M
  return zend_prefix_with_ns(name);
1203
2.04M
}
1204
/* }}} */
1205
1206
static zend_string *zend_resolve_class_name_ast(zend_ast *ast) /* {{{ */
1207
2.00M
{
1208
2.00M
  zval *class_name = zend_ast_get_zval(ast);
1209
2.00M
  if (Z_TYPE_P(class_name) != IS_STRING) {
1210
40
    zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
1211
40
  }
1212
2.00M
  return zend_resolve_class_name(Z_STR_P(class_name), ast->attr);
1213
2.00M
}
1214
/* }}} */
1215
1216
static void label_ptr_dtor(zval *zv) /* {{{ */
1217
4.09k
{
1218
4.09k
  efree_size(Z_PTR_P(zv), sizeof(zend_label));
1219
4.09k
}
1220
/* }}} */
1221
1222
1.75k
static void str_dtor(zval *zv)  /* {{{ */ {
1223
1.75k
  zend_string_release_ex(Z_STR_P(zv), 0);
1224
1.75k
}
1225
/* }}} */
1226
1227
static bool zend_is_call(zend_ast *ast);
1228
1229
static uint32_t zend_add_try_element(uint32_t try_op) /* {{{ */
1230
46.9k
{
1231
46.9k
  zend_op_array *op_array = CG(active_op_array);
1232
46.9k
  uint32_t try_catch_offset = op_array->last_try_catch++;
1233
46.9k
  zend_try_catch_element *elem;
1234
1235
46.9k
  op_array->try_catch_array = safe_erealloc(
1236
46.9k
    op_array->try_catch_array, sizeof(zend_try_catch_element), op_array->last_try_catch, 0);
1237
1238
46.9k
  elem = &op_array->try_catch_array[try_catch_offset];
1239
46.9k
  elem->try_op = try_op;
1240
46.9k
  elem->catch_op = 0;
1241
46.9k
  elem->finally_op = 0;
1242
46.9k
  elem->finally_end = 0;
1243
1244
46.9k
  return try_catch_offset;
1245
46.9k
}
1246
/* }}} */
1247
1248
ZEND_API void function_add_ref(zend_function *function) /* {{{ */
1249
1.85k
{
1250
1.85k
  if (function->type == ZEND_USER_FUNCTION) {
1251
1.85k
    zend_op_array *op_array = &function->op_array;
1252
1.85k
    if (op_array->refcount) {
1253
325
      (*op_array->refcount)++;
1254
325
    }
1255
1256
1.85k
    ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
1257
1.85k
    ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, NULL);
1258
1.85k
  }
1259
1260
1.85k
  if (function->common.function_name) {
1261
1.85k
    zend_string_addref(function->common.function_name);
1262
1.85k
  }
1263
1.85k
}
1264
/* }}} */
1265
1266
static zend_never_inline ZEND_COLD ZEND_NORETURN void do_bind_function_error(zend_string *lcname, zend_op_array *op_array, bool compile_time) /* {{{ */
1267
103
{
1268
103
  zval *zv = zend_hash_find_known_hash(compile_time ? CG(function_table) : EG(function_table), lcname);
1269
103
  int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
1270
103
  zend_function *old_function;
1271
1272
103
  ZEND_ASSERT(zv != NULL);
1273
103
  old_function = (zend_function*)Z_PTR_P(zv);
1274
103
  if (old_function->type == ZEND_USER_FUNCTION
1275
95
    && old_function->op_array.last > 0) {
1276
95
    zend_error_noreturn(error_level, "Cannot redeclare function %s() (previously declared in %s:%d)",
1277
95
          op_array ? ZSTR_VAL(op_array->function_name) : ZSTR_VAL(old_function->common.function_name),
1278
95
          ZSTR_VAL(old_function->op_array.filename),
1279
95
          old_function->op_array.line_start);
1280
95
  } else {
1281
8
    zend_error_noreturn(error_level, "Cannot redeclare function %s()",
1282
8
      op_array ? ZSTR_VAL(op_array->function_name) : ZSTR_VAL(old_function->common.function_name));
1283
8
  }
1284
103
}
1285
1286
ZEND_API zend_result do_bind_function(zend_function *func, zval *lcname) /* {{{ */
1287
95
{
1288
95
  zend_function *added_func = zend_hash_add_ptr(EG(function_table), Z_STR_P(lcname), func);
1289
95
  if (UNEXPECTED(!added_func)) {
1290
0
    do_bind_function_error(Z_STR_P(lcname), &func->op_array, false);
1291
0
    return FAILURE;
1292
0
  }
1293
1294
95
  if (func->op_array.refcount) {
1295
21
    ++*func->op_array.refcount;
1296
21
  }
1297
95
  if (func->common.function_name) {
1298
95
    zend_string_addref(func->common.function_name);
1299
95
  }
1300
95
  zend_observer_function_declared_notify(&func->op_array, Z_STR_P(lcname));
1301
95
  return SUCCESS;
1302
95
}
1303
/* }}} */
1304
1305
ZEND_API zend_class_entry *zend_bind_class_in_slot(
1306
    zval *class_table_slot, zval *lcname, zend_string *lc_parent_name)
1307
6.94k
{
1308
6.94k
  zend_class_entry *ce = Z_PTR_P(class_table_slot);
1309
6.94k
  bool is_preloaded =
1310
6.94k
    (ce->ce_flags & ZEND_ACC_PRELOADED) && !(CG(compiler_options) & ZEND_COMPILE_PRELOAD);
1311
6.94k
  bool success;
1312
6.94k
  if (EXPECTED(!is_preloaded)) {
1313
6.94k
    success = zend_hash_set_bucket_key(EG(class_table), (Bucket*) class_table_slot, Z_STR_P(lcname)) != NULL;
1314
6.94k
  } else {
1315
    /* If preloading is used, don't replace the existing bucket, add a new one. */
1316
0
    success = zend_hash_add_ptr(EG(class_table), Z_STR_P(lcname), ce) != NULL;
1317
0
  }
1318
6.94k
  if (UNEXPECTED(!success)) {
1319
140
    zend_class_entry *old_class = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname));
1320
140
    ZEND_ASSERT(old_class);
1321
140
    zend_class_redeclaration_error(E_COMPILE_ERROR, old_class);
1322
140
    return NULL;
1323
140
  }
1324
1325
6.80k
  if (ce->ce_flags & ZEND_ACC_LINKED) {
1326
244
    zend_observer_class_linked_notify(ce, Z_STR_P(lcname));
1327
244
    return ce;
1328
244
  }
1329
1330
6.56k
  ce = zend_do_link_class(ce, lc_parent_name, Z_STR_P(lcname));
1331
6.56k
  if (ce) {
1332
5.11k
    zend_observer_class_linked_notify(ce, Z_STR_P(lcname));
1333
5.11k
    return ce;
1334
5.11k
  }
1335
1336
1.44k
  if (!is_preloaded) {
1337
    /* Reload bucket pointer, the hash table may have been reallocated */
1338
278
    zval *zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
1339
278
    zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1));
1340
1.16k
  } else {
1341
1.16k
    zend_hash_del(EG(class_table), Z_STR_P(lcname));
1342
1.16k
  }
1343
1.44k
  return NULL;
1344
6.56k
}
1345
1346
ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */
1347
6.32k
{
1348
6.32k
  zend_class_entry *ce;
1349
6.32k
  zval *rtd_key, *zv;
1350
1351
6.32k
  rtd_key = lcname + 1;
1352
1353
6.32k
  zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(rtd_key));
1354
1355
6.32k
  if (UNEXPECTED(!zv)) {
1356
15
    ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname));
1357
15
    ZEND_ASSERT(ce);
1358
15
    zend_class_redeclaration_error(E_COMPILE_ERROR, ce);
1359
15
    return FAILURE;
1360
15
  }
1361
1362
  /* Register the derived class */
1363
6.30k
  return zend_bind_class_in_slot(zv, lcname, lc_parent_name) ? SUCCESS : FAILURE;
1364
6.32k
}
1365
/* }}} */
1366
1367
17.9k
static zend_string *add_type_string(zend_string *type, zend_string *new_type, bool is_intersection) {
1368
17.9k
  zend_string *result;
1369
17.9k
  if (type == NULL) {
1370
12.2k
    return zend_string_copy(new_type);
1371
12.2k
  }
1372
1373
5.60k
  if (is_intersection) {
1374
2.74k
    result = zend_string_concat3(ZSTR_VAL(type), ZSTR_LEN(type),
1375
2.74k
      "&", 1, ZSTR_VAL(new_type), ZSTR_LEN(new_type));
1376
2.74k
    zend_string_release(type);
1377
2.85k
  } else {
1378
2.85k
    result = zend_string_concat3(
1379
2.85k
      ZSTR_VAL(type), ZSTR_LEN(type), "|", 1, ZSTR_VAL(new_type), ZSTR_LEN(new_type));
1380
2.85k
    zend_string_release(type);
1381
2.85k
  }
1382
5.60k
  return result;
1383
17.9k
}
1384
1385
3.39k
static zend_string *resolve_class_name(zend_string *name, zend_class_entry *scope) {
1386
3.39k
  if (scope) {
1387
2.19k
    if (zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_SELF))) {
1388
31
      name = scope->name;
1389
2.16k
    } else if (zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_PARENT)) && scope->parent) {
1390
0
      name = scope->parent->name;
1391
0
    }
1392
2.19k
  }
1393
1394
  /* The resolved name for anonymous classes contains null bytes. Cut off everything after the
1395
   * null byte here, to avoid larger parts of the type being omitted by printing code later. */
1396
3.39k
  size_t len = strlen(ZSTR_VAL(name));
1397
3.39k
  if (len != ZSTR_LEN(name)) {
1398
12
    return zend_string_init(ZSTR_VAL(name), len, 0);
1399
12
  }
1400
3.38k
  return zend_string_copy(name);
1401
3.39k
}
1402
1403
static zend_string *add_intersection_type(zend_string *str,
1404
  const zend_type_list *intersection_type_list, zend_class_entry *scope,
1405
  bool is_bracketed)
1406
1.56k
{
1407
1.56k
  const zend_type *single_type;
1408
1.56k
  zend_string *intersection_str = NULL;
1409
1410
5.88k
  ZEND_TYPE_LIST_FOREACH(intersection_type_list, single_type) {
1411
5.88k
    ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*single_type));
1412
5.88k
    ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*single_type));
1413
1414
4.31k
    intersection_str = add_type_string(intersection_str, ZEND_TYPE_NAME(*single_type), /* is_intersection */ true);
1415
4.31k
  } ZEND_TYPE_LIST_FOREACH_END();
1416
1417
1.56k
  ZEND_ASSERT(intersection_str);
1418
1419
1.56k
  if (is_bracketed) {
1420
1.19k
    zend_string *result = zend_string_concat3("(", 1, ZSTR_VAL(intersection_str), ZSTR_LEN(intersection_str), ")", 1);
1421
1.19k
    zend_string_release(intersection_str);
1422
1.19k
    intersection_str = result;
1423
1.19k
  }
1424
1.56k
  str = add_type_string(str, intersection_str, /* is_intersection */ false);
1425
1.56k
  zend_string_release(intersection_str);
1426
1.56k
  return str;
1427
1.56k
}
1428
1429
13.0k
zend_string *zend_type_to_string_resolved(const zend_type type, zend_class_entry *scope) {
1430
13.0k
  zend_string *str = NULL;
1431
1432
  /* Pure intersection type */
1433
13.0k
  if (ZEND_TYPE_IS_INTERSECTION(type)) {
1434
372
    ZEND_ASSERT(!ZEND_TYPE_IS_UNION(type));
1435
372
    str = add_intersection_type(str, ZEND_TYPE_LIST(type), scope, /* is_bracketed */ false);
1436
12.6k
  } else if (ZEND_TYPE_HAS_LIST(type)) {
1437
    /* A union type might not be a list */
1438
585
    const zend_type *list_type;
1439
2.87k
    ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) {
1440
2.87k
      if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {
1441
1.19k
        str = add_intersection_type(str, ZEND_TYPE_LIST(*list_type), scope, /* is_bracketed */ true);
1442
1.19k
        continue;
1443
1.19k
      }
1444
1.09k
      ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
1445
1.09k
      ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*list_type));
1446
1447
1.09k
      zend_string *name = ZEND_TYPE_NAME(*list_type);
1448
1.09k
      zend_string *resolved = resolve_class_name(name, scope);
1449
1.09k
      str = add_type_string(str, resolved, /* is_intersection */ false);
1450
1.09k
      zend_string_release(resolved);
1451
1.09k
    } ZEND_TYPE_LIST_FOREACH_END();
1452
12.0k
  } else if (ZEND_TYPE_HAS_NAME(type)) {
1453
2.29k
    str = resolve_class_name(ZEND_TYPE_NAME(type), scope);
1454
2.29k
  }
1455
1456
13.0k
  uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
1457
1458
13.0k
  if (type_mask == MAY_BE_ANY) {
1459
132
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_MIXED), /* is_intersection */ false);
1460
1461
132
    return str;
1462
132
  }
1463
12.9k
  if (type_mask & MAY_BE_STATIC) {
1464
126
    zend_string *name = ZSTR_KNOWN(ZEND_STR_STATIC);
1465
    // During compilation of eval'd code the called scope refers to the scope calling the eval
1466
126
    if (scope && !zend_is_compiling()) {
1467
36
      zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
1468
36
      if (called_scope) {
1469
15
        name = called_scope->name;
1470
15
      }
1471
36
    }
1472
126
    str = add_type_string(str, name, /* is_intersection */ false);
1473
126
  }
1474
12.9k
  if (type_mask & MAY_BE_CALLABLE) {
1475
55
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_CALLABLE), /* is_intersection */ false);
1476
55
  }
1477
12.9k
  if (type_mask & MAY_BE_OBJECT) {
1478
206
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_OBJECT), /* is_intersection */ false);
1479
206
  }
1480
12.9k
  if (type_mask & MAY_BE_ARRAY) {
1481
941
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_ARRAY), /* is_intersection */ false);
1482
941
  }
1483
12.9k
  if (type_mask & MAY_BE_STRING) {
1484
5.06k
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_STRING), /* is_intersection */ false);
1485
5.06k
  }
1486
12.9k
  if (type_mask & MAY_BE_LONG) {
1487
3.20k
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_INT), /* is_intersection */ false);
1488
3.20k
  }
1489
12.9k
  if (type_mask & MAY_BE_DOUBLE) {
1490
244
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_FLOAT), /* is_intersection */ false);
1491
244
  }
1492
12.9k
  if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL) {
1493
429
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_BOOL), /* is_intersection */ false);
1494
12.4k
  } else if (type_mask & MAY_BE_FALSE) {
1495
116
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_FALSE), /* is_intersection */ false);
1496
12.3k
  } else if (type_mask & MAY_BE_TRUE) {
1497
49
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_TRUE), /* is_intersection */ false);
1498
49
  }
1499
12.9k
  if (type_mask & MAY_BE_VOID) {
1500
149
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_VOID), /* is_intersection */ false);
1501
149
  }
1502
12.9k
  if (type_mask & MAY_BE_NEVER) {
1503
22
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_NEVER), /* is_intersection */ false);
1504
22
  }
1505
1506
12.9k
  if (type_mask & MAY_BE_NULL) {
1507
1.19k
    bool is_union = !str || memchr(ZSTR_VAL(str), '|', ZSTR_LEN(str)) != NULL;
1508
1.19k
    bool has_intersection = !str || memchr(ZSTR_VAL(str), '&', ZSTR_LEN(str)) != NULL;
1509
1.19k
    if (!is_union && !has_intersection) {
1510
1.01k
      zend_string *nullable_str = zend_string_concat2("?", 1, ZSTR_VAL(str), ZSTR_LEN(str));
1511
1.01k
      zend_string_release(str);
1512
1.01k
      return nullable_str;
1513
1.01k
    }
1514
1515
182
    str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_NULL_LOWERCASE), /* is_intersection */ false);
1516
182
  }
1517
11.8k
  return str;
1518
12.9k
}
1519
1520
7.91k
ZEND_API zend_string *zend_type_to_string(zend_type type) {
1521
7.91k
  return zend_type_to_string_resolved(type, NULL);
1522
7.91k
}
1523
1524
899
static bool is_generator_compatible_class_type(const zend_string *name) {
1525
899
  return zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_TRAVERSABLE))
1526
702
    || zend_string_equals_literal_ci(name, "Iterator")
1527
614
    || zend_string_equals_literal_ci(name, "Generator");
1528
899
}
1529
1530
static void zend_mark_function_as_generator(void) /* {{{ */
1531
22.7k
{
1532
22.7k
  if (!CG(active_op_array)->function_name) {
1533
88
    zend_error_noreturn(E_COMPILE_ERROR,
1534
88
      "The \"yield\" expression can only be used inside a function");
1535
88
  }
1536
1537
22.7k
  if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
1538
799
    const zend_type return_type = CG(active_op_array)->arg_info[-1].type;
1539
799
    bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & MAY_BE_OBJECT) != 0;
1540
799
    if (!valid_type) {
1541
766
      const zend_type *single_type;
1542
1.67k
      ZEND_TYPE_FOREACH(return_type, single_type) {
1543
1.67k
        if (ZEND_TYPE_HAS_NAME(*single_type)
1544
899
            && is_generator_compatible_class_type(ZEND_TYPE_NAME(*single_type))) {
1545
726
          valid_type = true;
1546
726
          break;
1547
726
        }
1548
1.67k
      } ZEND_TYPE_FOREACH_END();
1549
766
    }
1550
1551
799
    if (!valid_type) {
1552
40
      zend_string *str = zend_type_to_string(return_type);
1553
40
      zend_error_noreturn(E_COMPILE_ERROR,
1554
40
        "Generator return type must be a supertype of Generator, %s given",
1555
40
        ZSTR_VAL(str));
1556
40
    }
1557
799
  }
1558
1559
22.6k
  CG(active_op_array)->fn_flags |= ZEND_ACC_GENERATOR;
1560
22.6k
}
1561
/* }}} */
1562
1563
ZEND_API zend_string *zend_mangle_property_name(const char *src1, size_t src1_length, const char *src2, size_t src2_length, bool internal) /* {{{ */
1564
64.7k
{
1565
64.7k
  size_t prop_name_length = 1 + src1_length + 1 + src2_length;
1566
64.7k
  zend_string *prop_name = zend_string_alloc(prop_name_length, internal);
1567
1568
64.7k
  ZSTR_VAL(prop_name)[0] = '\0';
1569
64.7k
  memcpy(ZSTR_VAL(prop_name) + 1, src1, src1_length+1);
1570
64.7k
  memcpy(ZSTR_VAL(prop_name) + 1 + src1_length + 1, src2, src2_length+1);
1571
64.7k
  return prop_name;
1572
64.7k
}
1573
/* }}} */
1574
1575
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) /* {{{ */
1576
1.45M
{
1577
1.45M
  size_t class_name_len;
1578
1.45M
  size_t anonclass_src_len;
1579
1580
1.45M
  *class_name = NULL;
1581
1582
1.45M
  if (!ZSTR_LEN(name) || ZSTR_VAL(name)[0] != '\0') {
1583
1.31M
    *prop_name = ZSTR_VAL(name);
1584
1.31M
    if (prop_len) {
1585
885k
      *prop_len = ZSTR_LEN(name);
1586
885k
    }
1587
1.31M
    return SUCCESS;
1588
1.31M
  }
1589
142k
  if (ZSTR_LEN(name) < 3 || ZSTR_VAL(name)[1] == '\0') {
1590
1.55k
    zend_error(E_NOTICE, "Illegal member variable name");
1591
1.55k
    *prop_name = ZSTR_VAL(name);
1592
1.55k
    if (prop_len) {
1593
1.53k
      *prop_len = ZSTR_LEN(name);
1594
1.53k
    }
1595
1.55k
    return FAILURE;
1596
1.55k
  }
1597
1598
141k
  class_name_len = zend_strnlen(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 2);
1599
141k
  if (class_name_len >= ZSTR_LEN(name) - 2 || ZSTR_VAL(name)[class_name_len + 1] != '\0') {
1600
637
    zend_error(E_NOTICE, "Corrupt member variable name");
1601
637
    *prop_name = ZSTR_VAL(name);
1602
637
    if (prop_len) {
1603
591
      *prop_len = ZSTR_LEN(name);
1604
591
    }
1605
637
    return FAILURE;
1606
637
  }
1607
1608
140k
  *class_name = ZSTR_VAL(name) + 1;
1609
140k
  anonclass_src_len = zend_strnlen(*class_name + class_name_len + 1, ZSTR_LEN(name) - class_name_len - 2);
1610
140k
  if (class_name_len + anonclass_src_len + 2 != ZSTR_LEN(name)) {
1611
31.2k
    class_name_len += anonclass_src_len + 1;
1612
31.2k
  }
1613
140k
  *prop_name = ZSTR_VAL(name) + class_name_len + 2;
1614
140k
  if (prop_len) {
1615
88.2k
    *prop_len = ZSTR_LEN(name) - class_name_len - 2;
1616
88.2k
  }
1617
140k
  return SUCCESS;
1618
141k
}
1619
/* }}} */
1620
1621
static bool array_is_const_ex(zend_array *array, uint32_t *max_checks)
1622
197
{
1623
197
  if (zend_hash_num_elements(array) > *max_checks) {
1624
3
    return false;
1625
3
  }
1626
194
  *max_checks -= zend_hash_num_elements(array);
1627
1628
194
  zval *element;
1629
548
  ZEND_HASH_FOREACH_VAL(array, element) {
1630
548
    if (Z_TYPE_P(element) < IS_ARRAY) {
1631
27
      continue;
1632
150
    } else if (Z_TYPE_P(element) == IS_ARRAY) {
1633
150
      if (!array_is_const_ex(array, max_checks)) {
1634
150
        return false;
1635
150
      }
1636
150
    } else {
1637
0
      return false;
1638
0
    }
1639
548
  } ZEND_HASH_FOREACH_END();
1640
1641
44
  return true;
1642
194
}
1643
1644
static bool array_is_const(zend_array *array)
1645
47
{
1646
47
  uint32_t max_checks = 50;
1647
47
  return array_is_const_ex(array, &max_checks);
1648
47
}
1649
1650
10.4k
static bool can_ct_eval_const(zend_constant *c) {
1651
10.4k
  if (ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED) {
1652
143
    return 0;
1653
143
  }
1654
10.3k
  if ((ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)
1655
10.3k
      && !(CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION)
1656
9.60k
      && !((ZEND_CONSTANT_FLAGS(c) & CONST_NO_FILE_CACHE)
1657
9.60k
        && (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) {
1658
9.60k
    return 1;
1659
9.60k
  }
1660
718
  if (Z_TYPE(c->value) < IS_ARRAY
1661
718
      && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
1662
15
    return 1;
1663
703
  } else if (Z_TYPE(c->value) == IS_ARRAY
1664
0
      && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)
1665
0
      && array_is_const(Z_ARR(c->value))) {
1666
0
    return 1;
1667
0
  }
1668
703
  return 0;
1669
718
}
1670
1671
static bool zend_try_ct_eval_const(zval *zv, zend_string *name, bool is_fully_qualified) /* {{{ */
1672
4.10M
{
1673
  /* Substitute true, false and null (including unqualified usage in namespaces)
1674
   * before looking up the possibly namespaced name. */
1675
4.10M
  const char *lookup_name = ZSTR_VAL(name);
1676
4.10M
  size_t lookup_len = ZSTR_LEN(name);
1677
1678
4.10M
  if (!is_fully_qualified) {
1679
4.09M
    zend_get_unqualified_name(name, &lookup_name, &lookup_len);
1680
4.09M
  }
1681
1682
4.10M
  zend_constant *c;
1683
4.10M
  if ((c = zend_get_special_const(lookup_name, lookup_len))) {
1684
31.9k
    ZVAL_COPY_VALUE(zv, &c->value);
1685
31.9k
    return 1;
1686
31.9k
  }
1687
4.07M
  c = zend_hash_find_ptr(EG(zend_constants), name);
1688
4.07M
  if (c && can_ct_eval_const(c)) {
1689
9.61k
    ZVAL_COPY_OR_DUP(zv, &c->value);
1690
9.61k
    return 1;
1691
9.61k
  }
1692
4.06M
  return 0;
1693
4.07M
}
1694
/* }}} */
1695
1696
static inline bool zend_is_scope_known(void) /* {{{ */
1697
15.4k
{
1698
15.4k
  if (!CG(active_op_array)) {
1699
    /* This can only happen when evaluating a default value string. */
1700
0
    return 0;
1701
0
  }
1702
1703
15.4k
  if (CG(active_op_array)->fn_flags & ZEND_ACC_CLOSURE) {
1704
    /* Closures can be rebound to a different scope */
1705
4.05k
    return 0;
1706
4.05k
  }
1707
1708
11.3k
  if (!CG(active_class_entry)) {
1709
    /* The scope is known if we're in a free function (no scope), but not if we're in
1710
     * a file/eval (which inherits including/eval'ing scope). */
1711
1.85k
    return CG(active_op_array)->function_name != NULL;
1712
1.85k
  }
1713
1714
  /* For traits self etc refers to the using class, not the trait itself */
1715
9.53k
  return (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == 0;
1716
11.3k
}
1717
/* }}} */
1718
1719
static inline bool class_name_refers_to_active_ce(zend_string *class_name, uint32_t fetch_type) /* {{{ */
1720
29.6k
{
1721
29.6k
  if (!CG(active_class_entry)) {
1722
25.7k
    return 0;
1723
25.7k
  }
1724
3.88k
  if (fetch_type == ZEND_FETCH_CLASS_SELF && zend_is_scope_known()) {
1725
1.10k
    return 1;
1726
1.10k
  }
1727
2.77k
  return fetch_type == ZEND_FETCH_CLASS_DEFAULT
1728
1.88k
    && zend_string_equals_ci(class_name, CG(active_class_entry)->name);
1729
3.88k
}
1730
/* }}} */
1731
1732
uint32_t zend_get_class_fetch_type(const zend_string *name) /* {{{ */
1733
2.50M
{
1734
2.50M
  if (zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_SELF))) {
1735
9.05k
    return ZEND_FETCH_CLASS_SELF;
1736
2.49M
  } else if (zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_PARENT))) {
1737
7.74k
    return ZEND_FETCH_CLASS_PARENT;
1738
2.48M
  } else if (zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_STATIC))) {
1739
2.28k
    return ZEND_FETCH_CLASS_STATIC;
1740
2.48M
  } else {
1741
2.48M
    return ZEND_FETCH_CLASS_DEFAULT;
1742
2.48M
  }
1743
2.50M
}
1744
/* }}} */
1745
1746
static uint32_t zend_get_class_fetch_type_ast(zend_ast *name_ast) /* {{{ */
1747
282k
{
1748
  /* Fully qualified names are always default refs */
1749
282k
  if (name_ast->attr == ZEND_NAME_FQ) {
1750
3.47k
    return ZEND_FETCH_CLASS_DEFAULT;
1751
3.47k
  }
1752
1753
279k
  return zend_get_class_fetch_type(zend_ast_get_str(name_ast));
1754
282k
}
1755
/* }}} */
1756
1757
static zend_string *zend_resolve_const_class_name_reference(zend_ast *ast, const char *type)
1758
53.0k
{
1759
53.0k
  zend_string *class_name = zend_ast_get_str(ast);
1760
53.0k
  if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type_ast(ast)) {
1761
22
    zend_error_noreturn(E_COMPILE_ERROR,
1762
22
      "Cannot use \"%s\" as %s, as it is reserved",
1763
22
      ZSTR_VAL(class_name), type);
1764
22
  }
1765
52.9k
  return zend_resolve_class_name(class_name, ast->attr);
1766
53.0k
}
1767
1768
static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
1769
13.0k
{
1770
13.0k
  if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && zend_is_scope_known()) {
1771
3.84k
    zend_class_entry *ce = CG(active_class_entry);
1772
3.84k
    if (!ce) {
1773
35
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"%s\" when no class scope is active",
1774
35
        fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
1775
35
        fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
1776
3.81k
    } else if (fetch_type == ZEND_FETCH_CLASS_PARENT && !ce->parent_name) {
1777
22
      zend_error_noreturn(E_COMPILE_ERROR,
1778
22
        "Cannot use \"parent\" when current class scope has no parent");
1779
22
    }
1780
3.84k
  }
1781
13.0k
}
1782
/* }}} */
1783
1784
static bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast) /* {{{ */
1785
8.60k
{
1786
8.60k
  uint32_t fetch_type;
1787
8.60k
  zval *class_name;
1788
1789
8.60k
  if (class_ast->kind != ZEND_AST_ZVAL) {
1790
2.10k
    return 0;
1791
2.10k
  }
1792
1793
6.49k
  class_name = zend_ast_get_zval(class_ast);
1794
1795
6.49k
  if (Z_TYPE_P(class_name) != IS_STRING) {
1796
7
    zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
1797
7
  }
1798
1799
6.48k
  fetch_type = zend_get_class_fetch_type(Z_STR_P(class_name));
1800
6.48k
  zend_ensure_valid_class_fetch_type(fetch_type);
1801
1802
6.48k
  switch (fetch_type) {
1803
984
    case ZEND_FETCH_CLASS_SELF:
1804
984
      if (CG(active_class_entry) && zend_is_scope_known()) {
1805
272
        ZVAL_STR_COPY(zv, CG(active_class_entry)->name);
1806
272
        return 1;
1807
272
      }
1808
712
      return 0;
1809
1.17k
    case ZEND_FETCH_CLASS_PARENT:
1810
1.17k
      if (CG(active_class_entry) && CG(active_class_entry)->parent_name
1811
61
          && zend_is_scope_known()) {
1812
61
        ZVAL_STR_COPY(zv, CG(active_class_entry)->parent_name);
1813
61
        return 1;
1814
61
      }
1815
1.11k
      return 0;
1816
647
    case ZEND_FETCH_CLASS_STATIC:
1817
647
      return 0;
1818
3.66k
    case ZEND_FETCH_CLASS_DEFAULT:
1819
3.66k
      ZVAL_STR(zv, zend_resolve_class_name_ast(class_ast));
1820
3.66k
      return 1;
1821
6.48k
    EMPTY_SWITCH_DEFAULT_CASE()
1822
6.48k
  }
1823
6.48k
}
1824
/* }}} */
1825
1826
/* We don't use zend_verify_const_access because we need to deal with unlinked classes. */
1827
static bool zend_verify_ct_const_access(zend_class_constant *c, zend_class_entry *scope)
1828
620
{
1829
620
  if (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED) {
1830
17
    return 0;
1831
603
  } else if (c->ce->ce_flags & ZEND_ACC_TRAIT) {
1832
    /* This condition is only met on directly accessing trait constants,
1833
     * because the ce is replaced to the class entry of the composing class
1834
     * on binding. */
1835
1
    return 0;
1836
602
  } else if (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_PUBLIC) {
1837
412
    return 1;
1838
412
  } else if (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_PRIVATE) {
1839
189
    return c->ce == scope;
1840
189
  } else {
1841
1
    zend_class_entry *ce = c->ce;
1842
1
    while (1) {
1843
1
      if (ce == scope) {
1844
0
        return 1;
1845
0
      }
1846
1
      if (!ce->parent) {
1847
1
        break;
1848
1
      }
1849
0
      if (ce->ce_flags & ZEND_ACC_RESOLVED_PARENT) {
1850
0
        ce = ce->parent;
1851
0
      } else {
1852
0
        ce = zend_hash_find_ptr_lc(CG(class_table), ce->parent_name);
1853
0
        if (!ce) {
1854
0
          break;
1855
0
        }
1856
0
      }
1857
0
    }
1858
    /* Reverse case cannot be true during compilation */
1859
1
    return 0;
1860
1
  }
1861
620
}
1862
1863
static bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend_string *name) /* {{{ */
1864
29.6k
{
1865
29.6k
  uint32_t fetch_type = zend_get_class_fetch_type(class_name);
1866
29.6k
  zend_class_constant *cc;
1867
29.6k
  zval *c;
1868
1869
29.6k
  if (class_name_refers_to_active_ce(class_name, fetch_type)) {
1870
1.27k
    cc = zend_hash_find_ptr(&CG(active_class_entry)->constants_table, name);
1871
28.3k
  } else if (fetch_type == ZEND_FETCH_CLASS_DEFAULT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
1872
692
    zend_class_entry *ce = zend_hash_find_ptr_lc(CG(class_table), class_name);
1873
692
    if (ce) {
1874
75
      cc = zend_hash_find_ptr(&ce->constants_table, name);
1875
617
    } else {
1876
617
      return 0;
1877
617
    }
1878
27.7k
  } else {
1879
27.7k
    return 0;
1880
27.7k
  }
1881
1882
1.35k
  if (CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION) {
1883
432
    return 0;
1884
432
  }
1885
1886
919
  if (!cc || !zend_verify_ct_const_access(cc, CG(active_class_entry))) {
1887
318
    return 0;
1888
318
  }
1889
1890
601
  c = &cc->value;
1891
1892
  /* Substitute case-sensitive (or lowercase) persistent class constants */
1893
601
  if (Z_TYPE_P(c) < IS_ARRAY) {
1894
384
    ZVAL_COPY_OR_DUP(zv, c);
1895
384
    return 1;
1896
384
  } else if (Z_TYPE_P(c) == IS_ARRAY && array_is_const(Z_ARR_P(c))) {
1897
44
    ZVAL_COPY_OR_DUP(zv, c);
1898
44
    return 1;
1899
44
  }
1900
1901
173
  return 0;
1902
601
}
1903
/* }}} */
1904
1905
static void zend_add_to_list(void *result, void *item) /* {{{ */
1906
4.89k
{
1907
4.89k
  void** list = *(void**)result;
1908
4.89k
  size_t n = 0;
1909
1910
4.89k
  if (list) {
1911
106k
    while (list[n]) {
1912
102k
      n++;
1913
102k
    }
1914
3.75k
  }
1915
1916
4.89k
  list = erealloc(list, sizeof(void*) * (n+2));
1917
1918
4.89k
  list[n]   = item;
1919
4.89k
  list[n+1] = NULL;
1920
1921
4.89k
  *(void**)result = list;
1922
4.89k
}
1923
/* }}} */
1924
1925
static void zend_do_extended_stmt(znode* result) /* {{{ */
1926
797k
{
1927
797k
  zend_op *opline;
1928
1929
797k
  if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_STMT)) {
1930
797k
    return;
1931
797k
  }
1932
1933
0
  opline = get_next_op();
1934
1935
0
  opline->opcode = ZEND_EXT_STMT;
1936
0
  if (result) {
1937
0
    SET_NODE(opline->op1, result);
1938
0
  }
1939
0
}
1940
/* }}} */
1941
1942
static void zend_do_extended_fcall_begin(void) /* {{{ */
1943
1.95M
{
1944
1.95M
  zend_op *opline;
1945
1946
1.95M
  if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_FCALL)) {
1947
1.95M
    return;
1948
1.95M
  }
1949
1950
0
  opline = get_next_op();
1951
1952
0
  opline->opcode = ZEND_EXT_FCALL_BEGIN;
1953
0
}
1954
/* }}} */
1955
1956
static void zend_do_extended_fcall_end(void) /* {{{ */
1957
1.95M
{
1958
1.95M
  zend_op *opline;
1959
1960
1.95M
  if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_FCALL)) {
1961
1.95M
    return;
1962
1.95M
  }
1963
1964
0
  opline = get_next_op();
1965
1966
0
  opline->opcode = ZEND_EXT_FCALL_END;
1967
0
}
1968
/* }}} */
1969
1970
0
ZEND_API bool zend_is_auto_global_str(const char *name, size_t len) /* {{{ */ {
1971
0
  zend_auto_global *auto_global;
1972
1973
0
  if ((auto_global = zend_hash_str_find_ptr(CG(auto_globals), name, len)) != NULL) {
1974
0
    if (auto_global->armed) {
1975
0
      auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1976
0
    }
1977
0
    return 1;
1978
0
  }
1979
0
  return 0;
1980
0
}
1981
/* }}} */
1982
1983
ZEND_API bool zend_is_auto_global(zend_string *name) /* {{{ */
1984
2.21M
{
1985
2.21M
  zend_auto_global *auto_global;
1986
1987
2.21M
  if ((auto_global = zend_hash_find_ptr(CG(auto_globals), name)) != NULL) {
1988
5.49k
    if (auto_global->armed) {
1989
215
      auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1990
215
    }
1991
5.49k
    return 1;
1992
5.49k
  }
1993
2.20M
  return 0;
1994
2.21M
}
1995
/* }}} */
1996
1997
ZEND_API zend_result zend_register_auto_global(zend_string *name, bool jit, zend_auto_global_callback auto_global_callback) /* {{{ */
1998
128
{
1999
128
  zend_auto_global auto_global;
2000
128
  zend_result retval;
2001
2002
128
  auto_global.name = name;
2003
128
  auto_global.auto_global_callback = auto_global_callback;
2004
128
  auto_global.jit = jit;
2005
2006
128
  retval = zend_hash_add_mem(CG(auto_globals), auto_global.name, &auto_global, sizeof(zend_auto_global)) != NULL ? SUCCESS : FAILURE;
2007
2008
128
  return retval;
2009
128
}
2010
/* }}} */
2011
2012
ZEND_API void zend_activate_auto_globals(void) /* {{{ */
2013
278k
{
2014
278k
  zend_auto_global *auto_global;
2015
2016
5.01M
  ZEND_HASH_MAP_FOREACH_PTR(CG(auto_globals), auto_global) {
2017
5.01M
    auto_global->armed = auto_global->jit || auto_global->auto_global_callback;
2018
5.01M
  } ZEND_HASH_FOREACH_END();
2019
2020
5.01M
  ZEND_HASH_MAP_FOREACH_PTR(CG(auto_globals), auto_global) {
2021
5.01M
    if (auto_global->armed && !auto_global->jit) {
2022
1.11M
      auto_global->armed = auto_global->auto_global_callback(auto_global->name);
2023
1.11M
    }
2024
5.01M
  } ZEND_HASH_FOREACH_END();
2025
278k
}
2026
/* }}} */
2027
2028
int ZEND_FASTCALL zendlex(zend_parser_stack_elem *elem) /* {{{ */
2029
10.7M
{
2030
10.7M
  zval zv;
2031
10.7M
  int ret;
2032
2033
10.7M
  if (CG(increment_lineno)) {
2034
13.1k
    CG(zend_lineno)++;
2035
13.1k
    CG(increment_lineno) = 0;
2036
13.1k
  }
2037
2038
10.7M
  ret = lex_scan(&zv, elem);
2039
10.7M
  ZEND_ASSERT(!EG(exception) || ret == T_ERROR);
2040
10.7M
  return ret;
2041
2042
10.7M
}
2043
/* }}} */
2044
2045
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, bool nullify_handlers) /* {{{ */
2046
115k
{
2047
115k
  bool persistent_hashes = ce->type == ZEND_INTERNAL_CLASS;
2048
2049
115k
  ce->refcount = 1;
2050
115k
  ce->ce_flags = ZEND_ACC_CONSTANTS_UPDATED;
2051
2052
115k
  if (CG(compiler_options) & ZEND_COMPILE_GUARDS) {
2053
0
    ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2054
0
  }
2055
2056
115k
  ce->default_properties_table = NULL;
2057
115k
  ce->default_static_members_table = NULL;
2058
115k
  zend_hash_init(&ce->properties_info, 8, NULL, NULL, persistent_hashes);
2059
115k
  zend_hash_init(&ce->constants_table, 8, NULL, NULL, persistent_hashes);
2060
115k
  zend_hash_init(&ce->function_table, 8, NULL, ZEND_FUNCTION_DTOR, persistent_hashes);
2061
2062
115k
  ce->doc_comment = NULL;
2063
2064
115k
  ZEND_MAP_PTR_INIT(ce->static_members_table, NULL);
2065
115k
  ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
2066
2067
115k
  ce->default_object_handlers = &std_object_handlers;
2068
115k
  ce->default_properties_count = 0;
2069
115k
  ce->default_static_members_count = 0;
2070
115k
  ce->properties_info_table = NULL;
2071
115k
  ce->attributes = NULL;
2072
115k
  ce->enum_backing_type = IS_UNDEF;
2073
115k
  ce->backed_enum_table = NULL;
2074
2075
115k
  if (nullify_handlers) {
2076
113k
    ce->constructor = NULL;
2077
113k
    ce->destructor = NULL;
2078
113k
    ce->clone = NULL;
2079
113k
    ce->__get = NULL;
2080
113k
    ce->__set = NULL;
2081
113k
    ce->__unset = NULL;
2082
113k
    ce->__isset = NULL;
2083
113k
    ce->__call = NULL;
2084
113k
    ce->__callstatic = NULL;
2085
113k
    ce->__tostring = NULL;
2086
113k
    ce->__serialize = NULL;
2087
113k
    ce->__unserialize = NULL;
2088
113k
    ce->__debugInfo = NULL;
2089
113k
    ce->create_object = NULL;
2090
113k
    ce->get_iterator = NULL;
2091
113k
    ce->iterator_funcs_ptr = NULL;
2092
113k
    ce->arrayaccess_funcs_ptr = NULL;
2093
113k
    ce->get_static_method = NULL;
2094
113k
    ce->parent = NULL;
2095
113k
    ce->parent_name = NULL;
2096
113k
    ce->num_interfaces = 0;
2097
113k
    ce->interfaces = NULL;
2098
113k
    ce->num_traits = 0;
2099
113k
    ce->num_hooked_props = 0;
2100
113k
    ce->num_hooked_prop_variance_checks = 0;
2101
113k
    ce->trait_names = NULL;
2102
113k
    ce->trait_aliases = NULL;
2103
113k
    ce->trait_precedences = NULL;
2104
113k
    ce->serialize = NULL;
2105
113k
    ce->unserialize = NULL;
2106
113k
    if (ce->type == ZEND_INTERNAL_CLASS) {
2107
0
      ce->info.internal.module = NULL;
2108
0
      ce->info.internal.builtin_functions = NULL;
2109
0
    }
2110
113k
  }
2111
115k
}
2112
/* }}} */
2113
2114
ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, uint32_t var) /* {{{ */
2115
0
{
2116
0
  return op_array->vars[EX_VAR_TO_NUM(var)];
2117
0
}
2118
/* }}} */
2119
2120
zend_ast *zend_ast_append_str(zend_ast *left_ast, zend_ast *right_ast) /* {{{ */
2121
0
{
2122
0
  zval *left_zv = zend_ast_get_zval(left_ast);
2123
0
  zend_string *left = Z_STR_P(left_zv);
2124
0
  zend_string *right = zend_ast_get_str(right_ast);
2125
2126
0
  zend_string *result;
2127
0
  size_t left_len = ZSTR_LEN(left);
2128
0
  size_t len = left_len + ZSTR_LEN(right) + 1; /* left\right */
2129
2130
0
  result = zend_string_extend(left, len, 0);
2131
0
  ZSTR_VAL(result)[left_len] = '\\';
2132
0
  memcpy(&ZSTR_VAL(result)[left_len + 1], ZSTR_VAL(right), ZSTR_LEN(right));
2133
0
  ZSTR_VAL(result)[len] = '\0';
2134
0
  zend_string_release_ex(right, 0);
2135
2136
0
  ZVAL_STR(left_zv, result);
2137
0
  return left_ast;
2138
0
}
2139
/* }}} */
2140
2141
zend_ast *zend_negate_num_string(zend_ast *ast) /* {{{ */
2142
1.60k
{
2143
1.60k
  zval *zv = zend_ast_get_zval(ast);
2144
1.60k
  if (Z_TYPE_P(zv) == IS_LONG) {
2145
1.28k
    if (Z_LVAL_P(zv) == 0) {
2146
656
      ZVAL_NEW_STR(zv, ZSTR_INIT_LITERAL("-0", 0));
2147
656
    } else {
2148
630
      ZEND_ASSERT(Z_LVAL_P(zv) > 0);
2149
630
      Z_LVAL_P(zv) *= -1;
2150
630
    }
2151
1.28k
  } else if (Z_TYPE_P(zv) == IS_STRING) {
2152
315
    size_t orig_len = Z_STRLEN_P(zv);
2153
315
    Z_STR_P(zv) = zend_string_extend(Z_STR_P(zv), orig_len + 1, 0);
2154
315
    memmove(Z_STRVAL_P(zv) + 1, Z_STRVAL_P(zv), orig_len + 1);
2155
315
    Z_STRVAL_P(zv)[0] = '-';
2156
315
  } else {
2157
0
    ZEND_UNREACHABLE();
2158
0
  }
2159
1.60k
  return ast;
2160
1.60k
}
2161
/* }}} */
2162
2163
static void zend_verify_namespace(void) /* {{{ */
2164
497k
{
2165
497k
  if (FC(has_bracketed_namespaces) && !FC(in_namespace)) {
2166
46
    zend_error_noreturn(E_COMPILE_ERROR, "No code may exist outside of namespace {}");
2167
46
  }
2168
497k
}
2169
/* }}} */
2170
2171
/* {{{ zend_dirname
2172
   Returns directory name component of path */
2173
ZEND_API size_t zend_dirname(char *path, size_t len)
2174
1.82k
{
2175
1.82k
  char *end = path + len - 1;
2176
1.82k
  unsigned int len_adjust = 0;
2177
2178
#ifdef ZEND_WIN32
2179
  /* Note that on Win32 CWD is per drive (heritage from CP/M).
2180
   * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
2181
   */
2182
  if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
2183
    /* Skip over the drive spec (if any) so as not to change */
2184
    path += 2;
2185
    len_adjust += 2;
2186
    if (2 == len) {
2187
      /* Return "c:" on Win32 for dirname("c:").
2188
       * It would be more consistent to return "c:."
2189
       * but that would require making the string *longer*.
2190
       */
2191
      return len;
2192
    }
2193
  }
2194
#endif
2195
2196
1.82k
  if (len == 0) {
2197
    /* Illegal use of this function */
2198
0
    return 0;
2199
0
  }
2200
2201
  /* Strip trailing slashes */
2202
1.82k
  while (end >= path && IS_SLASH_P_EX(end, end == path)) {
2203
0
    end--;
2204
0
  }
2205
1.82k
  if (end < path) {
2206
    /* The path only contained slashes */
2207
0
    path[0] = DEFAULT_SLASH;
2208
0
    path[1] = '\0';
2209
0
    return 1 + len_adjust;
2210
0
  }
2211
2212
  /* Strip filename */
2213
20.1k
  while (end >= path && !IS_SLASH_P_EX(end, end == path)) {
2214
18.2k
    end--;
2215
18.2k
  }
2216
1.82k
  if (end < path) {
2217
    /* No slash found, therefore return '.' */
2218
1.18k
    path[0] = '.';
2219
1.18k
    path[1] = '\0';
2220
1.18k
    return 1 + len_adjust;
2221
1.18k
  }
2222
2223
  /* Strip slashes which came before the file name */
2224
1.26k
  while (end >= path && IS_SLASH_P_EX(end, end == path)) {
2225
633
    end--;
2226
633
  }
2227
633
  if (end < path) {
2228
5
    path[0] = DEFAULT_SLASH;
2229
5
    path[1] = '\0';
2230
5
    return 1 + len_adjust;
2231
5
  }
2232
628
  *(end+1) = '\0';
2233
2234
628
  return (size_t)(end + 1 - path) + len_adjust;
2235
633
}
2236
/* }}} */
2237
2238
static void zend_adjust_for_fetch_type(zend_op *opline, znode *result, uint32_t type) /* {{{ */
2239
692k
{
2240
692k
  uint_fast8_t factor = (opline->opcode == ZEND_FETCH_STATIC_PROP_R) ? 1 : 3;
2241
2242
692k
  switch (type) {
2243
472k
    case BP_VAR_R:
2244
472k
      opline->result_type = IS_TMP_VAR;
2245
472k
      result->op_type = IS_TMP_VAR;
2246
472k
      return;
2247
109k
    case BP_VAR_W:
2248
109k
      opline->opcode += 1 * factor;
2249
109k
      return;
2250
16.1k
    case BP_VAR_RW:
2251
16.1k
      opline->opcode += 2 * factor;
2252
16.1k
      return;
2253
78.1k
    case BP_VAR_IS:
2254
78.1k
      opline->result_type = IS_TMP_VAR;
2255
78.1k
      result->op_type = IS_TMP_VAR;
2256
78.1k
      opline->opcode += 3 * factor;
2257
78.1k
      return;
2258
10.2k
    case BP_VAR_FUNC_ARG:
2259
10.2k
      opline->opcode += 4 * factor;
2260
10.2k
      return;
2261
6.19k
    case BP_VAR_UNSET:
2262
6.19k
      opline->opcode += 5 * factor;
2263
6.19k
      return;
2264
692k
    EMPTY_SWITCH_DEFAULT_CASE()
2265
692k
  }
2266
692k
}
2267
/* }}} */
2268
2269
static inline void zend_make_var_result(znode *result, zend_op *opline) /* {{{ */
2270
2.85M
{
2271
2.85M
  opline->result_type = IS_VAR;
2272
2.85M
  opline->result.var = get_temporary_variable();
2273
2.85M
  GET_NODE(result, opline->result);
2274
2.85M
}
2275
/* }}} */
2276
2277
static inline void zend_make_tmp_result(znode *result, zend_op *opline) /* {{{ */
2278
15.7M
{
2279
15.7M
  opline->result_type = IS_TMP_VAR;
2280
15.7M
  opline->result.var = get_temporary_variable();
2281
15.7M
  GET_NODE(result, opline->result);
2282
15.7M
}
2283
/* }}} */
2284
2285
static zend_op *zend_emit_op(znode *result, uint8_t opcode, znode *op1, znode *op2) /* {{{ */
2286
18.2M
{
2287
18.2M
  zend_op *opline = get_next_op();
2288
18.2M
  opline->opcode = opcode;
2289
2290
18.2M
  if (op1 != NULL) {
2291
14.5M
    SET_NODE(opline->op1, op1);
2292
14.5M
  }
2293
2294
18.2M
  if (op2 != NULL) {
2295
1.09M
    SET_NODE(opline->op2, op2);
2296
1.09M
  }
2297
2298
18.2M
  if (result) {
2299
2.50M
    zend_make_var_result(result, opline);
2300
2.50M
  }
2301
18.2M
  return opline;
2302
18.2M
}
2303
/* }}} */
2304
2305
static zend_op *zend_emit_op_tmp(znode *result, uint8_t opcode, znode *op1, znode *op2) /* {{{ */
2306
16.8M
{
2307
16.8M
  zend_op *opline = get_next_op();
2308
16.8M
  opline->opcode = opcode;
2309
2310
16.8M
  if (op1 != NULL) {
2311
4.30M
    SET_NODE(opline->op1, op1);
2312
4.30M
  }
2313
2314
16.8M
  if (op2 != NULL) {
2315
1.82M
    SET_NODE(opline->op2, op2);
2316
1.82M
  }
2317
2318
16.8M
  if (result) {
2319
15.7M
    zend_make_tmp_result(result, opline);
2320
15.7M
  }
2321
2322
16.8M
  return opline;
2323
16.8M
}
2324
/* }}} */
2325
2326
static void zend_emit_tick(void) /* {{{ */
2327
11.4k
{
2328
11.4k
  zend_op *opline;
2329
2330
  /* This prevents a double TICK generated by the parser statement of "declare()" */
2331
11.4k
  if (CG(active_op_array)->last && CG(active_op_array)->opcodes[CG(active_op_array)->last - 1].opcode == ZEND_TICKS) {
2332
837
    return;
2333
837
  }
2334
2335
10.6k
  opline = get_next_op();
2336
2337
10.6k
  opline->opcode = ZEND_TICKS;
2338
10.6k
  opline->extended_value = FC(declarables).ticks;
2339
10.6k
}
2340
/* }}} */
2341
2342
static inline zend_op *zend_emit_op_data(znode *value) /* {{{ */
2343
85.1k
{
2344
85.1k
  return zend_emit_op(NULL, ZEND_OP_DATA, value, NULL);
2345
85.1k
}
2346
/* }}} */
2347
2348
static inline uint32_t zend_emit_jump(uint32_t opnum_target) /* {{{ */
2349
426k
{
2350
426k
  uint32_t opnum = get_next_op_number();
2351
426k
  zend_op *opline = zend_emit_op(NULL, ZEND_JMP, NULL, NULL);
2352
426k
  opline->op1.opline_num = opnum_target;
2353
426k
  return opnum;
2354
426k
}
2355
/* }}} */
2356
2357
ZEND_API bool zend_is_smart_branch(const zend_op *opline) /* {{{ */
2358
104k
{
2359
104k
  switch (opline->opcode) {
2360
3.26k
    case ZEND_IS_IDENTICAL:
2361
3.50k
    case ZEND_IS_NOT_IDENTICAL:
2362
45.7k
    case ZEND_IS_EQUAL:
2363
46.5k
    case ZEND_IS_NOT_EQUAL:
2364
53.9k
    case ZEND_IS_SMALLER:
2365
55.6k
    case ZEND_IS_SMALLER_OR_EQUAL:
2366
70.1k
    case ZEND_CASE:
2367
74.5k
    case ZEND_CASE_STRICT:
2368
74.9k
    case ZEND_ISSET_ISEMPTY_CV:
2369
75.0k
    case ZEND_ISSET_ISEMPTY_VAR:
2370
75.5k
    case ZEND_ISSET_ISEMPTY_DIM_OBJ:
2371
75.6k
    case ZEND_ISSET_ISEMPTY_PROP_OBJ:
2372
75.8k
    case ZEND_ISSET_ISEMPTY_STATIC_PROP:
2373
76.0k
    case ZEND_INSTANCEOF:
2374
76.5k
    case ZEND_TYPE_CHECK:
2375
76.6k
    case ZEND_DEFINED:
2376
76.6k
    case ZEND_IN_ARRAY:
2377
76.7k
    case ZEND_ARRAY_KEY_EXISTS:
2378
76.7k
      return 1;
2379
27.3k
    default:
2380
27.3k
      return 0;
2381
104k
  }
2382
104k
}
2383
/* }}} */
2384
2385
static inline uint32_t zend_emit_cond_jump(uint8_t opcode, znode *cond, uint32_t opnum_target) /* {{{ */
2386
119k
{
2387
119k
  uint32_t opnum = get_next_op_number();
2388
119k
  zend_op *opline;
2389
2390
119k
  if (cond->op_type == IS_TMP_VAR && opnum > 0) {
2391
88.4k
    opline = CG(active_op_array)->opcodes + opnum - 1;
2392
88.4k
    if (opline->result_type == IS_TMP_VAR
2393
86.6k
     && opline->result.var == cond->u.op.var
2394
86.6k
     && zend_is_smart_branch(opline)) {
2395
76.5k
      if (opcode == ZEND_JMPZ) {
2396
18.0k
        opline->result_type = IS_TMP_VAR | IS_SMART_BRANCH_JMPZ;
2397
58.5k
      } else {
2398
58.5k
        ZEND_ASSERT(opcode == ZEND_JMPNZ);
2399
58.5k
        opline->result_type = IS_TMP_VAR | IS_SMART_BRANCH_JMPNZ;
2400
58.5k
      }
2401
76.5k
    }
2402
88.4k
  }
2403
119k
  opline = zend_emit_op(NULL, opcode, cond, NULL);
2404
119k
  opline->op2.opline_num = opnum_target;
2405
119k
  return opnum;
2406
119k
}
2407
/* }}} */
2408
2409
static inline void zend_update_jump_target(uint32_t opnum_jump, uint32_t opnum_target) /* {{{ */
2410
520k
{
2411
520k
  zend_op *opline = &CG(active_op_array)->opcodes[opnum_jump];
2412
520k
  switch (opline->opcode) {
2413
396k
    case ZEND_JMP:
2414
396k
      opline->op1.opline_num = opnum_target;
2415
396k
      break;
2416
34.0k
    case ZEND_JMPZ:
2417
87.5k
    case ZEND_JMPNZ:
2418
97.3k
    case ZEND_JMPZ_EX:
2419
101k
    case ZEND_JMPNZ_EX:
2420
107k
    case ZEND_JMP_SET:
2421
124k
    case ZEND_COALESCE:
2422
124k
    case ZEND_JMP_NULL:
2423
124k
    case ZEND_BIND_INIT_STATIC_OR_JMP:
2424
124k
    case ZEND_JMP_FRAMELESS:
2425
124k
      opline->op2.opline_num = opnum_target;
2426
124k
      break;
2427
520k
    EMPTY_SWITCH_DEFAULT_CASE()
2428
520k
  }
2429
520k
}
2430
/* }}} */
2431
2432
static inline void zend_update_jump_target_to_next(uint32_t opnum_jump) /* {{{ */
2433
503k
{
2434
503k
  zend_update_jump_target(opnum_jump, get_next_op_number());
2435
503k
}
2436
/* }}} */
2437
2438
static inline zend_op *zend_delayed_emit_op(znode *result, uint8_t opcode, znode *op1, znode *op2) /* {{{ */
2439
355k
{
2440
355k
  zend_op tmp_opline;
2441
2442
355k
  init_op(&tmp_opline);
2443
2444
355k
  tmp_opline.opcode = opcode;
2445
355k
  if (op1 != NULL) {
2446
355k
    SET_NODE(tmp_opline.op1, op1);
2447
355k
  }
2448
355k
  if (op2 != NULL) {
2449
328k
    SET_NODE(tmp_opline.op2, op2);
2450
328k
  }
2451
355k
  if (result) {
2452
351k
    zend_make_var_result(result, &tmp_opline);
2453
351k
  }
2454
2455
355k
  zend_stack_push(&CG(delayed_oplines_stack), &tmp_opline);
2456
355k
  return zend_stack_top(&CG(delayed_oplines_stack));
2457
355k
}
2458
/* }}} */
2459
2460
static inline uint32_t zend_delayed_compile_begin(void) /* {{{ */
2461
571k
{
2462
571k
  return zend_stack_count(&CG(delayed_oplines_stack));
2463
571k
}
2464
/* }}} */
2465
2466
static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */
2467
570k
{
2468
570k
  zend_op *opline = NULL, *oplines = zend_stack_base(&CG(delayed_oplines_stack));
2469
570k
  uint32_t i, count = zend_stack_count(&CG(delayed_oplines_stack));
2470
2471
570k
  ZEND_ASSERT(count >= offset);
2472
924k
  for (i = offset; i < count; ++i) {
2473
354k
    if (EXPECTED(oplines[i].opcode != ZEND_NOP)) {
2474
344k
      opline = get_next_op();
2475
344k
      memcpy(opline, &oplines[i], sizeof(zend_op));
2476
344k
    } else {
2477
10.4k
      opline = CG(active_op_array)->opcodes + oplines[i].extended_value;
2478
10.4k
    }
2479
354k
  }
2480
2481
570k
  CG(delayed_oplines_stack).top = offset;
2482
570k
  return opline;
2483
570k
}
2484
/* }}} */
2485
2486
static bool zend_ast_kind_is_short_circuited(zend_ast_kind ast_kind)
2487
25.0M
{
2488
25.0M
  switch (ast_kind) {
2489
263k
    case ZEND_AST_DIM:
2490
346k
    case ZEND_AST_PROP:
2491
428k
    case ZEND_AST_NULLSAFE_PROP:
2492
451k
    case ZEND_AST_STATIC_PROP:
2493
570k
    case ZEND_AST_METHOD_CALL:
2494
576k
    case ZEND_AST_NULLSAFE_METHOD_CALL:
2495
652k
    case ZEND_AST_STATIC_CALL:
2496
652k
      return 1;
2497
24.4M
    default:
2498
24.4M
      return 0;
2499
25.0M
  }
2500
25.0M
}
2501
2502
static bool zend_ast_is_short_circuited(const zend_ast *ast)
2503
759k
{
2504
759k
  switch (ast->kind) {
2505
101k
    case ZEND_AST_DIM:
2506
136k
    case ZEND_AST_PROP:
2507
150k
    case ZEND_AST_STATIC_PROP:
2508
156k
    case ZEND_AST_METHOD_CALL:
2509
168k
    case ZEND_AST_STATIC_CALL:
2510
168k
      return zend_ast_is_short_circuited(ast->child[0]);
2511
432
    case ZEND_AST_NULLSAFE_PROP:
2512
572
    case ZEND_AST_NULLSAFE_METHOD_CALL:
2513
572
      return 1;
2514
590k
    default:
2515
590k
      return 0;
2516
759k
  }
2517
759k
}
2518
2519
static void zend_assert_not_short_circuited(const zend_ast *ast)
2520
13.6k
{
2521
13.6k
  if (zend_ast_is_short_circuited(ast)) {
2522
44
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot take reference of a nullsafe chain");
2523
44
  }
2524
13.6k
}
2525
2526
/* Mark nodes that are an inner part of a short-circuiting chain.
2527
 * We should not perform a "commit" on them, as it will be performed by the outer-most node.
2528
 * We do this to avoid passing down an argument in various compile functions. */
2529
2530
662k
#define ZEND_SHORT_CIRCUITING_INNER 0x8000
2531
2532
440k
static void zend_short_circuiting_mark_inner(zend_ast *ast) {
2533
440k
  if (zend_ast_kind_is_short_circuited(ast->kind)) {
2534
183k
    ast->attr |= ZEND_SHORT_CIRCUITING_INNER;
2535
183k
  }
2536
440k
}
2537
2538
static uint32_t zend_short_circuiting_checkpoint(void)
2539
24.7M
{
2540
24.7M
  return zend_stack_count(&CG(short_circuiting_opnums));
2541
24.7M
}
2542
2543
static void zend_short_circuiting_commit(uint32_t checkpoint, znode *result, zend_ast *ast)
2544
24.6M
{
2545
24.6M
  bool is_short_circuited = zend_ast_kind_is_short_circuited(ast->kind)
2546
24.1M
    || ast->kind == ZEND_AST_ISSET || ast->kind == ZEND_AST_EMPTY;
2547
24.6M
  if (!is_short_circuited) {
2548
24.1M
    ZEND_ASSERT(zend_stack_count(&CG(short_circuiting_opnums)) == checkpoint
2549
24.1M
      && "Short circuiting stack should be empty");
2550
24.1M
    return;
2551
24.1M
  }
2552
2553
479k
  if (ast->attr & ZEND_SHORT_CIRCUITING_INNER) {
2554
    /* Outer-most node will commit. */
2555
88.8k
    return;
2556
88.8k
  }
2557
2558
438k
  while (zend_stack_count(&CG(short_circuiting_opnums)) != checkpoint) {
2559
47.6k
    uint32_t opnum = *(uint32_t *) zend_stack_top(&CG(short_circuiting_opnums));
2560
47.6k
    zend_op *opline = &CG(active_op_array)->opcodes[opnum];
2561
47.6k
    opline->op2.opline_num = get_next_op_number();
2562
47.6k
    SET_NODE(opline->result, result);
2563
47.6k
    opline->extended_value |=
2564
47.6k
      ast->kind == ZEND_AST_ISSET ? ZEND_SHORT_CIRCUITING_CHAIN_ISSET :
2565
47.6k
      ast->kind == ZEND_AST_EMPTY ? ZEND_SHORT_CIRCUITING_CHAIN_EMPTY :
2566
47.2k
                                    ZEND_SHORT_CIRCUITING_CHAIN_EXPR;
2567
47.6k
    zend_stack_del_top(&CG(short_circuiting_opnums));
2568
47.6k
  }
2569
390k
}
2570
2571
static void zend_emit_jmp_null(znode *obj_node, uint32_t bp_type)
2572
47.6k
{
2573
47.6k
  uint32_t jmp_null_opnum = get_next_op_number();
2574
47.6k
  zend_op *opline = zend_emit_op(NULL, ZEND_JMP_NULL, obj_node, NULL);
2575
47.6k
  if (opline->op1_type == IS_CONST) {
2576
1.19k
    Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
2577
1.19k
  }
2578
47.6k
  if (bp_type == BP_VAR_IS) {
2579
7.38k
    opline->extended_value |= ZEND_JMP_NULL_BP_VAR_IS;
2580
7.38k
  }
2581
47.6k
  zend_stack_push(&CG(short_circuiting_opnums), &jmp_null_opnum);
2582
47.6k
}
2583
2584
static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */
2585
136k
{
2586
136k
  const zend_memoize_mode memoize_mode = CG(memoize_mode);
2587
136k
  if (memoize_mode == ZEND_MEMOIZE_COMPILE) {
2588
68.8k
    znode memoized_result;
2589
2590
    /* Go through normal compilation */
2591
68.8k
    CG(memoize_mode) = ZEND_MEMOIZE_NONE;
2592
68.8k
    zend_compile_expr(result, expr);
2593
68.8k
    CG(memoize_mode) = ZEND_MEMOIZE_COMPILE;
2594
2595
68.8k
    if (result->op_type == IS_VAR) {
2596
5.40k
      zend_emit_op(&memoized_result, ZEND_COPY_TMP, result, NULL);
2597
63.4k
    } else if (result->op_type == IS_TMP_VAR) {
2598
55.1k
      zend_emit_op_tmp(&memoized_result, ZEND_COPY_TMP, result, NULL);
2599
55.1k
    } else {
2600
8.32k
      if (result->op_type == IS_CONST) {
2601
7.11k
        Z_TRY_ADDREF(result->u.constant);
2602
7.11k
      }
2603
8.32k
      memoized_result = *result;
2604
8.32k
    }
2605
2606
68.8k
    zend_hash_index_update_mem(
2607
68.8k
      CG(memoized_exprs), (uintptr_t) expr, &memoized_result, sizeof(znode));
2608
68.8k
  } else if (memoize_mode == ZEND_MEMOIZE_FETCH) {
2609
67.2k
    znode *memoized_result = zend_hash_index_find_ptr(CG(memoized_exprs), (uintptr_t) expr);
2610
67.2k
    *result = *memoized_result;
2611
67.2k
    if (result->op_type == IS_CONST) {
2612
6.37k
      Z_TRY_ADDREF(result->u.constant);
2613
6.37k
    }
2614
67.2k
  } else {
2615
0
    ZEND_UNREACHABLE();
2616
0
  }
2617
136k
}
2618
/* }}} */
2619
2620
static void zend_emit_return_type_check(
2621
    znode *expr, zend_arg_info *return_info, bool implicit) /* {{{ */
2622
27.8k
{
2623
27.8k
  zend_type type = return_info->type;
2624
27.8k
  if (ZEND_TYPE_IS_SET(type)) {
2625
27.8k
    zend_op *opline;
2626
2627
    /* `return ...;` is illegal in a void function (but `return;` isn't) */
2628
27.8k
    if (ZEND_TYPE_CONTAINS_CODE(type, IS_VOID)) {
2629
5.00k
      if (expr) {
2630
21
        if (expr->op_type == IS_CONST && Z_TYPE(expr->u.constant) == IS_NULL) {
2631
7
          zend_error_noreturn(E_COMPILE_ERROR,
2632
7
            "A void %s must not return a value "
2633
7
            "(did you mean \"return;\" instead of \"return null;\"?)",
2634
7
            CG(active_class_entry) != NULL ? "method" : "function");
2635
14
        } else {
2636
14
          zend_error_noreturn(E_COMPILE_ERROR, "A void %s must not return a value",
2637
14
          CG(active_class_entry) != NULL ? "method" : "function");
2638
14
        }
2639
21
      }
2640
      /* we don't need run-time check */
2641
4.98k
      return;
2642
5.00k
    }
2643
2644
    /* `return` is illegal in a never-returning function */
2645
22.8k
    if (ZEND_TYPE_CONTAINS_CODE(type, IS_NEVER)) {
2646
      /* Implicit case handled separately using VERIFY_NEVER_TYPE opcode. */
2647
13
      ZEND_ASSERT(!implicit);
2648
13
      zend_error_noreturn(E_COMPILE_ERROR, "A never-returning %s must not return",
2649
13
        CG(active_class_entry) != NULL ? "method" : "function");
2650
0
      return;
2651
13
    }
2652
2653
22.8k
    if (!expr && !implicit) {
2654
18
      if (ZEND_TYPE_ALLOW_NULL(type)) {
2655
7
        zend_error_noreturn(E_COMPILE_ERROR,
2656
7
          "A %s with return type must return a value "
2657
7
          "(did you mean \"return null;\" instead of \"return;\"?)",
2658
7
          CG(active_class_entry) != NULL ? "method" : "function");
2659
11
      } else {
2660
11
        zend_error_noreturn(E_COMPILE_ERROR,
2661
11
          "A %s with return type must return a value",
2662
11
          CG(active_class_entry) != NULL ? "method" : "function");
2663
11
      }
2664
18
    }
2665
2666
22.8k
    if (expr && ZEND_TYPE_PURE_MASK(type) == MAY_BE_ANY) {
2667
      /* we don't need run-time check for mixed return type */
2668
561
      return;
2669
561
    }
2670
2671
22.2k
    if (expr && expr->op_type == IS_CONST && ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(expr->u.constant))) {
2672
      /* we don't need run-time check */
2673
2.11k
      return;
2674
2.11k
    }
2675
2676
20.1k
    opline = zend_emit_op(NULL, ZEND_VERIFY_RETURN_TYPE, expr, NULL);
2677
20.1k
    if (expr && expr->op_type == IS_CONST) {
2678
1.57k
      opline->result_type = expr->op_type = IS_TMP_VAR;
2679
1.57k
      opline->result.var = expr->u.op.var = get_temporary_variable();
2680
1.57k
    }
2681
20.1k
  }
2682
27.8k
}
2683
/* }}} */
2684
2685
void zend_emit_final_return(bool return_one) /* {{{ */
2686
798k
{
2687
798k
  znode zn;
2688
798k
  zend_op *ret;
2689
798k
  bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
2690
2691
798k
  if ((CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)
2692
20.9k
      && !(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR)) {
2693
20.6k
    zend_arg_info *return_info = CG(active_op_array)->arg_info - 1;
2694
2695
20.6k
    if (ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_NEVER)) {
2696
405
      zend_emit_op(NULL, ZEND_VERIFY_NEVER_TYPE, NULL, NULL);
2697
405
      return;
2698
405
    }
2699
2700
20.2k
    zend_emit_return_type_check(NULL, return_info, true);
2701
20.2k
  }
2702
2703
797k
  zn.op_type = IS_CONST;
2704
797k
  if (return_one) {
2705
85.9k
    ZVAL_LONG(&zn.u.constant, 1);
2706
711k
  } else {
2707
711k
    ZVAL_NULL(&zn.u.constant);
2708
711k
  }
2709
2710
797k
  ret = zend_emit_op(NULL, returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN, &zn, NULL);
2711
797k
  ret->extended_value = -1;
2712
797k
}
2713
/* }}} */
2714
2715
static inline bool zend_is_variable(zend_ast *ast) /* {{{ */
2716
2.48M
{
2717
2.48M
  return ast->kind == ZEND_AST_VAR
2718
2.34M
    || ast->kind == ZEND_AST_DIM
2719
2.32M
    || ast->kind == ZEND_AST_PROP
2720
2.31M
    || ast->kind == ZEND_AST_NULLSAFE_PROP
2721
2.31M
    || ast->kind == ZEND_AST_STATIC_PROP;
2722
2.48M
}
2723
/* }}} */
2724
2725
static inline bool zend_is_call(zend_ast *ast) /* {{{ */
2726
2.64M
{
2727
2.64M
  return ast->kind == ZEND_AST_CALL
2728
2.52M
    || ast->kind == ZEND_AST_METHOD_CALL
2729
2.50M
    || ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL
2730
2.50M
    || ast->kind == ZEND_AST_STATIC_CALL
2731
2.49M
    || ast->kind == ZEND_AST_PIPE;
2732
2.64M
}
2733
/* }}} */
2734
2735
static inline bool zend_is_variable_or_call(zend_ast *ast) /* {{{ */
2736
27.1k
{
2737
27.1k
  return zend_is_variable(ast) || zend_is_call(ast);
2738
27.1k
}
2739
/* }}} */
2740
2741
static inline bool zend_is_unticked_stmt(zend_ast *ast) /* {{{ */
2742
15.0k
{
2743
15.0k
  return ast->kind == ZEND_AST_STMT_LIST || ast->kind == ZEND_AST_LABEL
2744
12.0k
    || ast->kind == ZEND_AST_PROP_DECL || ast->kind == ZEND_AST_CLASS_CONST_GROUP
2745
12.0k
    || ast->kind == ZEND_AST_USE_TRAIT || ast->kind == ZEND_AST_METHOD;
2746
15.0k
}
2747
/* }}} */
2748
2749
static inline bool zend_can_write_to_variable(zend_ast *ast) /* {{{ */
2750
24.9k
{
2751
24.9k
  while (
2752
30.2k
    ast->kind == ZEND_AST_DIM
2753
27.7k
    || ast->kind == ZEND_AST_PROP
2754
24.9k
  ) {
2755
5.25k
    ast = ast->child[0];
2756
5.25k
  }
2757
2758
24.9k
  return zend_is_variable_or_call(ast) && !zend_ast_is_short_circuited(ast);
2759
24.9k
}
2760
/* }}} */
2761
2762
static inline bool zend_is_const_default_class_ref(zend_ast *name_ast) /* {{{ */
2763
44.5k
{
2764
44.5k
  if (name_ast->kind != ZEND_AST_ZVAL) {
2765
0
    return 0;
2766
0
  }
2767
2768
44.5k
  return ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type_ast(name_ast);
2769
44.5k
}
2770
/* }}} */
2771
2772
static inline void zend_handle_numeric_op(znode *node) /* {{{ */
2773
9.60k
{
2774
9.60k
  if (node->op_type == IS_CONST && Z_TYPE(node->u.constant) == IS_STRING) {
2775
5.49k
    zend_ulong index;
2776
2777
5.49k
    if (ZEND_HANDLE_NUMERIC(Z_STR(node->u.constant), index)) {
2778
782
      zval_ptr_dtor(&node->u.constant);
2779
782
      ZVAL_LONG(&node->u.constant, index);
2780
782
    }
2781
5.49k
  }
2782
9.60k
}
2783
/* }}} */
2784
2785
static inline void zend_handle_numeric_dim(zend_op *opline, znode *dim_node) /* {{{ */
2786
74.1k
{
2787
74.1k
  if (Z_TYPE(dim_node->u.constant) == IS_STRING) {
2788
17.1k
    zend_ulong index;
2789
2790
17.1k
    if (ZEND_HANDLE_NUMERIC(Z_STR(dim_node->u.constant), index)) {
2791
      /* For numeric indexes we also keep the original value to use by ArrayAccess
2792
       * See bug #63217
2793
       */
2794
4.75k
      int c = zend_add_literal(&dim_node->u.constant);
2795
4.75k
      ZEND_ASSERT(opline->op2.constant + 1 == c);
2796
4.75k
      ZVAL_LONG(CT_CONSTANT(opline->op2), index);
2797
4.75k
      Z_EXTRA_P(CT_CONSTANT(opline->op2)) = ZEND_EXTRA_VALUE;
2798
4.75k
      return;
2799
4.75k
    }
2800
17.1k
  }
2801
74.1k
}
2802
/* }}} */
2803
2804
static inline void zend_set_class_name_op1(zend_op *opline, znode *class_node) /* {{{ */
2805
61.9k
{
2806
61.9k
  if (class_node->op_type == IS_CONST) {
2807
26.9k
    opline->op1_type = IS_CONST;
2808
26.9k
    opline->op1.constant = zend_add_class_name_literal(
2809
26.9k
      Z_STR(class_node->u.constant));
2810
35.0k
  } else {
2811
35.0k
    SET_NODE(opline->op1, class_node);
2812
35.0k
  }
2813
61.9k
}
2814
/* }}} */
2815
2816
static void zend_compile_class_ref(znode *result, zend_ast *name_ast, uint32_t fetch_flags) /* {{{ */
2817
154k
{
2818
154k
  uint32_t fetch_type;
2819
2820
154k
  if (name_ast->kind != ZEND_AST_ZVAL) {
2821
41.1k
    znode name_node;
2822
2823
41.1k
    zend_compile_expr(&name_node, name_ast);
2824
2825
41.1k
    if (name_node.op_type == IS_CONST) {
2826
3.44k
      zend_string *name;
2827
2828
3.44k
      if (Z_TYPE(name_node.u.constant) != IS_STRING) {
2829
11
        zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
2830
11
      }
2831
2832
3.43k
      name = Z_STR(name_node.u.constant);
2833
3.43k
      fetch_type = zend_get_class_fetch_type(name);
2834
2835
3.43k
      if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
2836
2.40k
        result->op_type = IS_CONST;
2837
2.40k
        ZVAL_STR(&result->u.constant, zend_resolve_class_name(name, ZEND_NAME_FQ));
2838
2.40k
      } else {
2839
1.02k
        zend_ensure_valid_class_fetch_type(fetch_type);
2840
1.02k
        result->op_type = IS_UNUSED;
2841
1.02k
        result->u.op.num = fetch_type | fetch_flags;
2842
1.02k
      }
2843
2844
3.43k
      zend_string_release_ex(name, 0);
2845
37.7k
    } else {
2846
37.7k
      zend_op *opline = zend_emit_op(result, ZEND_FETCH_CLASS, NULL, &name_node);
2847
37.7k
      opline->op1.num = ZEND_FETCH_CLASS_DEFAULT | fetch_flags;
2848
37.7k
    }
2849
41.1k
    return;
2850
41.1k
  }
2851
2852
  /* Fully qualified names are always default refs */
2853
113k
  if (name_ast->attr == ZEND_NAME_FQ) {
2854
3.32k
    result->op_type = IS_CONST;
2855
3.32k
    ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast));
2856
3.32k
    return;
2857
3.32k
  }
2858
2859
109k
  fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
2860
109k
  if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
2861
105k
    result->op_type = IS_CONST;
2862
105k
    ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast));
2863
105k
  } else {
2864
4.65k
    zend_ensure_valid_class_fetch_type(fetch_type);
2865
4.65k
    result->op_type = IS_UNUSED;
2866
4.65k
    result->u.op.num = fetch_type | fetch_flags;
2867
4.65k
  }
2868
109k
}
2869
/* }}} */
2870
2871
static zend_result zend_try_compile_cv(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2872
1.08M
{
2873
1.08M
  zend_ast *name_ast = ast->child[0];
2874
1.08M
  if (name_ast->kind == ZEND_AST_ZVAL) {
2875
992k
    zval *zv = zend_ast_get_zval(name_ast);
2876
992k
    zend_string *name;
2877
2878
992k
    if (EXPECTED(Z_TYPE_P(zv) == IS_STRING)) {
2879
986k
      name = zval_make_interned_string(zv);
2880
986k
    } else {
2881
5.71k
      name = zend_new_interned_string(zval_get_string_func(zv));
2882
5.71k
    }
2883
2884
992k
    if (zend_is_auto_global(name)) {
2885
895
      return FAILURE;
2886
895
    }
2887
2888
991k
    if (!CG(context).has_assigned_to_http_response_header && zend_string_equals_literal(name, "http_response_header")) {
2889
72
      if (type == BP_VAR_R) {
2890
71
        zend_error(E_DEPRECATED,
2891
71
          "The predefined locally scoped $http_response_header variable is deprecated,"
2892
71
          " call http_get_last_response_headers() instead");
2893
71
      } else if (type == BP_VAR_W) {
2894
0
        CG(context).has_assigned_to_http_response_header = true;
2895
0
      }
2896
72
    }
2897
2898
991k
    result->op_type = IS_CV;
2899
991k
    result->u.op.var = lookup_cv(name);
2900
2901
991k
    if (UNEXPECTED(Z_TYPE_P(zv) != IS_STRING)) {
2902
5.71k
      zend_string_release_ex(name, 0);
2903
5.71k
    }
2904
2905
991k
    return SUCCESS;
2906
992k
  }
2907
2908
95.5k
  return FAILURE;
2909
1.08M
}
2910
/* }}} */
2911
2912
static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint32_t type, bool delayed) /* {{{ */
2913
337k
{
2914
337k
  zend_ast *name_ast = ast->child[0];
2915
337k
  znode name_node;
2916
337k
  zend_op *opline;
2917
2918
337k
  zend_compile_expr(&name_node, name_ast);
2919
337k
  if (name_node.op_type == IS_CONST) {
2920
245k
    convert_to_string(&name_node.u.constant);
2921
245k
  }
2922
2923
337k
  if (delayed) {
2924
12.7k
    opline = zend_delayed_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
2925
324k
  } else {
2926
324k
    opline = zend_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
2927
324k
  }
2928
2929
337k
  if (name_node.op_type == IS_CONST &&
2930
245k
      zend_is_auto_global(Z_STR(name_node.u.constant))) {
2931
2932
871
    opline->extended_value = ZEND_FETCH_GLOBAL;
2933
336k
  } else {
2934
    // TODO: Have a test case for this?
2935
336k
    if (name_node.op_type == IS_CONST
2936
244k
      && type == BP_VAR_R
2937
243k
      && zend_string_equals_literal(Z_STR(name_node.u.constant), "http_response_header")) {
2938
0
      zend_error(E_DEPRECATED,
2939
0
        "The predefined locally scoped $http_response_header variable is deprecated,"
2940
0
        " call http_get_last_response_headers() instead");
2941
0
    }
2942
336k
    opline->extended_value = ZEND_FETCH_LOCAL;
2943
336k
  }
2944
2945
337k
  zend_adjust_for_fetch_type(opline, result, type);
2946
337k
  return opline;
2947
337k
}
2948
/* }}} */
2949
2950
static bool is_this_fetch(zend_ast *ast) /* {{{ */
2951
1.54M
{
2952
1.54M
  if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) {
2953
1.31M
    zval *name = zend_ast_get_zval(ast->child[0]);
2954
1.31M
    return Z_TYPE_P(name) == IS_STRING && zend_string_equals(Z_STR_P(name), ZSTR_KNOWN(ZEND_STR_THIS));
2955
1.31M
  }
2956
2957
227k
  return 0;
2958
1.54M
}
2959
/* }}} */
2960
2961
static bool is_globals_fetch(const zend_ast *ast)
2962
4.07M
{
2963
4.07M
  if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) {
2964
1.40M
    zval *name = zend_ast_get_zval(ast->child[0]);
2965
1.40M
    return Z_TYPE_P(name) == IS_STRING && zend_string_equals_literal(Z_STR_P(name), "GLOBALS");
2966
1.40M
  }
2967
2968
2.66M
  return 0;
2969
4.07M
}
2970
2971
static bool is_global_var_fetch(zend_ast *ast)
2972
426k
{
2973
426k
  return ast->kind == ZEND_AST_DIM && is_globals_fetch(ast->child[0]);
2974
426k
}
2975
2976
static bool this_guaranteed_exists(void) /* {{{ */
2977
12.2k
{
2978
12.2k
  zend_oparray_context *ctx = &CG(context);
2979
15.6k
  while (ctx) {
2980
    /* Instance methods always have a $this.
2981
     * This also includes closures that have a scope and use $this. */
2982
15.6k
    zend_op_array *op_array = ctx->op_array;
2983
15.6k
    if (op_array->fn_flags & ZEND_ACC_STATIC) {
2984
82
      return false;
2985
15.5k
    } else if (op_array->scope) {
2986
10.4k
      return true;
2987
10.4k
    } else if (!(op_array->fn_flags & ZEND_ACC_CLOSURE)) {
2988
1.72k
      return false;
2989
1.72k
    }
2990
3.45k
    ctx = ctx->prev;
2991
3.45k
  }
2992
0
  return false;
2993
12.2k
}
2994
/* }}} */
2995
2996
static zend_op *zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type, bool delayed) /* {{{ */
2997
975k
{
2998
975k
  if (is_this_fetch(ast)) {
2999
3.53k
    zend_op *opline = zend_emit_op(result, ZEND_FETCH_THIS, NULL, NULL);
3000
3.53k
    if ((type == BP_VAR_R) || (type == BP_VAR_IS)) {
3001
3.36k
      opline->result_type = IS_TMP_VAR;
3002
3.36k
      result->op_type = IS_TMP_VAR;
3003
3.36k
    }
3004
3.53k
    CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
3005
3.53k
    return opline;
3006
971k
  } else if (is_globals_fetch(ast)) {
3007
2.44k
    zend_op *opline = zend_emit_op(result, ZEND_FETCH_GLOBALS, NULL, NULL);
3008
2.44k
    if (type == BP_VAR_R || type == BP_VAR_IS) {
3009
2.36k
      opline->result_type = IS_TMP_VAR;
3010
2.36k
      result->op_type = IS_TMP_VAR;
3011
2.36k
    }
3012
2.44k
    return opline;
3013
969k
  } else if (zend_try_compile_cv(result, ast, type) == FAILURE) {
3014
94.1k
    return zend_compile_simple_var_no_cv(result, ast, type, delayed);
3015
94.1k
  }
3016
875k
  return NULL;
3017
975k
}
3018
/* }}} */
3019
3020
static void zend_separate_if_call_and_write(znode *node, zend_ast *ast, uint32_t type) /* {{{ */
3021
320k
{
3022
320k
  if (type != BP_VAR_R
3023
182k
   && type != BP_VAR_IS
3024
   /* Whether a FUNC_ARG is R may only be determined at runtime. */
3025
112k
   && type != BP_VAR_FUNC_ARG
3026
105k
   && zend_is_call(ast)) {
3027
7.75k
    if (node->op_type == IS_VAR) {
3028
7.73k
      zend_op *opline = zend_emit_op(NULL, ZEND_SEPARATE, node, NULL);
3029
7.73k
      opline->result_type = IS_VAR;
3030
7.73k
      opline->result.var = opline->op1.var;
3031
7.73k
    } else {
3032
16
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context");
3033
16
    }
3034
7.75k
  }
3035
320k
}
3036
/* }}} */
3037
3038
static inline void zend_emit_assign_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
3039
8.19k
{
3040
8.19k
  znode dummy_node;
3041
8.19k
  zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN, var_ast,
3042
8.19k
    zend_ast_create_znode(value_node));
3043
8.19k
  zend_compile_expr(&dummy_node, assign_ast);
3044
8.19k
  zend_do_free(&dummy_node);
3045
8.19k
}
3046
/* }}} */
3047
3048
static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t type, bool by_ref)
3049
214k
{
3050
214k
  zend_ast *var_ast = ast->child[0];
3051
214k
  zend_ast *dim_ast = ast->child[1];
3052
214k
  zend_op *opline;
3053
3054
214k
  znode var_node, dim_node;
3055
3056
214k
  if (is_globals_fetch(var_ast)) {
3057
4.93k
    if (dim_ast == NULL) {
3058
9
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot append to $GLOBALS");
3059
9
    }
3060
3061
4.92k
    zend_compile_expr(&dim_node, dim_ast);
3062
4.92k
    if (dim_node.op_type == IS_CONST) {
3063
4.75k
      convert_to_string(&dim_node.u.constant);
3064
4.75k
    }
3065
3066
4.92k
    opline = zend_delayed_emit_op(result, ZEND_FETCH_R, &dim_node, NULL);
3067
4.92k
    opline->extended_value = ZEND_FETCH_GLOBAL;
3068
4.92k
    zend_adjust_for_fetch_type(opline, result, type);
3069
4.92k
    return opline;
3070
210k
  } else {
3071
210k
    zend_short_circuiting_mark_inner(var_ast);
3072
210k
    opline = zend_delayed_compile_var(&var_node, var_ast, type, false);
3073
210k
    if (opline) {
3074
102k
      if (type == BP_VAR_W && (opline->opcode == ZEND_FETCH_STATIC_PROP_W || opline->opcode == ZEND_FETCH_OBJ_W)) {
3075
2.65k
        opline->extended_value |= ZEND_FETCH_DIM_WRITE;
3076
99.9k
      } else if (opline->opcode == ZEND_FETCH_DIM_W
3077
58.1k
          || opline->opcode == ZEND_FETCH_DIM_RW
3078
56.4k
          || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG
3079
56.1k
          || opline->opcode == ZEND_FETCH_DIM_UNSET) {
3080
44.0k
        opline->extended_value = ZEND_FETCH_DIM_DIM;
3081
44.0k
      }
3082
102k
    }
3083
210k
  }
3084
3085
210k
  zend_separate_if_call_and_write(&var_node, var_ast, type);
3086
3087
210k
  if (dim_ast == NULL) {
3088
14.2k
    if (type == BP_VAR_R || type == BP_VAR_IS) {
3089
314
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
3090
314
    }
3091
13.9k
    if (type == BP_VAR_UNSET) {
3092
10
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting");
3093
10
    }
3094
13.9k
    dim_node.op_type = IS_UNUSED;
3095
195k
  } else {
3096
195k
    zend_compile_expr(&dim_node, dim_ast);
3097
195k
  }
3098
3099
209k
  opline = zend_delayed_emit_op(result, ZEND_FETCH_DIM_R, &var_node, &dim_node);
3100
209k
  zend_adjust_for_fetch_type(opline, result, type);
3101
209k
  if (by_ref) {
3102
6.65k
    opline->extended_value = ZEND_FETCH_DIM_REF;
3103
6.65k
  }
3104
3105
209k
  if (dim_node.op_type == IS_CONST) {
3106
63.6k
    zend_handle_numeric_dim(opline, &dim_node);
3107
63.6k
  }
3108
209k
  return opline;
3109
210k
}
3110
3111
static zend_op *zend_compile_dim(znode *result, zend_ast *ast, uint32_t type, bool by_ref) /* {{{ */
3112
102k
{
3113
102k
  uint32_t offset = zend_delayed_compile_begin();
3114
102k
  zend_delayed_compile_dim(result, ast, type, by_ref);
3115
102k
  return zend_delayed_compile_end(offset);
3116
102k
}
3117
/* }}} */
3118
3119
static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
3120
119k
{
3121
119k
  zend_ast *obj_ast = ast->child[0];
3122
119k
  zend_ast *prop_ast = ast->child[1];
3123
3124
119k
  znode obj_node, prop_node;
3125
119k
  zend_op *opline;
3126
119k
  bool nullsafe = ast->kind == ZEND_AST_NULLSAFE_PROP;
3127
3128
119k
  if (is_this_fetch(obj_ast)) {
3129
10.2k
    if (this_guaranteed_exists()) {
3130
8.66k
      obj_node.op_type = IS_UNUSED;
3131
8.66k
    } else {
3132
1.63k
      zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL);
3133
1.63k
    }
3134
10.2k
    CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
3135
3136
    /* We will throw if $this doesn't exist, so there's no need to emit a JMP_NULL
3137
     * check for a nullsafe access. */
3138
109k
  } else {
3139
109k
    zend_short_circuiting_mark_inner(obj_ast);
3140
109k
    opline = zend_delayed_compile_var(&obj_node, obj_ast, type, false);
3141
109k
    if (opline && (opline->opcode == ZEND_FETCH_DIM_W
3142
31.6k
        || opline->opcode == ZEND_FETCH_DIM_RW
3143
31.1k
        || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG
3144
30.9k
        || opline->opcode == ZEND_FETCH_DIM_UNSET)) {
3145
3.24k
      opline->extended_value = ZEND_FETCH_DIM_OBJ;
3146
3.24k
    }
3147
3148
109k
    zend_separate_if_call_and_write(&obj_node, obj_ast, type);
3149
109k
    if (nullsafe) {
3150
45.1k
      if (obj_node.op_type == IS_TMP_VAR) {
3151
        /* Flush delayed oplines */
3152
12.1k
        zend_op *opline = NULL, *oplines = zend_stack_base(&CG(delayed_oplines_stack));
3153
12.1k
        uint32_t var = obj_node.u.op.var;
3154
12.1k
        uint32_t count = zend_stack_count(&CG(delayed_oplines_stack));
3155
12.1k
        uint32_t i = count;
3156
3157
191k
        while (i > 0 && oplines[i-1].result_type == IS_TMP_VAR && oplines[i-1].result.var == var) {
3158
181k
          i--;
3159
181k
          if (oplines[i].op1_type == IS_TMP_VAR) {
3160
179k
            var = oplines[i].op1.var;
3161
179k
          } else {
3162
1.66k
            break;
3163
1.66k
          }
3164
181k
        }
3165
193k
        for (; i < count; ++i) {
3166
181k
          if (oplines[i].opcode != ZEND_NOP) {
3167
10.4k
            opline = get_next_op();
3168
10.4k
            memcpy(opline, &oplines[i], sizeof(zend_op));
3169
10.4k
            oplines[i].opcode = ZEND_NOP;
3170
10.4k
            oplines[i].extended_value = opline - CG(active_op_array)->opcodes;
3171
10.4k
          }
3172
181k
        }
3173
12.1k
      }
3174
45.1k
      zend_emit_jmp_null(&obj_node, type);
3175
45.1k
    }
3176
109k
  }
3177
3178
119k
  zend_compile_expr(&prop_node, prop_ast);
3179
3180
119k
  opline = zend_delayed_emit_op(result, ZEND_FETCH_OBJ_R, &obj_node, &prop_node);
3181
119k
  if (opline->op2_type == IS_CONST) {
3182
115k
    convert_to_string(CT_CONSTANT(opline->op2));
3183
115k
    zend_string_hash_val(Z_STR_P(CT_CONSTANT(opline->op2)));
3184
115k
    opline->extended_value = zend_alloc_cache_slots(3);
3185
115k
  }
3186
3187
119k
  zend_adjust_for_fetch_type(opline, result, type);
3188
3189
119k
  return opline;
3190
119k
}
3191
/* }}} */
3192
3193
static zend_op *zend_compile_prop(znode *result, zend_ast *ast, uint32_t type, bool by_ref) /* {{{ */
3194
73.5k
{
3195
73.5k
  uint32_t offset = zend_delayed_compile_begin();
3196
73.5k
  zend_op *opline = zend_delayed_compile_prop(result, ast, type);
3197
73.5k
  if (by_ref) { /* shared with cache_slot */
3198
3.59k
    opline->extended_value |= ZEND_FETCH_REF;
3199
3.59k
  }
3200
73.5k
  return zend_delayed_compile_end(offset);
3201
73.5k
}
3202
/* }}} */
3203
3204
static zend_op *zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, bool by_ref, bool delayed) /* {{{ */
3205
21.5k
{
3206
21.5k
  zend_ast *class_ast = ast->child[0];
3207
21.5k
  zend_ast *prop_ast = ast->child[1];
3208
3209
21.5k
  znode class_node, prop_node;
3210
21.5k
  zend_op *opline;
3211
3212
21.5k
  zend_short_circuiting_mark_inner(class_ast);
3213
21.5k
  zend_compile_class_ref(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
3214
3215
21.5k
  zend_compile_expr(&prop_node, prop_ast);
3216
3217
21.5k
  if (delayed) {
3218
8.83k
    opline = zend_delayed_emit_op(result, ZEND_FETCH_STATIC_PROP_R, &prop_node, NULL);
3219
12.7k
  } else {
3220
12.7k
    opline = zend_emit_op(result, ZEND_FETCH_STATIC_PROP_R, &prop_node, NULL);
3221
12.7k
  }
3222
21.5k
  if (opline->op1_type == IS_CONST) {
3223
19.4k
    convert_to_string(CT_CONSTANT(opline->op1));
3224
19.4k
    opline->extended_value = zend_alloc_cache_slots(3);
3225
19.4k
  }
3226
21.5k
  if (class_node.op_type == IS_CONST) {
3227
14.8k
    opline->op2_type = IS_CONST;
3228
14.8k
    opline->op2.constant = zend_add_class_name_literal(
3229
14.8k
      Z_STR(class_node.u.constant));
3230
14.8k
    if (opline->op1_type != IS_CONST) {
3231
1.40k
      opline->extended_value = zend_alloc_cache_slot();
3232
1.40k
    }
3233
14.8k
  } else {
3234
6.73k
    SET_NODE(opline->op2, &class_node);
3235
6.73k
  }
3236
3237
21.5k
  if (by_ref && (type == BP_VAR_W || type == BP_VAR_FUNC_ARG)) { /* shared with cache_slot */
3238
2.87k
    opline->extended_value |= ZEND_FETCH_REF;
3239
2.87k
  }
3240
3241
21.5k
  zend_adjust_for_fetch_type(opline, result, type);
3242
21.5k
  return opline;
3243
21.5k
}
3244
/* }}} */
3245
3246
10.8k
static void zend_verify_list_assign_target(zend_ast *var_ast, zend_ast_attr array_style) /* {{{ */ {
3247
10.8k
  if (var_ast->kind == ZEND_AST_ARRAY) {
3248
1.29k
    if (var_ast->attr == ZEND_ARRAY_SYNTAX_LONG) {
3249
7
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot assign to array(), use [] instead");
3250
7
    }
3251
1.28k
    if (array_style != var_ast->attr) {
3252
8
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix [] and list()");
3253
8
    }
3254
9.55k
  } else if (!zend_can_write_to_variable(var_ast)) {
3255
118
    zend_error_noreturn(E_COMPILE_ERROR, "Assignments can only happen to writable values");
3256
118
  }
3257
10.8k
}
3258
/* }}} */
3259
3260
static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node);
3261
3262
/* Propagate refs used on leaf elements to the surrounding list() structures. */
3263
6.79k
static bool zend_propagate_list_refs(zend_ast *ast) { /* {{{ */
3264
6.79k
  zend_ast_list *list = zend_ast_get_list(ast);
3265
6.79k
  bool has_refs = false;
3266
6.79k
  uint32_t i;
3267
3268
29.6k
  for (i = 0; i < list->children; ++i) {
3269
22.8k
    zend_ast *elem_ast = list->child[i];
3270
3271
22.8k
    if (elem_ast) {
3272
11.6k
      zend_ast *var_ast = elem_ast->child[0];
3273
11.6k
      if (var_ast->kind == ZEND_AST_ARRAY) {
3274
1.32k
        elem_ast->attr = zend_propagate_list_refs(var_ast);
3275
1.32k
      }
3276
11.6k
      has_refs |= elem_ast->attr;
3277
11.6k
    }
3278
22.8k
  }
3279
3280
6.79k
  return has_refs;
3281
6.79k
}
3282
/* }}} */
3283
3284
static bool list_is_keyed(zend_ast_list *list)
3285
6.35k
{
3286
7.15k
  for (uint32_t i = 0; i < list->children; i++) {
3287
7.11k
    zend_ast *child = list->child[i];
3288
7.11k
    if (child) {
3289
6.32k
      return child->kind == ZEND_AST_ARRAY_ELEM && child->child[1] != NULL;
3290
6.32k
    }
3291
7.11k
  }
3292
36
  return false;
3293
6.35k
}
3294
3295
static void zend_compile_list_assign(
3296
    znode *result, zend_ast *ast, znode *expr_node, zend_ast_attr array_style) /* {{{ */
3297
6.35k
{
3298
6.35k
  zend_ast_list *list = zend_ast_get_list(ast);
3299
6.35k
  uint32_t i;
3300
6.35k
  bool has_elems = false;
3301
6.35k
  bool is_keyed = list_is_keyed(list);
3302
3303
6.35k
  if (list->children && expr_node->op_type == IS_CONST && Z_TYPE(expr_node->u.constant) == IS_STRING) {
3304
404
    zval_make_interned_string(&expr_node->u.constant);
3305
404
  }
3306
3307
18.1k
  for (i = 0; i < list->children; ++i) {
3308
11.7k
    zend_ast *elem_ast = list->child[i];
3309
11.7k
    zend_ast *var_ast, *key_ast;
3310
11.7k
    znode fetch_result, dim_node;
3311
11.7k
    zend_op *opline;
3312
3313
11.7k
    if (elem_ast == NULL) {
3314
871
      if (is_keyed) {
3315
16
        zend_error(E_COMPILE_ERROR,
3316
16
          "Cannot use empty array entries in keyed array assignment");
3317
855
      } else {
3318
855
        continue;
3319
855
      }
3320
871
    }
3321
3322
10.9k
    if (elem_ast->kind == ZEND_AST_UNPACK) {
3323
19
      zend_error(E_COMPILE_ERROR,
3324
19
          "Spread operator is not supported in assignments");
3325
19
    }
3326
3327
10.9k
    var_ast = elem_ast->child[0];
3328
10.9k
    key_ast = elem_ast->child[1];
3329
10.9k
    has_elems = true;
3330
3331
10.9k
    if (is_keyed) {
3332
3.02k
      if (key_ast == NULL) {
3333
7
        zend_error(E_COMPILE_ERROR,
3334
7
          "Cannot mix keyed and unkeyed array entries in assignments");
3335
7
      }
3336
3337
3.02k
      zend_compile_expr(&dim_node, key_ast);
3338
7.87k
    } else {
3339
7.87k
      if (key_ast != NULL) {
3340
7
        zend_error(E_COMPILE_ERROR,
3341
7
          "Cannot mix keyed and unkeyed array entries in assignments");
3342
7
      }
3343
3344
7.87k
      dim_node.op_type = IS_CONST;
3345
7.87k
      ZVAL_LONG(&dim_node.u.constant, i);
3346
7.87k
    }
3347
3348
10.9k
    if (expr_node->op_type == IS_CONST) {
3349
1.54k
      Z_TRY_ADDREF(expr_node->u.constant);
3350
1.54k
    }
3351
3352
10.9k
    zend_verify_list_assign_target(var_ast, array_style);
3353
3354
10.9k
    opline = zend_emit_op(&fetch_result,
3355
10.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);
3356
3357
10.9k
    if (dim_node.op_type == IS_CONST) {
3358
10.4k
      zend_handle_numeric_dim(opline, &dim_node);
3359
10.4k
    }
3360
3361
10.9k
    if (elem_ast->attr) {
3362
3.96k
      zend_emit_op(&fetch_result, ZEND_MAKE_REF, &fetch_result, NULL);
3363
3.96k
    }
3364
10.9k
    if (var_ast->kind == ZEND_AST_ARRAY) {
3365
1.27k
      zend_compile_list_assign(NULL, var_ast, &fetch_result, var_ast->attr);
3366
9.62k
    } else if (elem_ast->attr) {
3367
3.25k
      zend_emit_assign_ref_znode(var_ast, &fetch_result);
3368
6.37k
    } else {
3369
6.37k
      zend_emit_assign_znode(var_ast, &fetch_result);
3370
6.37k
    }
3371
10.9k
  }
3372
3373
6.35k
  if (has_elems == 0) {
3374
36
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list");
3375
36
  }
3376
3377
6.32k
  if (result) {
3378
4.44k
    *result = *expr_node;
3379
4.44k
  } else {
3380
1.88k
    zend_do_free(expr_node);
3381
1.88k
  }
3382
6.32k
}
3383
/* }}} */
3384
3385
static void zend_ensure_writable_variable(const zend_ast *ast) /* {{{ */
3386
442k
{
3387
442k
  if (ast->kind == ZEND_AST_CALL || ast->kind == ZEND_AST_PIPE) {
3388
95
    zend_error_noreturn(E_COMPILE_ERROR, "Can't use function return value in write context");
3389
95
  }
3390
442k
  if (
3391
442k
    ast->kind == ZEND_AST_METHOD_CALL
3392
442k
    || ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL
3393
442k
    || ast->kind == ZEND_AST_STATIC_CALL
3394
442k
  ) {
3395
19
    zend_error_noreturn(E_COMPILE_ERROR, "Can't use method return value in write context");
3396
19
  }
3397
442k
  if (zend_ast_is_short_circuited(ast)) {
3398
22
    zend_error_noreturn(E_COMPILE_ERROR, "Can't use nullsafe operator in write context");
3399
22
  }
3400
441k
  if (is_globals_fetch(ast)) {
3401
32
    zend_error_noreturn(E_COMPILE_ERROR,
3402
32
      "$GLOBALS can only be modified using the $GLOBALS[$name] = $value syntax");
3403
32
  }
3404
441k
}
3405
/* }}} */
3406
3407
/* Detects $a... = $a pattern */
3408
static bool zend_is_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast) /* {{{ */
3409
31.0k
{
3410
31.0k
  if (expr_ast->kind != ZEND_AST_VAR || expr_ast->child[0]->kind != ZEND_AST_ZVAL) {
3411
25.8k
    return 0;
3412
25.8k
  }
3413
3414
12.1k
  while (zend_is_variable(var_ast) && var_ast->kind != ZEND_AST_VAR) {
3415
7.01k
    var_ast = var_ast->child[0];
3416
7.01k
  }
3417
3418
5.14k
  if (var_ast->kind != ZEND_AST_VAR || var_ast->child[0]->kind != ZEND_AST_ZVAL) {
3419
1.17k
    return 0;
3420
1.17k
  }
3421
3422
3.97k
  {
3423
3.97k
    zend_string *name1 = zval_get_string(zend_ast_get_zval(var_ast->child[0]));
3424
3.97k
    zend_string *name2 = zval_get_string(zend_ast_get_zval(expr_ast->child[0]));
3425
3.97k
    bool result = zend_string_equals(name1, name2);
3426
3.97k
    zend_string_release_ex(name1, 0);
3427
3.97k
    zend_string_release_ex(name2, 0);
3428
3.97k
    return result;
3429
5.14k
  }
3430
5.14k
}
3431
/* }}} */
3432
3433
static void zend_compile_expr_with_potential_assign_to_self(
3434
31.0k
    znode *expr_node, zend_ast *expr_ast, zend_ast *var_ast) {
3435
31.0k
  if (zend_is_assign_to_self(var_ast, expr_ast) && !is_this_fetch(expr_ast)) {
3436
    /* $a[0] = $a should evaluate the right $a first */
3437
1.11k
    znode cv_node;
3438
3439
1.11k
    if (zend_try_compile_cv(&cv_node, expr_ast, BP_VAR_R) == FAILURE) {
3440
179
      zend_compile_simple_var_no_cv(expr_node, expr_ast, BP_VAR_R, false);
3441
937
    } else {
3442
937
      zend_emit_op_tmp(expr_node, ZEND_QM_ASSIGN, &cv_node, NULL);
3443
937
    }
3444
29.8k
  } else {
3445
29.8k
    zend_compile_expr(expr_node, expr_ast);
3446
29.8k
  }
3447
31.0k
}
3448
3449
static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
3450
240k
{
3451
240k
  zend_ast *var_ast = ast->child[0];
3452
240k
  zend_ast *expr_ast = ast->child[1];
3453
3454
240k
  znode var_node, expr_node;
3455
240k
  zend_op *opline;
3456
240k
  uint32_t offset;
3457
240k
  if (is_this_fetch(var_ast)) {
3458
13
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
3459
13
  }
3460
3461
240k
  zend_ensure_writable_variable(var_ast);
3462
3463
  /* Treat $GLOBALS['x'] assignment like assignment to variable. */
3464
240k
  zend_ast_kind kind = is_global_var_fetch(var_ast) ? ZEND_AST_VAR : var_ast->kind;
3465
240k
  switch (kind) {
3466
206k
    case ZEND_AST_VAR:
3467
206k
      offset = zend_delayed_compile_begin();
3468
206k
      zend_delayed_compile_var(&var_node, var_ast, BP_VAR_W, false);
3469
206k
      zend_compile_expr(&expr_node, expr_ast);
3470
206k
      zend_delayed_compile_end(offset);
3471
206k
      CG(zend_lineno) = zend_ast_get_lineno(var_ast);
3472
206k
      zend_emit_op_tmp(result, ZEND_ASSIGN, &var_node, &expr_node);
3473
206k
      return;
3474
3.21k
    case ZEND_AST_STATIC_PROP:
3475
3.21k
      offset = zend_delayed_compile_begin();
3476
3.21k
      zend_delayed_compile_var(result, var_ast, BP_VAR_W, false);
3477
3.21k
      zend_compile_expr(&expr_node, expr_ast);
3478
3479
3.21k
      opline = zend_delayed_compile_end(offset);
3480
3.21k
      opline->opcode = ZEND_ASSIGN_STATIC_PROP;
3481
3.21k
      opline->result_type = IS_TMP_VAR;
3482
3.21k
      result->op_type = IS_TMP_VAR;
3483
3484
3.21k
      zend_emit_op_data(&expr_node);
3485
3.21k
      return;
3486
13.8k
    case ZEND_AST_DIM:
3487
13.8k
      offset = zend_delayed_compile_begin();
3488
13.8k
      zend_delayed_compile_dim(result, var_ast, BP_VAR_W, /* by_ref */ false);
3489
13.8k
      zend_compile_expr_with_potential_assign_to_self(&expr_node, expr_ast, var_ast);
3490
3491
13.8k
      opline = zend_delayed_compile_end(offset);
3492
13.8k
      opline->opcode = ZEND_ASSIGN_DIM;
3493
13.8k
      opline->result_type = IS_TMP_VAR;
3494
13.8k
      result->op_type = IS_TMP_VAR;
3495
3496
13.8k
      opline = zend_emit_op_data(&expr_node);
3497
13.8k
      return;
3498
12.2k
    case ZEND_AST_PROP:
3499
12.2k
    case ZEND_AST_NULLSAFE_PROP:
3500
12.2k
      offset = zend_delayed_compile_begin();
3501
12.2k
      zend_delayed_compile_prop(result, var_ast, BP_VAR_W);
3502
12.2k
      zend_compile_expr(&expr_node, expr_ast);
3503
3504
12.2k
      opline = zend_delayed_compile_end(offset);
3505
12.2k
      opline->opcode = ZEND_ASSIGN_OBJ;
3506
12.2k
      opline->result_type = IS_TMP_VAR;
3507
12.2k
      result->op_type = IS_TMP_VAR;
3508
3509
12.2k
      zend_emit_op_data(&expr_node);
3510
12.2k
      return;
3511
5.06k
    case ZEND_AST_ARRAY:
3512
5.06k
      if (zend_propagate_list_refs(var_ast)) {
3513
2.16k
        if (!zend_is_variable_or_call(expr_ast)) {
3514
22
          zend_error_noreturn(E_COMPILE_ERROR,
3515
22
            "Cannot assign reference to non referenceable value");
3516
2.14k
        } else {
3517
2.14k
          zend_assert_not_short_circuited(expr_ast);
3518
2.14k
        }
3519
3520
2.14k
        zend_compile_var(&expr_node, expr_ast, BP_VAR_W, true);
3521
        /* MAKE_REF is usually not necessary for CVs. However, if there are
3522
         * self-assignments, this forces the RHS to evaluate first. */
3523
2.14k
        zend_emit_op(&expr_node, ZEND_MAKE_REF, &expr_node, NULL);
3524
2.90k
      } else {
3525
2.90k
        if (expr_ast->kind == ZEND_AST_VAR) {
3526
          /* list($a, $b) = $a should evaluate the right $a first */
3527
989
          znode cv_node;
3528
3529
989
          if (zend_try_compile_cv(&cv_node, expr_ast, BP_VAR_R) == FAILURE) {
3530
360
            zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, false);
3531
629
          } else {
3532
629
            zend_emit_op_tmp(&expr_node, ZEND_QM_ASSIGN, &cv_node, NULL);
3533
629
          }
3534
1.91k
        } else {
3535
1.91k
          zend_compile_expr(&expr_node, expr_ast);
3536
1.91k
        }
3537
2.90k
      }
3538
3539
5.04k
      zend_compile_list_assign(result, var_ast, &expr_node, var_ast->attr);
3540
5.04k
      return;
3541
0
    EMPTY_SWITCH_DEFAULT_CASE();
3542
240k
  }
3543
240k
}
3544
/* }}} */
3545
3546
static void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
3547
9.18k
{
3548
9.18k
  zend_ast *target_ast = ast->child[0];
3549
9.18k
  zend_ast *source_ast = ast->child[1];
3550
3551
9.18k
  znode target_node, source_node;
3552
9.18k
  zend_op *opline;
3553
9.18k
  uint32_t offset, flags;
3554
3555
9.18k
  if (is_this_fetch(target_ast)) {
3556
7
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
3557
7
  }
3558
9.17k
  zend_ensure_writable_variable(target_ast);
3559
9.17k
  zend_assert_not_short_circuited(source_ast);
3560
9.17k
  if (is_globals_fetch(source_ast)) {
3561
10
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot acquire reference to $GLOBALS");
3562
10
  }
3563
3564
9.16k
  offset = zend_delayed_compile_begin();
3565
9.16k
  zend_delayed_compile_var(&target_node, target_ast, BP_VAR_W, true);
3566
9.16k
  zend_compile_var(&source_node, source_ast, BP_VAR_W, true);
3567
3568
9.16k
  if ((target_ast->kind != ZEND_AST_VAR
3569
6.96k
    || target_ast->child[0]->kind != ZEND_AST_ZVAL)
3570
3.02k
   && source_ast->kind != ZEND_AST_ZNODE
3571
2.21k
   && source_node.op_type != IS_CV) {
3572
    /* Both LHS and RHS expressions may modify the same data structure,
3573
     * and the modification during RHS evaluation may dangle the pointer
3574
     * to the result of the LHS evaluation.
3575
     * Use MAKE_REF instruction to replace direct pointer with REFERENCE.
3576
     * See: Bug #71539
3577
     */
3578
1.18k
    zend_emit_op(&source_node, ZEND_MAKE_REF, &source_node, NULL);
3579
1.18k
  }
3580
3581
9.16k
  opline = zend_delayed_compile_end(offset);
3582
3583
9.16k
  if (source_node.op_type != IS_VAR && zend_is_call(source_ast)) {
3584
8
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context");
3585
8
  }
3586
3587
9.15k
  flags = zend_is_call(source_ast) ? ZEND_RETURNS_FUNCTION : 0;
3588
3589
9.15k
  if (opline && opline->opcode == ZEND_FETCH_OBJ_W) {
3590
925
    opline->opcode = ZEND_ASSIGN_OBJ_REF;
3591
925
    opline->extended_value &= ~ZEND_FETCH_REF;
3592
925
    opline->extended_value |= flags;
3593
925
    zend_emit_op_data(&source_node);
3594
925
    *result = target_node;
3595
8.23k
  } else if (opline && opline->opcode == ZEND_FETCH_STATIC_PROP_W) {
3596
334
    opline->opcode = ZEND_ASSIGN_STATIC_PROP_REF;
3597
334
    opline->extended_value &= ~ZEND_FETCH_REF;
3598
334
    opline->extended_value |= flags;
3599
334
    zend_emit_op_data(&source_node);
3600
334
    *result = target_node;
3601
7.89k
  } else {
3602
7.89k
    opline = zend_emit_op(result, ZEND_ASSIGN_REF, &target_node, &source_node);
3603
7.89k
    opline->extended_value = flags;
3604
7.89k
  }
3605
9.15k
}
3606
/* }}} */
3607
3608
static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
3609
3.75k
{
3610
3.75k
  znode dummy_node;
3611
3.75k
  zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN_REF, var_ast,
3612
3.75k
    zend_ast_create_znode(value_node));
3613
3.75k
  zend_compile_expr(&dummy_node, assign_ast);
3614
3.75k
  zend_do_free(&dummy_node);
3615
3.75k
}
3616
/* }}} */
3617
3618
static void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
3619
151k
{
3620
151k
  zend_ast *var_ast = ast->child[0];
3621
151k
  zend_ast *expr_ast = ast->child[1];
3622
151k
  uint32_t opcode = ast->attr;
3623
3624
151k
  znode var_node, expr_node;
3625
151k
  zend_op *opline;
3626
151k
  uint32_t offset, cache_slot;
3627
3628
151k
  zend_ensure_writable_variable(var_ast);
3629
3630
  /* Treat $GLOBALS['x'] assignment like assignment to variable. */
3631
151k
  zend_ast_kind kind = is_global_var_fetch(var_ast) ? ZEND_AST_VAR : var_ast->kind;
3632
151k
  switch (kind) {
3633
143k
    case ZEND_AST_VAR:
3634
143k
      offset = zend_delayed_compile_begin();
3635
143k
      zend_delayed_compile_var(&var_node, var_ast, BP_VAR_RW, false);
3636
143k
      zend_compile_expr(&expr_node, expr_ast);
3637
143k
      zend_delayed_compile_end(offset);
3638
143k
      opline = zend_emit_op_tmp(result, ZEND_ASSIGN_OP, &var_node, &expr_node);
3639
143k
      opline->extended_value = opcode;
3640
143k
      return;
3641
1.93k
    case ZEND_AST_STATIC_PROP:
3642
1.93k
      offset = zend_delayed_compile_begin();
3643
1.93k
      zend_delayed_compile_var(result, var_ast, BP_VAR_RW, false);
3644
1.93k
      zend_compile_expr(&expr_node, expr_ast);
3645
3646
1.93k
      opline = zend_delayed_compile_end(offset);
3647
1.93k
      cache_slot = opline->extended_value;
3648
1.93k
      opline->opcode = ZEND_ASSIGN_STATIC_PROP_OP;
3649
1.93k
      opline->extended_value = opcode;
3650
1.93k
      opline->result_type = IS_TMP_VAR;
3651
1.93k
      result->op_type = IS_TMP_VAR;
3652
3653
1.93k
      opline = zend_emit_op_data(&expr_node);
3654
1.93k
      opline->extended_value = cache_slot;
3655
1.93k
      return;
3656
3.97k
    case ZEND_AST_DIM:
3657
3.97k
      offset = zend_delayed_compile_begin();
3658
3.97k
      zend_delayed_compile_dim(result, var_ast, BP_VAR_RW, /* by_ref */ false);
3659
3.97k
      zend_compile_expr_with_potential_assign_to_self(&expr_node, expr_ast, var_ast);
3660
3661
3.97k
      opline = zend_delayed_compile_end(offset);
3662
3.97k
      opline->opcode = ZEND_ASSIGN_DIM_OP;
3663
3.97k
      opline->extended_value = opcode;
3664
3.97k
      opline->result_type = IS_TMP_VAR;
3665
3.97k
      result->op_type = IS_TMP_VAR;
3666
3667
3.97k
      zend_emit_op_data(&expr_node);
3668
3.97k
      return;
3669
1.43k
    case ZEND_AST_PROP:
3670
1.43k
    case ZEND_AST_NULLSAFE_PROP:
3671
1.43k
      offset = zend_delayed_compile_begin();
3672
1.43k
      zend_delayed_compile_prop(result, var_ast, BP_VAR_RW);
3673
1.43k
      zend_compile_expr(&expr_node, expr_ast);
3674
3675
1.43k
      opline = zend_delayed_compile_end(offset);
3676
1.43k
      cache_slot = opline->extended_value;
3677
1.43k
      opline->opcode = ZEND_ASSIGN_OBJ_OP;
3678
1.43k
      opline->extended_value = opcode;
3679
1.43k
      opline->result_type = IS_TMP_VAR;
3680
1.43k
      result->op_type = IS_TMP_VAR;
3681
3682
1.43k
      opline = zend_emit_op_data(&expr_node);
3683
1.43k
      opline->extended_value = cache_slot;
3684
1.43k
      return;
3685
151k
    EMPTY_SWITCH_DEFAULT_CASE()
3686
151k
  }
3687
151k
}
3688
/* }}} */
3689
3690
7.06k
static uint32_t zend_get_arg_num(zend_function *fn, zend_string *arg_name) {
3691
  // TODO: Caching?
3692
7.06k
  if (fn->type == ZEND_USER_FUNCTION) {
3693
8.51k
    for (uint32_t i = 0; i < fn->common.num_args; i++) {
3694
7.89k
      zend_arg_info *arg_info = &fn->op_array.arg_info[i];
3695
7.89k
      if (zend_string_equals(arg_info->name, arg_name)) {
3696
1.35k
        return i + 1;
3697
1.35k
      }
3698
7.89k
    }
3699
5.08k
  } else {
3700
5.08k
    ZEND_ASSERT(fn->common.num_args == 0 || fn->internal_function.arg_info);
3701
15.6k
    for (uint32_t i = 0; i < fn->common.num_args; i++) {
3702
12.0k
      zend_internal_arg_info *arg_info = &fn->internal_function.arg_info[i];
3703
12.0k
      size_t len = strlen(arg_info->name);
3704
12.0k
      if (zend_string_equals_cstr(arg_name, arg_info->name, len)) {
3705
1.47k
        return i + 1;
3706
1.47k
      }
3707
12.0k
    }
3708
5.08k
  }
3709
3710
  /* Either an invalid argument name, or collected into a variadic argument. */
3711
4.23k
  return (uint32_t) -1;
3712
7.06k
}
3713
3714
static uint32_t zend_compile_args(
3715
    zend_ast *ast, zend_function *fbc, bool *may_have_extra_named_args) /* {{{ */
3716
1.95M
{
3717
1.95M
  zend_ast_list *args = zend_ast_get_list(ast);
3718
1.95M
  uint32_t i;
3719
1.95M
  bool uses_arg_unpack = false;
3720
1.95M
  uint32_t arg_count = 0; /* number of arguments not including unpacks */
3721
3722
  /* Whether named arguments are used syntactically, to enforce language level limitations.
3723
   * May not actually use named argument passing. */
3724
1.95M
  bool uses_named_args = false;
3725
  /* Whether there may be any undef arguments due to the use of named arguments. */
3726
1.95M
  bool may_have_undef = false;
3727
  /* Whether there may be any extra named arguments collected into a variadic. */
3728
1.95M
  *may_have_extra_named_args = false;
3729
3730
4.47M
  for (i = 0; i < args->children; ++i) {
3731
2.52M
    zend_ast *arg = args->child[i];
3732
2.52M
    zend_string *arg_name = NULL;
3733
2.52M
    uint32_t arg_num = i + 1;
3734
3735
2.52M
    znode arg_node;
3736
2.52M
    zend_op *opline;
3737
2.52M
    uint8_t opcode;
3738
3739
2.52M
    if (arg->kind == ZEND_AST_UNPACK) {
3740
2.40k
      if (uses_named_args) {
3741
7
        zend_error_noreturn(E_COMPILE_ERROR,
3742
7
          "Cannot use argument unpacking after named arguments");
3743
7
      }
3744
3745
      /* Unpack may contain named arguments. */
3746
2.39k
      may_have_undef = true;
3747
2.39k
      if (!fbc || (fbc->common.fn_flags & ZEND_ACC_VARIADIC)) {
3748
1.58k
        *may_have_extra_named_args = true;
3749
1.58k
      }
3750
3751
2.39k
      uses_arg_unpack = true;
3752
2.39k
      fbc = NULL;
3753
3754
2.39k
      zend_compile_expr(&arg_node, arg->child[0]);
3755
2.39k
      opline = zend_emit_op(NULL, ZEND_SEND_UNPACK, &arg_node, NULL);
3756
2.39k
      opline->op2.num = arg_count;
3757
2.39k
      opline->result.var = EX_NUM_TO_VAR(arg_count - 1);
3758
3759
2.39k
      continue;
3760
2.40k
    }
3761
3762
2.52M
    if (arg->kind == ZEND_AST_NAMED_ARG) {
3763
13.4k
      uses_named_args = true;
3764
13.4k
      arg_name = zval_make_interned_string(zend_ast_get_zval(arg->child[0]));
3765
13.4k
      arg = arg->child[1];
3766
3767
13.4k
      if (fbc && !uses_arg_unpack) {
3768
7.06k
        arg_num = zend_get_arg_num(fbc, arg_name);
3769
7.06k
        if (arg_num == arg_count + 1 && !may_have_undef) {
3770
          /* Using named arguments, but passing in order. */
3771
550
          arg_name = NULL;
3772
550
          arg_count++;
3773
6.51k
        } else {
3774
          // TODO: We could track which arguments were passed, even if out of order.
3775
6.51k
          may_have_undef = true;
3776
6.51k
          if (arg_num == (uint32_t) -1 && (fbc->common.fn_flags & ZEND_ACC_VARIADIC)) {
3777
386
            *may_have_extra_named_args = true;
3778
386
          }
3779
6.51k
        }
3780
7.06k
      } else {
3781
6.42k
        arg_num = (uint32_t) -1;
3782
6.42k
        may_have_undef = true;
3783
6.42k
        *may_have_extra_named_args = true;
3784
6.42k
      }
3785
2.50M
    } else {
3786
2.50M
      if (uses_arg_unpack) {
3787
14
        zend_error_noreturn(E_COMPILE_ERROR,
3788
14
          "Cannot use positional argument after argument unpacking");
3789
14
      }
3790
3791
2.50M
      if (uses_named_args) {
3792
64
        zend_error_noreturn(E_COMPILE_ERROR,
3793
64
          "Cannot use positional argument after named argument");
3794
64
      }
3795
3796
2.50M
      arg_count++;
3797
2.50M
    }
3798
3799
    /* Treat passing of $GLOBALS the same as passing a call.
3800
     * This will error at runtime if the argument is by-ref. */
3801
2.52M
    if (zend_is_call(arg) || is_globals_fetch(arg)) {
3802
137k
      zend_compile_var(&arg_node, arg, BP_VAR_R, false);
3803
137k
      if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) {
3804
        /* Function call was converted into builtin instruction */
3805
5.06k
        if (!fbc || ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3806
2.74k
          opcode = ZEND_SEND_VAL_EX;
3807
2.74k
        } else {
3808
2.31k
          opcode = ZEND_SEND_VAL;
3809
2.31k
        }
3810
132k
      } else {
3811
132k
        if (fbc && arg_num != (uint32_t) -1) {
3812
39.6k
          if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3813
539
            opcode = ZEND_SEND_VAR_NO_REF;
3814
39.0k
          } else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) {
3815
            /* For IS_VAR operands, SEND_VAL will pass through the operand without
3816
             * dereferencing, so it will use a by-ref pass if the call returned by-ref
3817
             * and a by-value pass if it returned by-value. */
3818
84
            opcode = ZEND_SEND_VAL;
3819
38.9k
          } else {
3820
38.9k
            opcode = ZEND_SEND_VAR;
3821
38.9k
          }
3822
93.0k
        } else {
3823
93.0k
          opcode = ZEND_SEND_VAR_NO_REF_EX;
3824
93.0k
        }
3825
132k
      }
3826
2.38M
    } else if (zend_is_variable(arg) && !zend_ast_is_short_circuited(arg)) {
3827
109k
      if (fbc && arg_num != (uint32_t) -1) {
3828
33.3k
        if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) {
3829
2.25k
          zend_compile_var(&arg_node, arg, BP_VAR_W, true);
3830
2.25k
          opcode = ZEND_SEND_REF;
3831
31.1k
        } else {
3832
31.1k
          zend_compile_var(&arg_node, arg, BP_VAR_R, false);
3833
31.1k
          opcode = (arg_node.op_type == IS_TMP_VAR) ? ZEND_SEND_VAL : ZEND_SEND_VAR;
3834
31.1k
        }
3835
76.0k
      } else {
3836
76.0k
        do {
3837
76.0k
          if (arg->kind == ZEND_AST_VAR) {
3838
66.7k
            CG(zend_lineno) = zend_ast_get_lineno(ast);
3839
66.7k
            if (is_this_fetch(arg)) {
3840
1.32k
              zend_emit_op(&arg_node, ZEND_FETCH_THIS, NULL, NULL);
3841
1.32k
              opcode = ZEND_SEND_VAR_EX;
3842
1.32k
              CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
3843
1.32k
              break;
3844
65.4k
            } else if (zend_try_compile_cv(&arg_node, arg, BP_VAR_R) == SUCCESS) {
3845
65.1k
              opcode = ZEND_SEND_VAR_EX;
3846
65.1k
              break;
3847
65.1k
            }
3848
66.7k
          }
3849
9.58k
          opline = zend_emit_op(NULL, ZEND_CHECK_FUNC_ARG, NULL, NULL);
3850
9.58k
          if (arg_name) {
3851
3.43k
            opline->op2_type = IS_CONST;
3852
3.43k
            zend_string_addref(arg_name);
3853
3.43k
            opline->op2.constant = zend_add_literal_string(&arg_name);
3854
3.43k
            opline->result.num = zend_alloc_cache_slots(2);
3855
6.14k
          } else {
3856
6.14k
            opline->op2.num = arg_num;
3857
6.14k
          }
3858
9.58k
          zend_compile_var(&arg_node, arg, BP_VAR_FUNC_ARG, true);
3859
9.58k
          opcode = ZEND_SEND_FUNC_ARG;
3860
9.58k
        } while (0);
3861
76.0k
      }
3862
2.27M
    } else {
3863
2.27M
      zend_compile_expr(&arg_node, arg);
3864
2.27M
      if (arg_node.op_type == IS_VAR) {
3865
        /* pass ++$a or something similar */
3866
308k
        if (fbc && arg_num != (uint32_t) -1) {
3867
3.15k
          if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3868
38
            opcode = ZEND_SEND_VAR_NO_REF;
3869
3.11k
          } else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) {
3870
34
            opcode = ZEND_SEND_VAL;
3871
3.08k
          } else {
3872
3.08k
            opcode = ZEND_SEND_VAR;
3873
3.08k
          }
3874
305k
        } else {
3875
305k
          opcode = ZEND_SEND_VAR_NO_REF_EX;
3876
305k
        }
3877
1.96M
      } else if (arg_node.op_type == IS_CV) {
3878
0
        if (fbc && arg_num != (uint32_t) -1) {
3879
0
          if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) {
3880
0
            opcode = ZEND_SEND_REF;
3881
0
          } else {
3882
0
            opcode = ZEND_SEND_VAR;
3883
0
          }
3884
0
        } else {
3885
0
          opcode = ZEND_SEND_VAR_EX;
3886
0
        }
3887
1.96M
      } else {
3888
        /* Delay "Only variables can be passed by reference" error to execution */
3889
1.96M
        if (fbc && arg_num != (uint32_t) -1 && !ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3890
103k
          opcode = ZEND_SEND_VAL;
3891
1.86M
        } else {
3892
1.86M
          opcode = ZEND_SEND_VAL_EX;
3893
1.86M
        }
3894
1.96M
      }
3895
2.27M
    }
3896
3897
2.52M
    opline = zend_emit_op(NULL, opcode, &arg_node, NULL);
3898
2.52M
    if (arg_name) {
3899
12.9k
      opline->op2_type = IS_CONST;
3900
12.9k
      zend_string_addref(arg_name);
3901
12.9k
      opline->op2.constant = zend_add_literal_string(&arg_name);
3902
12.9k
      opline->result.num = zend_alloc_cache_slots(2);
3903
2.50M
    } else {
3904
2.50M
      opline->op2.opline_num = arg_num;
3905
2.50M
      opline->result.var = EX_NUM_TO_VAR(arg_num - 1);
3906
2.50M
    }
3907
2.52M
  }
3908
3909
1.95M
  if (may_have_undef) {
3910
9.11k
    zend_emit_op(NULL, ZEND_CHECK_UNDEF_ARGS, NULL, NULL);
3911
9.11k
  }
3912
3913
1.95M
  return arg_count;
3914
1.95M
}
3915
/* }}} */
3916
3917
ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, zend_function *fbc, bool result_used) /* {{{ */
3918
2.06M
{
3919
2.06M
  uint32_t no_discard = result_used ? 0 : ZEND_ACC_NODISCARD;
3920
3921
2.06M
  if (fbc && init_op->opcode != ZEND_NEW) {
3922
250k
    ZEND_ASSERT(!(fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE));
3923
250k
    if (fbc->type == ZEND_INTERNAL_FUNCTION && !(CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS)) {
3924
204k
      if (init_op->opcode == ZEND_INIT_FCALL && !zend_execute_internal) {
3925
24.9k
        if (!(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) {
3926
24.9k
          return ZEND_DO_ICALL;
3927
24.9k
        } else {
3928
10
          return ZEND_DO_FCALL_BY_NAME;
3929
10
        }
3930
24.9k
      }
3931
204k
    } else if (!(CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS)){
3932
46.0k
      if (zend_execute_ex == execute_ex) {
3933
22.1k
        if (!(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) {
3934
21.9k
          return ZEND_DO_UCALL;
3935
21.9k
        } else {
3936
243
          return ZEND_DO_FCALL_BY_NAME;
3937
243
        }
3938
22.1k
      }
3939
46.0k
    }
3940
1.81M
  } else if (zend_execute_ex == execute_ex &&
3941
1.73M
             !zend_execute_internal &&
3942
1.68M
             (init_op->opcode == ZEND_INIT_FCALL_BY_NAME ||
3943
1.60M
              init_op->opcode == ZEND_INIT_NS_FCALL_BY_NAME)) {
3944
1.53M
    return ZEND_DO_FCALL_BY_NAME;
3945
1.53M
  }
3946
479k
  return ZEND_DO_FCALL;
3947
2.06M
}
3948
/* }}} */
3949
3950
static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc, uint32_t lineno) /* {{{ */
3951
1.95M
{
3952
1.95M
  zend_op *opline;
3953
1.95M
  uint32_t opnum_init = get_next_op_number() - 1;
3954
3955
1.95M
  if (args_ast->kind == ZEND_AST_CALLABLE_CONVERT) {
3956
3.57k
    opline = &CG(active_op_array)->opcodes[opnum_init];
3957
3.57k
    opline->extended_value = 0;
3958
3959
3.57k
    if (opline->opcode == ZEND_NEW) {
3960
21
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot create Closure for new expression");
3961
21
    }
3962
3963
3.55k
    if (opline->opcode == ZEND_INIT_FCALL) {
3964
741
      opline->op1.num = zend_vm_calc_used_stack(0, fbc);
3965
741
    }
3966
3967
3.55k
    zend_emit_op_tmp(result, ZEND_CALLABLE_CONVERT, NULL, NULL);
3968
3.55k
    return true;
3969
3.57k
  }
3970
3971
1.95M
  bool may_have_extra_named_args;
3972
1.95M
  uint32_t arg_count = zend_compile_args(args_ast, fbc, &may_have_extra_named_args);
3973
3974
1.95M
  zend_do_extended_fcall_begin();
3975
3976
1.95M
  opline = &CG(active_op_array)->opcodes[opnum_init];
3977
1.95M
  opline->extended_value = arg_count;
3978
3979
1.95M
  if (opline->opcode == ZEND_INIT_FCALL) {
3980
135k
    opline->op1.num = zend_vm_calc_used_stack(arg_count, fbc);
3981
135k
  }
3982
3983
1.95M
  uint8_t call_op = zend_get_call_op(
3984
1.95M
    opline,
3985
1.95M
    fbc,
3986
    /* result_used: At this point we do not yet reliably
3987
     * know if the result is used. Deoptimize #[\NoDiscard]
3988
     * calls to be sure. The optimizer will fix this up.
3989
     */
3990
1.95M
    false
3991
1.95M
  );
3992
1.95M
  opline = zend_emit_op(result, call_op, NULL, NULL);
3993
1.95M
  if (may_have_extra_named_args) {
3994
5.77k
    opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS;
3995
5.77k
  }
3996
1.95M
  opline->lineno = lineno;
3997
1.95M
  zend_do_extended_fcall_end();
3998
1.95M
  return false;
3999
1.95M
}
4000
/* }}} */
4001
4002
static bool zend_compile_function_name(znode *name_node, zend_ast *name_ast) /* {{{ */
4003
1.70M
{
4004
1.70M
  zend_string *orig_name = zend_ast_get_str(name_ast);
4005
1.70M
  bool is_fully_qualified;
4006
4007
1.70M
  name_node->op_type = IS_CONST;
4008
1.70M
  ZVAL_STR(&name_node->u.constant, zend_resolve_function_name(
4009
1.70M
    orig_name, name_ast->attr, &is_fully_qualified));
4010
4011
1.70M
  return !is_fully_qualified && FC(current_namespace);
4012
1.70M
}
4013
/* }}} */
4014
4015
static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno) /* {{{ */
4016
191k
{
4017
191k
  if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) {
4018
91.3k
    const char *colon;
4019
91.3k
    zend_string *str = Z_STR(name_node->u.constant);
4020
91.3k
    if ((colon = zend_memrchr(ZSTR_VAL(str), ':', ZSTR_LEN(str))) != NULL && colon > ZSTR_VAL(str) && *(colon - 1) == ':') {
4021
355
      zend_string *class = zend_string_init(ZSTR_VAL(str), colon - ZSTR_VAL(str) - 1, 0);
4022
355
      zend_string *method = zend_string_init(colon + 1, ZSTR_LEN(str) - (colon - ZSTR_VAL(str)) - 1, 0);
4023
355
      zend_op *opline = get_next_op();
4024
4025
355
      opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
4026
355
      opline->op1_type = IS_CONST;
4027
355
      opline->op1.constant = zend_add_class_name_literal(class);
4028
355
      opline->op2_type = IS_CONST;
4029
355
      opline->op2.constant = zend_add_func_name_literal(method);
4030
      /* 2 slots, for class and method */
4031
355
      opline->result.num = zend_alloc_cache_slots(2);
4032
355
      zval_ptr_dtor(&name_node->u.constant);
4033
90.9k
    } else {
4034
90.9k
      zend_op *opline = get_next_op();
4035
4036
90.9k
      opline->opcode = ZEND_INIT_FCALL_BY_NAME;
4037
90.9k
      opline->op2_type = IS_CONST;
4038
90.9k
      opline->op2.constant = zend_add_func_name_literal(str);
4039
90.9k
      opline->result.num = zend_alloc_cache_slot();
4040
90.9k
    }
4041
99.9k
  } else {
4042
99.9k
    zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, name_node);
4043
99.9k
  }
4044
4045
191k
  zend_compile_call_common(result, args_ast, NULL, lineno);
4046
191k
}
4047
/* }}} */
4048
4049
static inline bool zend_args_contain_unpack_or_named(zend_ast_list *args) /* {{{ */
4050
1.57M
{
4051
1.57M
  uint32_t i;
4052
3.76M
  for (i = 0; i < args->children; ++i) {
4053
2.19M
    zend_ast *arg = args->child[i];
4054
2.19M
    if (arg->kind == ZEND_AST_UNPACK || arg->kind == ZEND_AST_NAMED_ARG) {
4055
2.75k
      return 1;
4056
2.75k
    }
4057
2.19M
  }
4058
1.57M
  return 0;
4059
1.57M
}
4060
/* }}} */
4061
4062
static zend_result zend_compile_func_strlen(znode *result, zend_ast_list *args) /* {{{ */
4063
839
{
4064
839
  znode arg_node;
4065
4066
839
  if (args->children != 1) {
4067
31
    return FAILURE;
4068
31
  }
4069
4070
808
  zend_compile_expr(&arg_node, args->child[0]);
4071
808
  if (arg_node.op_type == IS_CONST && Z_TYPE(arg_node.u.constant) == IS_STRING) {
4072
168
    result->op_type = IS_CONST;
4073
168
    ZVAL_LONG(&result->u.constant, Z_STRLEN(arg_node.u.constant));
4074
168
    zval_ptr_dtor_str(&arg_node.u.constant);
4075
640
  } else {
4076
640
    zend_emit_op_tmp(result, ZEND_STRLEN, &arg_node, NULL);
4077
640
  }
4078
808
  return SUCCESS;
4079
839
}
4080
/* }}} */
4081
4082
static zend_result zend_compile_func_typecheck(znode *result, zend_ast_list *args, uint32_t type) /* {{{ */
4083
1.65k
{
4084
1.65k
  znode arg_node;
4085
1.65k
  zend_op *opline;
4086
4087
1.65k
  if (args->children != 1) {
4088
341
    return FAILURE;
4089
341
  }
4090
4091
1.31k
  zend_compile_expr(&arg_node, args->child[0]);
4092
1.31k
  opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL);
4093
1.31k
  if (type != _IS_BOOL) {
4094
1.23k
    opline->extended_value = (1 << type);
4095
1.23k
  } else {
4096
81
    opline->extended_value = (1 << IS_FALSE) | (1 << IS_TRUE);
4097
81
  }
4098
1.31k
  return SUCCESS;
4099
1.65k
}
4100
/* }}} */
4101
4102
static zend_result zend_compile_func_is_scalar(znode *result, zend_ast_list *args) /* {{{ */
4103
91
{
4104
91
  znode arg_node;
4105
91
  zend_op *opline;
4106
4107
91
  if (args->children != 1) {
4108
10
    return FAILURE;
4109
10
  }
4110
4111
81
  zend_compile_expr(&arg_node, args->child[0]);
4112
81
  opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL);
4113
81
  opline->extended_value = (1 << IS_FALSE | 1 << IS_TRUE | 1 << IS_DOUBLE | 1 << IS_LONG | 1 << IS_STRING);
4114
81
  return SUCCESS;
4115
91
}
4116
4117
static zend_result zend_compile_func_cast(znode *result, zend_ast_list *args, uint32_t type) /* {{{ */
4118
820
{
4119
820
  znode arg_node;
4120
820
  zend_op *opline;
4121
4122
820
  if (args->children != 1) {
4123
180
    return FAILURE;
4124
180
  }
4125
4126
640
  zend_compile_expr(&arg_node, args->child[0]);
4127
640
  if (type == _IS_BOOL) {
4128
29
    opline = zend_emit_op_tmp(result, ZEND_BOOL, &arg_node, NULL);
4129
611
  } else {
4130
611
    opline = zend_emit_op_tmp(result, ZEND_CAST, &arg_node, NULL);
4131
611
    opline->extended_value = type;
4132
611
  }
4133
640
  return SUCCESS;
4134
820
}
4135
/* }}} */
4136
4137
static zend_result zend_compile_func_defined(znode *result, zend_ast_list *args) /* {{{ */
4138
1.06k
{
4139
1.06k
  zend_string *name;
4140
1.06k
  zend_op *opline;
4141
4142
1.06k
  if (args->children != 1 || args->child[0]->kind != ZEND_AST_ZVAL) {
4143
194
    return FAILURE;
4144
194
  }
4145
4146
874
  name = zval_get_string(zend_ast_get_zval(args->child[0]));
4147
874
  if (zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name)) || zend_memrchr(ZSTR_VAL(name), ':', ZSTR_LEN(name))) {
4148
362
    zend_string_release_ex(name, 0);
4149
362
    return FAILURE;
4150
362
  }
4151
4152
512
  if (zend_try_ct_eval_const(&result->u.constant, name, false)) {
4153
199
    zend_string_release_ex(name, 0);
4154
199
    zval_ptr_dtor(&result->u.constant);
4155
199
    ZVAL_TRUE(&result->u.constant);
4156
199
    result->op_type = IS_CONST;
4157
199
    return SUCCESS;
4158
199
  }
4159
4160
313
  opline = zend_emit_op_tmp(result, ZEND_DEFINED, NULL, NULL);
4161
313
  opline->op1_type = IS_CONST;
4162
313
  LITERAL_STR(opline->op1, name);
4163
313
  opline->extended_value = zend_alloc_cache_slot();
4164
4165
313
  return SUCCESS;
4166
512
}
4167
/* }}} */
4168
4169
static zend_result zend_compile_func_chr(znode *result, const zend_ast_list *args) /* {{{ */
4170
776
{
4171
776
  zval *zint;
4172
776
  if (
4173
776
    args->children == 1
4174
731
    && args->child[0]->kind == ZEND_AST_ZVAL
4175
625
    && (zint = zend_ast_get_zval(args->child[0]))
4176
625
    && Z_TYPE_P(zint) == IS_LONG
4177
529
    && Z_LVAL_P(zint) >= 0
4178
529
    && Z_LVAL_P(zint) <= 255
4179
776
  ) {
4180
395
    result->op_type = IS_CONST;
4181
395
    ZVAL_CHAR(&result->u.constant, Z_LVAL_P(zint));
4182
395
    return SUCCESS;
4183
395
  } else {
4184
381
    return FAILURE;
4185
381
  }
4186
776
}
4187
/* }}} */
4188
4189
static zend_result zend_compile_func_ord(znode *result, const zend_ast_list *args) /* {{{ */
4190
623
{
4191
623
  zval *str;
4192
623
  if (
4193
623
    args->children == 1
4194
419
    && args->child[0]->kind == ZEND_AST_ZVAL
4195
278
    && (str = zend_ast_get_zval(args->child[0]))
4196
278
    && Z_TYPE_P(str) == IS_STRING
4197
224
    && Z_STRLEN_P(str) == 1
4198
623
  ) {
4199
10
    result->op_type = IS_CONST;
4200
10
    ZVAL_LONG(&result->u.constant, (unsigned char)Z_STRVAL_P(str)[0]);
4201
10
    return SUCCESS;
4202
613
  } else {
4203
613
    return FAILURE;
4204
613
  }
4205
623
}
4206
/* }}} */
4207
4208
/* We can only calculate the stack size for functions that have been fully compiled, otherwise
4209
 * additional CV or TMP slots may still be added. This prevents the use of INIT_FCALL for
4210
 * directly or indirectly recursive function calls. */
4211
159k
static bool fbc_is_finalized(zend_function *fbc) {
4212
159k
  return !ZEND_USER_CODE(fbc->type) || (fbc->common.fn_flags & ZEND_ACC_DONE_PASS_TWO);
4213
159k
}
4214
4215
static bool zend_compile_ignore_class(zend_class_entry *ce, zend_string *filename)
4216
13.8k
{
4217
13.8k
  if (ce->type == ZEND_INTERNAL_CLASS) {
4218
3.41k
    return CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES;
4219
10.4k
  } else {
4220
10.4k
    return (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES)
4221
5.35k
      && ce->info.user.filename != filename;
4222
10.4k
  }
4223
13.8k
}
4224
4225
static bool zend_compile_ignore_function(zend_function *fbc, zend_string *filename)
4226
139k
{
4227
139k
  if (fbc->type == ZEND_INTERNAL_FUNCTION) {
4228
117k
    return CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS;
4229
117k
  } else {
4230
21.7k
    return (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS)
4231
21.7k
      || ((CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES)
4232
19.6k
        && fbc->op_array.filename != filename);
4233
21.7k
  }
4234
139k
}
4235
4236
static zend_result zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t num_args) /* {{{ */
4237
4.65k
{
4238
4.65k
  zend_string *name, *lcname;
4239
4.65k
  zend_function *fbc;
4240
4.65k
  zend_op *opline;
4241
4242
4.65k
  if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
4243
2.36k
    return FAILURE;
4244
2.36k
  }
4245
4246
2.29k
  name = zend_ast_get_str(name_ast);
4247
2.29k
  lcname = zend_string_tolower(name);
4248
4249
2.29k
  fbc = zend_hash_find_ptr(CG(function_table), lcname);
4250
2.29k
  if (!fbc
4251
922
   || !fbc_is_finalized(fbc)
4252
1.37k
   || zend_compile_ignore_function(fbc, CG(active_op_array)->filename)) {
4253
1.37k
    zend_string_release_ex(lcname, 0);
4254
1.37k
    return FAILURE;
4255
1.37k
  }
4256
4257
922
  opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, NULL);
4258
922
  opline->extended_value = num_args;
4259
922
  opline->op1.num = zend_vm_calc_used_stack(num_args, fbc);
4260
922
  opline->op2_type = IS_CONST;
4261
922
  LITERAL_STR(opline->op2, lcname);
4262
922
  opline->result.num = zend_alloc_cache_slot();
4263
4264
922
  return SUCCESS;
4265
2.29k
}
4266
/* }}} */
4267
4268
static void zend_compile_init_user_func(zend_ast *name_ast, uint32_t num_args, zend_string *orig_func_name) /* {{{ */
4269
4.65k
{
4270
4.65k
  zend_op *opline;
4271
4.65k
  znode name_node;
4272
4273
4.65k
  if (zend_try_compile_ct_bound_init_user_func(name_ast, num_args) == SUCCESS) {
4274
922
    return;
4275
922
  }
4276
4277
3.73k
  zend_compile_expr(&name_node, name_ast);
4278
4279
3.73k
  opline = zend_emit_op(NULL, ZEND_INIT_USER_CALL, NULL, &name_node);
4280
3.73k
  opline->op1_type = IS_CONST;
4281
3.73k
  LITERAL_STR(opline->op1, zend_string_copy(orig_func_name));
4282
3.73k
  opline->extended_value = num_args;
4283
3.73k
}
4284
/* }}} */
4285
4286
/* cufa = call_user_func_array */
4287
static zend_result zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
4288
2.20k
{
4289
2.20k
  znode arg_node;
4290
2.20k
  zend_op *opline;
4291
4292
2.20k
  if (args->children != 2) {
4293
86
    return FAILURE;
4294
86
  }
4295
4296
2.12k
  zend_compile_init_user_func(args->child[0], 0, lcname);
4297
2.12k
  if (args->child[1]->kind == ZEND_AST_CALL
4298
1.56k
   && args->child[1]->child[0]->kind == ZEND_AST_ZVAL
4299
1.47k
   && Z_TYPE_P(zend_ast_get_zval(args->child[1]->child[0])) == IS_STRING
4300
1.35k
   && args->child[1]->child[1]->kind == ZEND_AST_ARG_LIST) {
4301
1.29k
    zend_string *orig_name = zend_ast_get_str(args->child[1]->child[0]);
4302
1.29k
    zend_ast_list *list = zend_ast_get_list(args->child[1]->child[1]);
4303
1.29k
    bool is_fully_qualified;
4304
1.29k
    zend_string *name = zend_resolve_function_name(orig_name, args->child[1]->child[0]->attr, &is_fully_qualified);
4305
4306
1.29k
    if (zend_string_equals_literal_ci(name, "array_slice")
4307
1.05k
       && !zend_args_contain_unpack_or_named(list)
4308
970
     && list->children == 3
4309
525
     && list->child[1]->kind == ZEND_AST_ZVAL) {
4310
503
      zval *zv = zend_ast_get_zval(list->child[1]);
4311
4312
503
      if (Z_TYPE_P(zv) == IS_LONG
4313
466
       && Z_LVAL_P(zv) >= 0
4314
466
       && Z_LVAL_P(zv) <= 0x7fffffff) {
4315
178
        zend_op *opline;
4316
178
        znode len_node;
4317
4318
178
        zend_compile_expr(&arg_node, list->child[0]);
4319
178
        zend_compile_expr(&len_node, list->child[2]);
4320
178
        opline = zend_emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, &len_node);
4321
178
        opline->extended_value = Z_LVAL_P(zv);
4322
178
        zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
4323
178
        zend_string_release_ex(name, 0);
4324
178
        return SUCCESS;
4325
178
      }
4326
503
    }
4327
1.11k
    zend_string_release_ex(name, 0);
4328
1.11k
  }
4329
1.94k
  zend_compile_expr(&arg_node, args->child[1]);
4330
1.94k
  zend_emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, NULL);
4331
1.94k
  zend_emit_op(NULL, ZEND_CHECK_UNDEF_ARGS, NULL, NULL);
4332
1.94k
  opline = zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
4333
1.94k
  opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS;
4334
4335
1.94k
  return SUCCESS;
4336
2.12k
}
4337
/* }}} */
4338
4339
/* cuf = call_user_func */
4340
static zend_result zend_compile_func_cuf(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
4341
2.55k
{
4342
2.55k
  uint32_t i;
4343
4344
2.55k
  if (args->children < 1) {
4345
18
    return FAILURE;
4346
18
  }
4347
4348
2.53k
  zend_compile_init_user_func(args->child[0], args->children - 1, lcname);
4349
5.53k
  for (i = 1; i < args->children; ++i) {
4350
2.99k
    zend_ast *arg_ast = args->child[i];
4351
2.99k
    znode arg_node;
4352
2.99k
    zend_op *opline;
4353
4354
2.99k
    zend_compile_expr(&arg_node, arg_ast);
4355
4356
2.99k
    opline = zend_emit_op(NULL, ZEND_SEND_USER, &arg_node, NULL);
4357
2.99k
    opline->op2.num = i;
4358
2.99k
    opline->result.var = EX_NUM_TO_VAR(i - 1);
4359
2.99k
  }
4360
2.53k
  zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
4361
4362
2.53k
  return SUCCESS;
4363
2.55k
}
4364
/* }}} */
4365
4366
static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, zend_function *fbc, uint32_t lineno) /* {{{ */
4367
22.7k
{
4368
22.7k
  if (EG(assertions) >= 0) {
4369
22.7k
    znode name_node;
4370
22.7k
    zend_op *opline;
4371
22.7k
    uint32_t check_op_number = get_next_op_number();
4372
4373
22.7k
    zend_emit_op(NULL, ZEND_ASSERT_CHECK, NULL, NULL);
4374
4375
22.7k
    if (fbc && fbc_is_finalized(fbc)) {
4376
20.6k
      name_node.op_type = IS_CONST;
4377
20.6k
      ZVAL_STR_COPY(&name_node.u.constant, name);
4378
4379
20.6k
      opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
4380
20.6k
    } else {
4381
2.09k
      opline = zend_emit_op(NULL, ZEND_INIT_NS_FCALL_BY_NAME, NULL, NULL);
4382
2.09k
      opline->op2_type = IS_CONST;
4383
2.09k
      opline->op2.constant = zend_add_ns_func_name_literal(name);
4384
2.09k
    }
4385
22.7k
    opline->result.num = zend_alloc_cache_slot();
4386
4387
22.7k
    if (args->children == 1) {
4388
      /* add "assert(condition) as assertion message */
4389
20.7k
      zend_ast *arg = zend_ast_create_zval_from_str(
4390
20.7k
        zend_ast_export("assert(", args->child[0], ")"));
4391
20.7k
      if (args->child[0]->kind == ZEND_AST_NAMED_ARG) {
4392
        /* If the original argument was named, add the new argument as named as well,
4393
         * as mixing named and positional is not allowed. */
4394
1.08k
        zend_ast *name = zend_ast_create_zval_from_str(
4395
1.08k
          ZSTR_INIT_LITERAL("description", 0));
4396
1.08k
        arg = zend_ast_create(ZEND_AST_NAMED_ARG, name, arg);
4397
1.08k
      }
4398
20.7k
      args = (zend_ast_list *)zend_ast_list_add((zend_ast *) args, arg);
4399
20.7k
    }
4400
4401
22.7k
    zend_compile_call_common(result, (zend_ast*)args, fbc, lineno);
4402
4403
22.7k
    opline = &CG(active_op_array)->opcodes[check_op_number];
4404
22.7k
    opline->op2.opline_num = get_next_op_number();
4405
22.7k
    SET_NODE(opline->result, result);
4406
22.7k
  } else {
4407
0
    if (!fbc) {
4408
0
      zend_string_release_ex(name, 0);
4409
0
    }
4410
0
    result->op_type = IS_CONST;
4411
0
    ZVAL_TRUE(&result->u.constant);
4412
0
  }
4413
22.7k
}
4414
/* }}} */
4415
4416
static zend_result zend_compile_func_in_array(znode *result, zend_ast_list *args) /* {{{ */
4417
3.97k
{
4418
3.97k
  bool strict = false;
4419
3.97k
  znode array, needly;
4420
3.97k
  zend_op *opline;
4421
4422
3.97k
  if (args->children == 3) {
4423
2.67k
    if (args->child[2]->kind == ZEND_AST_ZVAL) {
4424
591
      strict = zend_is_true(zend_ast_get_zval(args->child[2]));
4425
2.07k
    } else if (args->child[2]->kind == ZEND_AST_CONST) {
4426
1.89k
      zval value;
4427
1.89k
      zend_ast *name_ast = args->child[2]->child[0];
4428
1.89k
      bool is_fully_qualified;
4429
1.89k
      zend_string *resolved_name = zend_resolve_const_name(
4430
1.89k
        zend_ast_get_str(name_ast), name_ast->attr, &is_fully_qualified);
4431
4432
1.89k
      if (!zend_try_ct_eval_const(&value, resolved_name, is_fully_qualified)) {
4433
761
        zend_string_release_ex(resolved_name, 0);
4434
761
        return FAILURE;
4435
761
      }
4436
4437
1.13k
      zend_string_release_ex(resolved_name, 0);
4438
1.13k
      strict = zend_is_true(&value);
4439
1.13k
      zval_ptr_dtor(&value);
4440
1.13k
    } else {
4441
180
      return FAILURE;
4442
180
    }
4443
2.67k
  } else if (args->children != 2) {
4444
135
    return FAILURE;
4445
135
  }
4446
4447
2.90k
  if (args->child[1]->kind != ZEND_AST_ARRAY
4448
2.57k
   || !zend_try_ct_eval_array(&array.u.constant, args->child[1])) {
4449
432
    return FAILURE;
4450
432
  }
4451
4452
2.47k
  if (zend_hash_num_elements(Z_ARRVAL(array.u.constant)) > 0) {
4453
1.32k
    bool ok = true;
4454
1.32k
    zval *val, tmp;
4455
1.32k
    HashTable *src = Z_ARRVAL(array.u.constant);
4456
1.32k
    HashTable *dst = zend_new_array(zend_hash_num_elements(src));
4457
4458
1.32k
    ZVAL_TRUE(&tmp);
4459
4460
1.32k
    if (strict) {
4461
3.77k
      ZEND_HASH_FOREACH_VAL(src, val) {
4462
3.77k
        if (Z_TYPE_P(val) == IS_STRING) {
4463
40
          zend_hash_add(dst, Z_STR_P(val), &tmp);
4464
1.03k
        } else if (Z_TYPE_P(val) == IS_LONG) {
4465
996
          zend_hash_index_add(dst, Z_LVAL_P(val), &tmp);
4466
996
        } else {
4467
40
          zend_array_destroy(dst);
4468
40
          ok = false;
4469
40
          break;
4470
40
        }
4471
3.77k
      } ZEND_HASH_FOREACH_END();
4472
747
    } else {
4473
3.51k
      ZEND_HASH_FOREACH_VAL(src, val) {
4474
3.51k
        if (Z_TYPE_P(val) != IS_STRING
4475
597
         || is_numeric_string(Z_STRVAL_P(val), Z_STRLEN_P(val), NULL, NULL, 0)) {
4476
524
          zend_array_destroy(dst);
4477
524
          ok = false;
4478
524
          break;
4479
524
        }
4480
508
        zend_hash_add(dst, Z_STR_P(val), &tmp);
4481
508
      } ZEND_HASH_FOREACH_END();
4482
747
    }
4483
4484
1.32k
    zend_array_destroy(src);
4485
1.32k
    if (!ok) {
4486
564
      return FAILURE;
4487
564
    }
4488
758
    Z_ARRVAL(array.u.constant) = dst;
4489
758
  }
4490
1.90k
  array.op_type = IS_CONST;
4491
4492
1.90k
  zend_compile_expr(&needly, args->child[0]);
4493
4494
1.90k
  opline = zend_emit_op_tmp(result, ZEND_IN_ARRAY, &needly, &array);
4495
1.90k
  opline->extended_value = strict;
4496
4497
1.90k
  return SUCCESS;
4498
2.47k
}
4499
/* }}} */
4500
4501
static zend_result zend_compile_func_count(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
4502
1.17k
{
4503
1.17k
  znode arg_node;
4504
1.17k
  zend_op *opline;
4505
4506
1.17k
  if (args->children != 1) {
4507
86
    return FAILURE;
4508
86
  }
4509
4510
1.08k
  zend_compile_expr(&arg_node, args->child[0]);
4511
1.08k
  opline = zend_emit_op_tmp(result, ZEND_COUNT, &arg_node, NULL);
4512
1.08k
  opline->extended_value = zend_string_equals_literal(lcname, "sizeof");
4513
4514
1.08k
  return SUCCESS;
4515
1.17k
}
4516
/* }}} */
4517
4518
static zend_result zend_compile_func_get_class(znode *result, zend_ast_list *args) /* {{{ */
4519
1.07k
{
4520
1.07k
  if (args->children == 0) {
4521
110
    zend_emit_op_tmp(result, ZEND_GET_CLASS, NULL, NULL);
4522
961
  } else {
4523
961
    znode arg_node;
4524
4525
961
    if (args->children != 1) {
4526
66
      return FAILURE;
4527
66
    }
4528
4529
895
    zend_compile_expr(&arg_node, args->child[0]);
4530
895
    zend_emit_op_tmp(result, ZEND_GET_CLASS, &arg_node, NULL);
4531
895
  }
4532
1.00k
  return SUCCESS;
4533
1.07k
}
4534
/* }}} */
4535
4536
static zend_result zend_compile_func_get_called_class(znode *result, zend_ast_list *args) /* {{{ */
4537
396
{
4538
396
  if (args->children != 0) {
4539
88
    return FAILURE;
4540
88
  }
4541
4542
308
  zend_emit_op_tmp(result, ZEND_GET_CALLED_CLASS, NULL, NULL);
4543
308
  return SUCCESS;
4544
396
}
4545
/* }}} */
4546
4547
static zend_result zend_compile_func_gettype(znode *result, zend_ast_list *args) /* {{{ */
4548
768
{
4549
768
  znode arg_node;
4550
4551
768
  if (args->children != 1) {
4552
22
    return FAILURE;
4553
22
  }
4554
4555
746
  zend_compile_expr(&arg_node, args->child[0]);
4556
746
  zend_emit_op_tmp(result, ZEND_GET_TYPE, &arg_node, NULL);
4557
746
  return SUCCESS;
4558
768
}
4559
/* }}} */
4560
4561
static zend_result zend_compile_func_num_args(znode *result, zend_ast_list *args) /* {{{ */
4562
142
{
4563
142
  if (CG(active_op_array)->function_name && args->children == 0) {
4564
72
    zend_emit_op_tmp(result, ZEND_FUNC_NUM_ARGS, NULL, NULL);
4565
72
    return SUCCESS;
4566
72
  } else {
4567
70
    return FAILURE;
4568
70
  }
4569
142
}
4570
/* }}} */
4571
4572
static zend_result zend_compile_func_get_args(znode *result, zend_ast_list *args) /* {{{ */
4573
567
{
4574
567
  if (CG(active_op_array)->function_name && args->children == 0) {
4575
384
    zend_emit_op_tmp(result, ZEND_FUNC_GET_ARGS, NULL, NULL);
4576
384
    return SUCCESS;
4577
384
  } else {
4578
183
    return FAILURE;
4579
183
  }
4580
567
}
4581
/* }}} */
4582
4583
static zend_result zend_compile_func_array_key_exists(znode *result, zend_ast_list *args) /* {{{ */
4584
355
{
4585
355
  znode subject, needle;
4586
4587
355
  if (args->children != 2) {
4588
159
    return FAILURE;
4589
159
  }
4590
4591
196
  zend_compile_expr(&needle, args->child[0]);
4592
196
  zend_compile_expr(&subject, args->child[1]);
4593
4594
196
  zend_emit_op_tmp(result, ZEND_ARRAY_KEY_EXISTS, &needle, &subject);
4595
196
  return SUCCESS;
4596
355
}
4597
/* }}} */
4598
4599
static zend_result zend_compile_func_array_slice(znode *result, zend_ast_list *args) /* {{{ */
4600
1.50k
{
4601
1.50k
  if (CG(active_op_array)->function_name
4602
544
   && args->children == 2
4603
408
   && args->child[0]->kind == ZEND_AST_CALL
4604
384
   && args->child[0]->child[0]->kind == ZEND_AST_ZVAL
4605
357
   && Z_TYPE_P(zend_ast_get_zval(args->child[0]->child[0])) == IS_STRING
4606
357
   && args->child[0]->child[1]->kind == ZEND_AST_ARG_LIST
4607
357
   && args->child[1]->kind == ZEND_AST_ZVAL) {
4608
4609
308
    zend_string *orig_name = zend_ast_get_str(args->child[0]->child[0]);
4610
308
    bool is_fully_qualified;
4611
308
    zend_string *name = zend_resolve_function_name(orig_name, args->child[0]->child[0]->attr, &is_fully_qualified);
4612
308
    zend_ast_list *list = zend_ast_get_list(args->child[0]->child[1]);
4613
308
    zval *zv = zend_ast_get_zval(args->child[1]);
4614
308
    znode first;
4615
4616
308
    if (zend_string_equals_literal_ci(name, "func_get_args")
4617
175
     && list->children == 0
4618
129
     && Z_TYPE_P(zv) == IS_LONG
4619
84
     && Z_LVAL_P(zv) >= 0) {
4620
84
      first.op_type = IS_CONST;
4621
84
      ZVAL_LONG(&first.u.constant, Z_LVAL_P(zv));
4622
84
      zend_emit_op_tmp(result, ZEND_FUNC_GET_ARGS, &first, NULL);
4623
84
      zend_string_release_ex(name, 0);
4624
84
      return SUCCESS;
4625
84
    }
4626
224
    zend_string_release_ex(name, 0);
4627
224
  }
4628
1.41k
  return FAILURE;
4629
1.50k
}
4630
/* }}} */
4631
4632
static uint32_t find_frameless_function_offset(uint32_t arity, void *handler)
4633
517k
{
4634
517k
  void **handlers = zend_flf_handlers;
4635
517k
  void **current = handlers;
4636
4.19M
  while (current) {
4637
4.19M
    if (*current == handler) {
4638
517k
      return current - handlers;
4639
517k
    }
4640
3.67M
    current++;
4641
3.67M
  }
4642
4643
0
  return (uint32_t)-1;
4644
517k
}
4645
4646
static const zend_frameless_function_info *find_frameless_function_info(zend_ast_list *args, zend_function *fbc, uint32_t type)
4647
363k
{
4648
363k
  if (zend_execute_internal) {
4649
90.5k
    return NULL;
4650
90.5k
  }
4651
4652
272k
  if (type != BP_VAR_R) {
4653
546
    return NULL;
4654
546
  }
4655
4656
272k
  if (ZEND_USER_CODE(fbc->type)) {
4657
8
    return NULL;
4658
8
  }
4659
4660
272k
  const zend_frameless_function_info *frameless_function_info = fbc->internal_function.frameless_function_infos;
4661
272k
  if (!frameless_function_info) {
4662
10.5k
    return NULL;
4663
10.5k
  }
4664
4665
261k
  if (args->children > 3) {
4666
548
    return NULL;
4667
548
  }
4668
4669
295k
  while (frameless_function_info->handler) {
4670
293k
    if (frameless_function_info->num_args >= args->children
4671
262k
     && fbc->common.required_num_args <= args->children
4672
259k
     && (!(fbc->common.fn_flags & ZEND_ACC_VARIADIC)
4673
258k
      || frameless_function_info->num_args == args->children)) {
4674
258k
      uint32_t num_args = frameless_function_info->num_args;
4675
258k
      uint32_t offset = find_frameless_function_offset(num_args, frameless_function_info->handler);
4676
258k
      if (offset == (uint32_t)-1) {
4677
0
        continue;
4678
0
      }
4679
258k
      return frameless_function_info;
4680
258k
    }
4681
34.3k
    frameless_function_info++;
4682
34.3k
  }
4683
4684
2.16k
  return NULL;
4685
260k
}
4686
4687
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)
4688
258k
{
4689
258k
  int lineno = CG(zend_lineno);
4690
258k
  uint32_t num_args = frameless_function_info->num_args;
4691
258k
  uint32_t offset = find_frameless_function_offset(num_args, frameless_function_info->handler);
4692
258k
  znode arg_zvs[3];
4693
806k
  for (uint32_t i = 0; i < num_args; i++) {
4694
547k
    if (i < args->children) {
4695
547k
      zend_compile_expr(&arg_zvs[i], args->child[i]);
4696
547k
    } else {
4697
0
      zend_internal_arg_info *arg_info = (zend_internal_arg_info *)&fbc->common.arg_info[i];
4698
0
      arg_zvs[i].op_type = IS_CONST;
4699
0
      if (zend_get_default_from_internal_arg_info(&arg_zvs[i].u.constant, arg_info) == FAILURE) {
4700
0
        ZEND_UNREACHABLE();
4701
0
      }
4702
0
    }
4703
547k
  }
4704
258k
  uint8_t opcode = ZEND_FRAMELESS_ICALL_0 + num_args;
4705
258k
  uint32_t opnum = get_next_op_number();
4706
258k
  zend_op *opline = zend_emit_op_tmp(result, opcode, NULL, NULL);
4707
258k
  opline->extended_value = offset;
4708
258k
  opline->lineno = lineno;
4709
258k
  if (num_args >= 1) {
4710
258k
    SET_NODE(opline->op1, &arg_zvs[0]);
4711
258k
  }
4712
258k
  if (num_args >= 2) {
4713
258k
    SET_NODE(opline->op2, &arg_zvs[1]);
4714
258k
  }
4715
258k
  if (num_args >= 3) {
4716
30.4k
    zend_emit_op_data(&arg_zvs[2]);
4717
30.4k
  }
4718
258k
  return opnum;
4719
258k
}
4720
4721
static uint32_t zend_compile_frameless_icall(znode *result, zend_ast_list *args, zend_function *fbc, uint32_t type)
4722
98.3k
{
4723
98.3k
  const zend_frameless_function_info *frameless_function_info = find_frameless_function_info(args, fbc, type);
4724
98.3k
  if (!frameless_function_info) {
4725
96.0k
    return (uint32_t)-1;
4726
96.0k
  }
4727
4728
2.24k
  return zend_compile_frameless_icall_ex(result, args, fbc, frameless_function_info, type);
4729
98.3k
}
4730
4731
static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno, uint32_t type) /* {{{ */
4732
1.45M
{
4733
1.45M
  int name_constants = zend_add_ns_func_name_literal(Z_STR(name_node->u.constant));
4734
4735
  /* Find frameless function with same name. */
4736
1.45M
  zend_function *frameless_function = NULL;
4737
1.45M
  if (args_ast->kind != ZEND_AST_CALLABLE_CONVERT
4738
1.45M
   && !zend_args_contain_unpack_or_named(zend_ast_get_list(args_ast))
4739
   /* Avoid blowing up op count with nested frameless branches. */
4740
1.45M
   && !CG(context).in_jmp_frameless_branch) {
4741
955k
    zend_string *lc_func_name = Z_STR_P(CT_CONSTANT_EX(CG(active_op_array), name_constants + 2));
4742
955k
    frameless_function = zend_hash_find_ptr(CG(function_table), lc_func_name);
4743
955k
  }
4744
4745
  /* Check whether any frameless handler may actually be used. */
4746
1.45M
  uint32_t jmp_fl_opnum = 0;
4747
1.45M
  const zend_frameless_function_info *frameless_function_info = NULL;
4748
1.45M
  if (frameless_function) {
4749
264k
    frameless_function_info = find_frameless_function_info(zend_ast_get_list(args_ast), frameless_function, type);
4750
264k
    if (frameless_function_info) {
4751
256k
      CG(context).in_jmp_frameless_branch = true;
4752
256k
      znode op1;
4753
256k
      op1.op_type = IS_CONST;
4754
256k
      ZVAL_COPY(&op1.u.constant, CT_CONSTANT_EX(CG(active_op_array), name_constants + 1));
4755
256k
      jmp_fl_opnum = get_next_op_number();
4756
256k
      zend_emit_op(NULL, ZEND_JMP_FRAMELESS, &op1, NULL);
4757
256k
    }
4758
264k
  }
4759
4760
  /* Compile ns call. */
4761
1.45M
  zend_op *opline = get_next_op();
4762
1.45M
  opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
4763
1.45M
  opline->op2_type = IS_CONST;
4764
1.45M
  opline->op2.constant = name_constants;
4765
1.45M
  opline->result.num = zend_alloc_cache_slot();
4766
1.45M
  zend_compile_call_common(result, args_ast, NULL, lineno);
4767
4768
  /* Compile frameless call. */
4769
1.45M
  if (frameless_function_info) {
4770
256k
    CG(zend_lineno) = lineno;
4771
4772
256k
    uint32_t jmp_end_opnum = zend_emit_jump(0);
4773
256k
    uint32_t jmp_fl_target = get_next_op_number();
4774
4775
256k
    uint32_t flf_icall_opnum = zend_compile_frameless_icall_ex(NULL, zend_ast_get_list(args_ast), frameless_function, frameless_function_info, type);
4776
4777
256k
    zend_op *jmp_fl = &CG(active_op_array)->opcodes[jmp_fl_opnum];
4778
256k
    jmp_fl->op2.opline_num = jmp_fl_target;
4779
256k
    jmp_fl->extended_value = zend_alloc_cache_slot();
4780
256k
    zend_op *flf_icall = &CG(active_op_array)->opcodes[flf_icall_opnum];
4781
256k
    SET_NODE(flf_icall->result, result);
4782
256k
    zend_update_jump_target_to_next(jmp_end_opnum);
4783
4784
256k
    CG(context).in_jmp_frameless_branch = false;
4785
256k
  }
4786
1.45M
}
4787
/* }}} */
4788
4789
static zend_op *zend_compile_rope_add(znode *result, uint32_t num, znode *elem_node);
4790
static zend_op *zend_compile_rope_add_ex(zend_op *opline, znode *result, uint32_t num, znode *elem_node);
4791
static void zend_compile_rope_finalize(znode *result, uint32_t j, zend_op *init_opline, zend_op *opline);
4792
4793
static zend_result zend_compile_func_sprintf(znode *result, zend_ast_list *args) /* {{{ */
4794
1.80k
{
4795
  /* Bail out if we do not have a format string. */
4796
1.80k
  if (args->children < 1) {
4797
232
    return FAILURE;
4798
232
  }
4799
4800
1.57k
  zend_eval_const_expr(&args->child[0]);
4801
  /* Bail out if the format string is not constant. */
4802
1.57k
  if (args->child[0]->kind != ZEND_AST_ZVAL) {
4803
310
    return FAILURE;
4804
310
  }
4805
4806
1.26k
  zval *format_string = zend_ast_get_zval(args->child[0]);
4807
1.26k
  if (Z_TYPE_P(format_string) != IS_STRING) {
4808
67
    return FAILURE;
4809
67
  }
4810
1.19k
  if (Z_STRLEN_P(format_string) >= 256) {
4811
34
    return FAILURE;
4812
34
  }
4813
4814
1.15k
  char *p;
4815
1.15k
  char *end;
4816
1.15k
  uint32_t placeholder_count;
4817
4818
1.15k
  placeholder_count = 0;
4819
1.15k
  p = Z_STRVAL_P(format_string);
4820
1.15k
  end = p + Z_STRLEN_P(format_string);
4821
4822
3.05k
  for (;;) {
4823
3.05k
    p = memchr(p, '%', end - p);
4824
3.05k
    if (!p) {
4825
1.02k
      break;
4826
1.02k
    }
4827
4828
2.03k
    char *q = p + 1;
4829
2.03k
    if (q == end) {
4830
34
      return FAILURE;
4831
34
    }
4832
4833
2.00k
    switch (*q) {
4834
735
      case 's':
4835
943
      case 'd':
4836
943
        placeholder_count++;
4837
943
        break;
4838
957
      case '%':
4839
957
        break;
4840
101
      default:
4841
101
        return FAILURE;
4842
2.00k
    }
4843
4844
1.90k
    p = q;
4845
1.90k
    p++;
4846
1.90k
  }
4847
4848
  /* Bail out if the number of placeholders does not match the number of values. */
4849
1.02k
  if (placeholder_count != (args->children - 1)) {
4850
134
    return FAILURE;
4851
134
  }
4852
4853
  /* Handle empty format strings. */
4854
890
  if (Z_STRLEN_P(format_string) == 0) {
4855
66
    result->op_type = IS_CONST;
4856
66
    ZVAL_EMPTY_STRING(&result->u.constant);
4857
4858
66
    return SUCCESS;
4859
66
  }
4860
4861
824
  znode *elements = NULL;
4862
4863
824
  if (placeholder_count > 0) {
4864
435
    elements = safe_emalloc(sizeof(*elements), placeholder_count, 0);
4865
435
  }
4866
4867
  /* Compile the value expressions first for error handling that is consistent
4868
   * with a function call: Values that fail to convert to a string may emit errors.
4869
   */
4870
1.47k
  for (uint32_t i = 0; i < placeholder_count; i++) {
4871
648
    zend_compile_expr(elements + i, args->child[1 + i]);
4872
648
  }
4873
4874
824
  uint32_t rope_elements = 0;
4875
824
  uint32_t rope_init_lineno = -1;
4876
824
  zend_op *opline = NULL;
4877
4878
824
  placeholder_count = 0;
4879
824
  p = Z_STRVAL_P(format_string);
4880
824
  end = p + Z_STRLEN_P(format_string);
4881
824
  char *offset = p;
4882
2.19k
  for (;;) {
4883
2.19k
    p = memchr(p, '%', end - p);
4884
2.19k
    if (!p) {
4885
824
      break;
4886
824
    }
4887
4888
1.37k
    char *q = p + 1;
4889
1.37k
    ZEND_ASSERT(q < end);
4890
1.37k
    ZEND_ASSERT(*q == 's' || *q == 'd' || *q == '%');
4891
4892
1.37k
    if (*q == '%') {
4893
      /* Optimization to not create a dedicated rope element for the literal '%':
4894
       * Include the first '%' within the "constant" part instead of dropping the
4895
       * full placeholder.
4896
       */
4897
723
      p++;
4898
723
    }
4899
4900
1.37k
    if (p != offset) {
4901
889
      znode const_node;
4902
889
      const_node.op_type = IS_CONST;
4903
889
      ZVAL_STRINGL(&const_node.u.constant, offset, p - offset);
4904
889
      if (rope_elements == 0) {
4905
297
        rope_init_lineno = get_next_op_number();
4906
297
      }
4907
889
      opline = zend_compile_rope_add(result, rope_elements++, &const_node);
4908
889
    }
4909
4910
1.37k
    if (*q != '%') {
4911
648
      switch (*q) {
4912
443
        case 's':
4913
          /* Perform the cast of constants when actually evaluating the corresponding placeholder
4914
           * for correct error reporting.
4915
           */
4916
443
          if (elements[placeholder_count].op_type == IS_CONST) {
4917
194
            if (Z_TYPE(elements[placeholder_count].u.constant) == IS_ARRAY) {
4918
35
              zend_emit_op_tmp(&elements[placeholder_count], ZEND_CAST, &elements[placeholder_count], NULL)->extended_value = IS_STRING;
4919
159
            } else {
4920
159
              convert_to_string(&elements[placeholder_count].u.constant);
4921
159
            }
4922
194
          }
4923
443
          break;
4924
205
        case 'd':
4925
205
          zend_emit_op_tmp(&elements[placeholder_count], ZEND_CAST, &elements[placeholder_count], NULL)->extended_value = IS_LONG;
4926
205
          break;
4927
0
        EMPTY_SWITCH_DEFAULT_CASE();
4928
648
      }
4929
4930
648
      if (rope_elements == 0) {
4931
208
        rope_init_lineno = get_next_op_number();
4932
208
      }
4933
648
      opline = zend_compile_rope_add(result, rope_elements++, &elements[placeholder_count]);
4934
4935
648
      placeholder_count++;
4936
648
    }
4937
4938
1.37k
    p = q;
4939
1.37k
    p++;
4940
1.37k
    offset = p;
4941
1.37k
  }
4942
824
  if (end != offset) {
4943
    /* Add the constant part after the last placeholder. */
4944
471
    znode const_node;
4945
471
    const_node.op_type = IS_CONST;
4946
471
    ZVAL_STRINGL(&const_node.u.constant, offset, end - offset);
4947
471
    if (rope_elements == 0) {
4948
319
      rope_init_lineno = get_next_op_number();
4949
319
    }
4950
471
    opline = zend_compile_rope_add(result, rope_elements++, &const_node);
4951
471
  }
4952
824
  ZEND_ASSERT(opline != NULL);
4953
4954
824
  zend_op *init_opline = CG(active_op_array)->opcodes + rope_init_lineno;
4955
824
  zend_compile_rope_finalize(result, rope_elements, init_opline, opline);
4956
824
  efree(elements);
4957
4958
824
  return SUCCESS;
4959
824
}
4960
4961
static zend_result zend_compile_func_clone(znode *result, zend_ast_list *args)
4962
1.90k
{
4963
1.90k
  znode arg_node;
4964
4965
1.90k
  if (args->children != 1) {
4966
320
    return FAILURE;
4967
320
  }
4968
4969
1.58k
  zend_compile_expr(&arg_node, args->child[0]);
4970
1.58k
  zend_emit_op_tmp(result, ZEND_CLONE, &arg_node, NULL);
4971
4972
1.58k
  return SUCCESS;
4973
1.90k
}
4974
4975
static zend_result zend_try_compile_special_func_ex(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */
4976
115k
{
4977
115k
  if (zend_string_equals_literal(lcname, "strlen")) {
4978
839
    return zend_compile_func_strlen(result, args);
4979
114k
  } else if (zend_string_equals_literal(lcname, "is_null")) {
4980
81
    return zend_compile_func_typecheck(result, args, IS_NULL);
4981
114k
  } else if (zend_string_equals_literal(lcname, "is_bool")) {
4982
81
    return zend_compile_func_typecheck(result, args, _IS_BOOL);
4983
114k
  } else if (zend_string_equals_literal(lcname, "is_long")
4984
113k
    || zend_string_equals_literal(lcname, "is_int")
4985
113k
    || zend_string_equals_literal(lcname, "is_integer")
4986
114k
  ) {
4987
378
    return zend_compile_func_typecheck(result, args, IS_LONG);
4988
113k
  } else if (zend_string_equals_literal(lcname, "is_float")
4989
113k
    || zend_string_equals_literal(lcname, "is_double")
4990
113k
  ) {
4991
704
    return zend_compile_func_typecheck(result, args, IS_DOUBLE);
4992
112k
  } else if (zend_string_equals_literal(lcname, "is_string")) {
4993
31
    return zend_compile_func_typecheck(result, args, IS_STRING);
4994
112k
  } else if (zend_string_equals_literal(lcname, "is_array")) {
4995
233
    return zend_compile_func_typecheck(result, args, IS_ARRAY);
4996
112k
  } else if (zend_string_equals_literal(lcname, "is_object")) {
4997
101
    return zend_compile_func_typecheck(result, args, IS_OBJECT);
4998
112k
  } else if (zend_string_equals_literal(lcname, "is_resource")) {
4999
46
    return zend_compile_func_typecheck(result, args, IS_RESOURCE);
5000
112k
  } else if (zend_string_equals_literal(lcname, "is_scalar")) {
5001
91
    return zend_compile_func_is_scalar(result, args);
5002
112k
  } else if (zend_string_equals_literal(lcname, "boolval")) {
5003
29
    return zend_compile_func_cast(result, args, _IS_BOOL);
5004
112k
  } else if (zend_string_equals_literal(lcname, "intval")) {
5005
156
    return zend_compile_func_cast(result, args, IS_LONG);
5006
112k
  } else if (zend_string_equals_literal(lcname, "floatval")
5007
111k
    || zend_string_equals_literal(lcname, "doubleval")
5008
112k
  ) {
5009
455
    return zend_compile_func_cast(result, args, IS_DOUBLE);
5010
111k
  } else if (zend_string_equals_literal(lcname, "strval")) {
5011
180
    return zend_compile_func_cast(result, args, IS_STRING);
5012
111k
  } else if (zend_string_equals_literal(lcname, "defined")) {
5013
1.06k
    return zend_compile_func_defined(result, args);
5014
110k
  } else if (zend_string_equals_literal(lcname, "chr") && type == BP_VAR_R) {
5015
776
    return zend_compile_func_chr(result, args);
5016
109k
  } else if (zend_string_equals_literal(lcname, "ord") && type == BP_VAR_R) {
5017
623
    return zend_compile_func_ord(result, args);
5018
109k
  } else if (zend_string_equals_literal(lcname, "call_user_func_array")) {
5019
2.20k
    return zend_compile_func_cufa(result, args, lcname);
5020
106k
  } else if (zend_string_equals_literal(lcname, "call_user_func")) {
5021
2.55k
    return zend_compile_func_cuf(result, args, lcname);
5022
104k
  } else if (zend_string_equals_literal(lcname, "in_array")) {
5023
3.97k
    return zend_compile_func_in_array(result, args);
5024
100k
  } else if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_COUNT))
5025
99.5k
      || zend_string_equals_literal(lcname, "sizeof")) {
5026
1.17k
    return zend_compile_func_count(result, args, lcname);
5027
99.2k
  } else if (zend_string_equals_literal(lcname, "get_class")) {
5028
1.07k
    return zend_compile_func_get_class(result, args);
5029
98.1k
  } else if (zend_string_equals_literal(lcname, "get_called_class")) {
5030
396
    return zend_compile_func_get_called_class(result, args);
5031
97.7k
  } else if (zend_string_equals_literal(lcname, "gettype")) {
5032
768
    return zend_compile_func_gettype(result, args);
5033
97.0k
  } else if (zend_string_equals_literal(lcname, "func_num_args")) {
5034
142
    return zend_compile_func_num_args(result, args);
5035
96.8k
  } else if (zend_string_equals_literal(lcname, "func_get_args")) {
5036
567
    return zend_compile_func_get_args(result, args);
5037
96.2k
  } else if (zend_string_equals_literal(lcname, "array_slice")) {
5038
1.50k
    return zend_compile_func_array_slice(result, args);
5039
94.7k
  } else if (zend_string_equals_literal(lcname, "array_key_exists")) {
5040
355
    return zend_compile_func_array_key_exists(result, args);
5041
94.4k
  } else if (zend_string_equals_literal(lcname, "sprintf")) {
5042
1.80k
    return zend_compile_func_sprintf(result, args);
5043
92.6k
  } else if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_CLONE))) {
5044
1.90k
    return zend_compile_func_clone(result, args);
5045
90.7k
  } else {
5046
90.7k
    return FAILURE;
5047
90.7k
  }
5048
115k
}
5049
5050
static zend_result zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */
5051
137k
{
5052
137k
  if (CG(compiler_options) & ZEND_COMPILE_NO_BUILTINS) {
5053
0
    return FAILURE;
5054
0
  }
5055
5056
137k
  if (fbc->type != ZEND_INTERNAL_FUNCTION) {
5057
    /* If the function is part of disabled_functions, it may be redeclared as a userland
5058
     * function with a different implementation. Don't use the VM builtin in that case. */
5059
21.0k
    return FAILURE;
5060
21.0k
  }
5061
5062
116k
  if (zend_args_contain_unpack_or_named(args)) {
5063
1.63k
    return FAILURE;
5064
1.63k
  }
5065
5066
115k
  if (zend_try_compile_special_func_ex(result, lcname, args, fbc, type) == SUCCESS) {
5067
16.6k
    return SUCCESS;
5068
16.6k
  }
5069
5070
98.3k
  return zend_compile_frameless_icall(result, args, fbc, type) != (uint32_t)-1 ? SUCCESS : FAILURE;
5071
115k
}
5072
5073
8
static const char *zend_get_cstring_from_property_hook_kind(zend_property_hook_kind kind) {
5074
8
  switch (kind) {
5075
1
    case ZEND_PROPERTY_HOOK_GET:
5076
1
      return "get";
5077
7
    case ZEND_PROPERTY_HOOK_SET:
5078
7
      return "set";
5079
8
    EMPTY_SWITCH_DEFAULT_CASE()
5080
8
  }
5081
8
}
5082
5083
static zend_string *zend_copy_unmangled_prop_name(zend_string *prop_name)
5084
641
{
5085
641
  if (ZSTR_VAL(prop_name)[0] != '\0') {
5086
476
    return zend_string_copy(prop_name);
5087
476
  } else {
5088
165
    const char *unmangled = zend_get_unmangled_property_name(prop_name);
5089
165
    return zend_string_init(unmangled, strlen(unmangled), /* persistent */ false);
5090
165
  }
5091
641
}
5092
5093
static bool zend_compile_parent_property_hook_call(znode *result, zend_ast *ast, uint32_t type)
5094
28.9k
{
5095
28.9k
  ZEND_ASSERT(ast->kind == ZEND_AST_STATIC_CALL);
5096
5097
28.9k
  zend_ast *class_ast = ast->child[0];
5098
28.9k
  zend_ast *method_ast = ast->child[1];
5099
5100
  /* Recognize parent::$prop::get() pattern. */
5101
28.9k
  if (class_ast->kind != ZEND_AST_STATIC_PROP
5102
2.39k
   || (class_ast->attr & ZEND_PARENTHESIZED_STATIC_PROP)
5103
2.14k
   || class_ast->child[0]->kind != ZEND_AST_ZVAL
5104
1.90k
   || Z_TYPE_P(zend_ast_get_zval(class_ast->child[0])) != IS_STRING
5105
1.90k
   || zend_get_class_fetch_type(zend_ast_get_str(class_ast->child[0])) != ZEND_FETCH_CLASS_PARENT
5106
1.54k
   || class_ast->child[1]->kind != ZEND_AST_ZVAL
5107
1.25k
   || method_ast->kind != ZEND_AST_ZVAL
5108
1.14k
   || Z_TYPE_P(zend_ast_get_zval(method_ast)) != IS_STRING
5109
1.14k
   || (!zend_string_equals_literal_ci(zend_ast_get_str(method_ast), "get")
5110
28.2k
    && !zend_string_equals_literal_ci(zend_ast_get_str(method_ast), "set"))) {
5111
28.2k
    return false;
5112
28.2k
  }
5113
5114
689
  zend_class_entry *ce = CG(active_class_entry);
5115
689
  if (!ce) {
5116
8
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"parent\" when no class scope is active");
5117
8
  }
5118
5119
681
  zend_ast *args_ast = ast->child[2];
5120
681
  if (args_ast->kind == ZEND_AST_CALLABLE_CONVERT) {
5121
6
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot create Closure for parent property hook call");
5122
6
  }
5123
5124
675
  zval *property_hook_name_zv = zend_ast_get_zval(class_ast->child[1]);
5125
675
  zend_string *property_name = zval_get_string(property_hook_name_zv);
5126
675
  zend_string *hook_name = zend_ast_get_str(method_ast);
5127
675
  zend_property_hook_kind hook_kind = zend_get_property_hook_kind_from_name(hook_name);
5128
675
  ZEND_ASSERT(hook_kind != (uint32_t)-1);
5129
5130
675
  const zend_string *prop_info_name = CG(context).active_property_info_name;
5131
675
  if (!prop_info_name) {
5132
7
    zend_error_noreturn(E_COMPILE_ERROR, "Must not use parent::$%s::%s() outside a property hook",
5133
7
      ZSTR_VAL(property_name), ZSTR_VAL(hook_name));
5134
7
  }
5135
5136
668
  const char *unmangled_prop_name = zend_get_unmangled_property_name(prop_info_name);
5137
668
  if (!zend_string_equals_cstr(property_name, unmangled_prop_name, strlen(unmangled_prop_name))) {
5138
23
    zend_error_noreturn(E_COMPILE_ERROR, "Must not use parent::$%s::%s() in a different property ($%s)",
5139
23
      ZSTR_VAL(property_name), ZSTR_VAL(hook_name), unmangled_prop_name);
5140
23
  }
5141
645
  if (hook_kind != CG(context).active_property_hook_kind) {
5142
8
    zend_error_noreturn(E_COMPILE_ERROR, "Must not use parent::$%s::%s() in a different property hook (%s)",
5143
8
      ZSTR_VAL(property_name), ZSTR_VAL(hook_name), zend_get_cstring_from_property_hook_kind(CG(context).active_property_hook_kind));
5144
8
  }
5145
5146
637
  zend_op *opline = get_next_op();
5147
637
  opline->opcode = ZEND_INIT_PARENT_PROPERTY_HOOK_CALL;
5148
637
  opline->op1_type = IS_CONST;
5149
637
  opline->op1.constant = zend_add_literal_string(&property_name);
5150
637
  opline->op2.num = hook_kind;
5151
5152
637
  zend_function *fbc = NULL;
5153
637
  zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast));
5154
5155
637
  return true;
5156
645
}
5157
5158
static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
5159
1.81M
{
5160
1.81M
  zend_ast *name_ast = ast->child[0];
5161
1.81M
  zend_ast *args_ast = ast->child[1];
5162
1.81M
  bool is_callable_convert = args_ast->kind == ZEND_AST_CALLABLE_CONVERT;
5163
5164
1.81M
  znode name_node;
5165
5166
1.81M
  if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
5167
101k
    zend_compile_expr(&name_node, name_ast);
5168
101k
    zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno);
5169
101k
    return;
5170
101k
  }
5171
5172
1.70M
  {
5173
1.70M
    bool runtime_resolution = zend_compile_function_name(&name_node, name_ast);
5174
1.70M
    if (runtime_resolution) {
5175
1.46M
      if (zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "assert")
5176
3.03k
          && !is_callable_convert) {
5177
2.09k
        zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL, ast->lineno);
5178
1.45M
      } else {
5179
1.45M
        zend_compile_ns_call(result, &name_node, args_ast, ast->lineno, type);
5180
1.45M
      }
5181
1.46M
      return;
5182
1.46M
    }
5183
1.70M
  }
5184
5185
248k
  {
5186
248k
    zval *name = &name_node.u.constant;
5187
248k
    zend_string *lcname;
5188
248k
    zend_function *fbc;
5189
248k
    zend_op *opline;
5190
5191
248k
    lcname = zend_string_tolower(Z_STR_P(name));
5192
248k
    zval *fbc_zv = zend_hash_find(CG(function_table), lcname);
5193
248k
    fbc = fbc_zv ? Z_PTR_P(fbc_zv) : NULL;
5194
5195
    /* Special assert() handling should apply independently of compiler flags. */
5196
248k
    if (fbc && zend_string_equals_literal(lcname, "assert") && !is_callable_convert) {
5197
20.6k
      zend_compile_assert(result, zend_ast_get_list(args_ast), lcname, fbc, ast->lineno);
5198
20.6k
      zend_string_release(lcname);
5199
20.6k
      zval_ptr_dtor(&name_node.u.constant);
5200
20.6k
      return;
5201
20.6k
    }
5202
5203
228k
    if (!fbc
5204
138k
     || !fbc_is_finalized(fbc)
5205
138k
     || zend_compile_ignore_function(fbc, CG(active_op_array)->filename)) {
5206
89.7k
      zend_string_release_ex(lcname, 0);
5207
89.7k
      zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno);
5208
89.7k
      return;
5209
89.7k
    }
5210
5211
138k
    if (!is_callable_convert &&
5212
137k
        zend_try_compile_special_func(result, lcname,
5213
137k
        zend_ast_get_list(args_ast), fbc, type) == SUCCESS
5214
138k
    ) {
5215
18.9k
      zend_string_release_ex(lcname, 0);
5216
18.9k
      zval_ptr_dtor(&name_node.u.constant);
5217
18.9k
      return;
5218
18.9k
    }
5219
5220
119k
    zval_ptr_dtor(&name_node.u.constant);
5221
119k
    ZVAL_NEW_STR(&name_node.u.constant, lcname);
5222
5223
119k
    opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
5224
119k
    opline->result.num = zend_alloc_cache_slot();
5225
5226
    /* Store offset to function from symbol table in op2.extra. */
5227
119k
    if (fbc->type == ZEND_INTERNAL_FUNCTION) {
5228
98.3k
      Bucket *fbc_bucket = (Bucket*)((uintptr_t)fbc_zv - XtOffsetOf(Bucket, val));
5229
98.3k
      Z_EXTRA_P(CT_CONSTANT(opline->op2)) = fbc_bucket - CG(function_table)->arData;
5230
98.3k
    }
5231
5232
119k
    zend_compile_call_common(result, args_ast, fbc, ast->lineno);
5233
119k
  }
5234
119k
}
5235
/* }}} */
5236
5237
static void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
5238
63.9k
{
5239
63.9k
  zend_ast *obj_ast = ast->child[0];
5240
63.9k
  zend_ast *method_ast = ast->child[1];
5241
63.9k
  zend_ast *args_ast = ast->child[2];
5242
5243
63.9k
  znode obj_node, method_node;
5244
63.9k
  zend_op *opline;
5245
63.9k
  zend_function *fbc = NULL;
5246
63.9k
  bool nullsafe = ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL;
5247
63.9k
  uint32_t short_circuiting_checkpoint = zend_short_circuiting_checkpoint();
5248
5249
63.9k
  if (is_this_fetch(obj_ast)) {
5250
1.92k
    if (this_guaranteed_exists()) {
5251
1.74k
      obj_node.op_type = IS_UNUSED;
5252
1.74k
    } else {
5253
175
      zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL);
5254
175
    }
5255
1.92k
    CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
5256
5257
    /* We will throw if $this doesn't exist, so there's no need to emit a JMP_NULL
5258
     * check for a nullsafe access. */
5259
62.0k
  } else {
5260
62.0k
    zend_short_circuiting_mark_inner(obj_ast);
5261
62.0k
    zend_compile_expr(&obj_node, obj_ast);
5262
62.0k
    if (nullsafe) {
5263
2.58k
      zend_emit_jmp_null(&obj_node, type);
5264
2.58k
    }
5265
62.0k
  }
5266
5267
63.9k
  zend_compile_expr(&method_node, method_ast);
5268
63.9k
  opline = zend_emit_op(NULL, ZEND_INIT_METHOD_CALL, &obj_node, NULL);
5269
5270
63.9k
  if (method_node.op_type == IS_CONST) {
5271
63.3k
    if (Z_TYPE(method_node.u.constant) != IS_STRING) {
5272
10
      zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
5273
10
    }
5274
5275
63.3k
    opline->op2_type = IS_CONST;
5276
63.3k
    opline->op2.constant = zend_add_func_name_literal(
5277
63.3k
      Z_STR(method_node.u.constant));
5278
63.3k
    opline->result.num = zend_alloc_cache_slots(2);
5279
63.3k
  } else {
5280
674
    SET_NODE(opline->op2, &method_node);
5281
674
  }
5282
5283
  /* Check if this calls a known method on $this */
5284
63.9k
  if (opline->op1_type == IS_UNUSED && opline->op2_type == IS_CONST &&
5285
1.70k
      CG(active_class_entry) && zend_is_scope_known()) {
5286
1.59k
    zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op2) + 1);
5287
1.59k
    fbc = zend_hash_find_ptr(&CG(active_class_entry)->function_table, lcname);
5288
5289
    /* We only know the exact method that is being called if it is either private or final.
5290
     * Otherwise an overriding method in a child class may be called. */
5291
1.59k
    if (fbc && !(fbc->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_FINAL))) {
5292
299
      fbc = NULL;
5293
299
    }
5294
1.59k
  }
5295
5296
63.9k
  if (zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast))) {
5297
519
    if (short_circuiting_checkpoint != zend_short_circuiting_checkpoint()) {
5298
17
      zend_error_noreturn(E_COMPILE_ERROR,
5299
17
        "Cannot combine nullsafe operator with Closure creation");
5300
17
    }
5301
519
  }
5302
63.9k
}
5303
/* }}} */
5304
5305
static bool zend_is_constructor(zend_string *name) /* {{{ */
5306
27.6k
{
5307
27.6k
  return zend_string_equals_literal_ci(name, ZEND_CONSTRUCTOR_FUNC_NAME);
5308
27.6k
}
5309
/* }}} */
5310
5311
static zend_function *zend_get_compatible_func_or_null(zend_class_entry *ce, zend_string *lcname) /* {{{ */
5312
5.16k
{
5313
5.16k
  zend_function *fbc = zend_hash_find_ptr(&ce->function_table, lcname);
5314
5.16k
  if (!fbc || (fbc->common.fn_flags & ZEND_ACC_PUBLIC) || ce == CG(active_class_entry)) {
5315
4.91k
    return fbc;
5316
4.91k
  }
5317
5318
249
  if (!(fbc->common.fn_flags & ZEND_ACC_PRIVATE)
5319
125
    && (fbc->common.scope->ce_flags & ZEND_ACC_LINKED)
5320
125
    && (!CG(active_class_entry) || (CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED))
5321
19
    && zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry))) {
5322
0
    return fbc;
5323
0
  }
5324
5325
249
  return NULL;
5326
249
}
5327
/* }}} */
5328
5329
static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
5330
28.9k
{
5331
28.9k
  zend_ast *class_ast = ast->child[0];
5332
28.9k
  zend_ast *method_ast = ast->child[1];
5333
28.9k
  zend_ast *args_ast = ast->child[2];
5334
5335
28.9k
  znode class_node, method_node;
5336
28.9k
  zend_op *opline;
5337
28.9k
  zend_function *fbc = NULL;
5338
5339
28.9k
  if (zend_compile_parent_property_hook_call(result, ast, type)) {
5340
637
    return;
5341
637
  }
5342
5343
28.2k
  zend_short_circuiting_mark_inner(class_ast);
5344
28.2k
  zend_compile_class_ref(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
5345
5346
28.2k
  zend_compile_expr(&method_node, method_ast);
5347
5348
28.2k
  if (method_node.op_type == IS_CONST) {
5349
26.5k
    zval *name = &method_node.u.constant;
5350
26.5k
    if (Z_TYPE_P(name) != IS_STRING) {
5351
3
      zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
5352
3
    }
5353
26.5k
    if (zend_is_constructor(Z_STR_P(name))) {
5354
181
      zval_ptr_dtor(name);
5355
181
      method_node.op_type = IS_UNUSED;
5356
181
    }
5357
26.5k
  }
5358
5359
28.2k
  opline = get_next_op();
5360
28.2k
  opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
5361
5362
28.2k
  zend_set_class_name_op1(opline, &class_node);
5363
5364
28.2k
  if (method_node.op_type == IS_CONST) {
5365
26.3k
    opline->op2_type = IS_CONST;
5366
26.3k
    opline->op2.constant = zend_add_func_name_literal(
5367
26.3k
      Z_STR(method_node.u.constant));
5368
26.3k
    opline->result.num = zend_alloc_cache_slots(2);
5369
26.3k
  } else {
5370
1.93k
    if (opline->op1_type == IS_CONST) {
5371
624
      opline->result.num = zend_alloc_cache_slot();
5372
624
    }
5373
1.93k
    SET_NODE(opline->op2, &method_node);
5374
1.93k
  }
5375
5376
  /* Check if we already know which method we're calling */
5377
28.2k
  if (opline->op2_type == IS_CONST) {
5378
26.3k
    zend_class_entry *ce = NULL;
5379
26.3k
    if (opline->op1_type == IS_CONST) {
5380
12.3k
      zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op1) + 1);
5381
12.3k
      ce = zend_hash_find_ptr(CG(class_table), lcname);
5382
12.3k
      if (ce) {
5383
4.58k
        if (zend_compile_ignore_class(ce, CG(active_op_array)->filename)) {
5384
0
          ce = NULL;
5385
0
        }
5386
7.76k
      } else if (CG(active_class_entry)
5387
685
          && zend_string_equals_ci(CG(active_class_entry)->name, lcname)) {
5388
203
        ce = CG(active_class_entry);
5389
203
      }
5390
14.0k
    } else if (opline->op1_type == IS_UNUSED
5391
1.31k
        && (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF
5392
822
        && zend_is_scope_known()) {
5393
374
      ce = CG(active_class_entry);
5394
374
    }
5395
26.3k
    if (ce) {
5396
5.16k
      zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op2) + 1);
5397
5.16k
      fbc = zend_get_compatible_func_or_null(ce, lcname);
5398
5.16k
    }
5399
26.3k
  }
5400
5401
28.2k
  zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast));
5402
28.2k
}
5403
/* }}} */
5404
5405
static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel);
5406
5407
static void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
5408
72.2k
{
5409
72.2k
  zend_ast *class_ast = ast->child[0];
5410
72.2k
  zend_ast *args_ast = ast->child[1];
5411
5412
72.2k
  znode class_node, ctor_result;
5413
72.2k
  zend_op *opline;
5414
5415
72.2k
  if (class_ast->kind == ZEND_AST_CLASS) {
5416
    /* anon class declaration */
5417
2.17k
    zend_compile_class_decl(&class_node, class_ast, false);
5418
70.0k
  } else {
5419
70.0k
    zend_compile_class_ref(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
5420
70.0k
  }
5421
5422
72.2k
  opline = zend_emit_op(result, ZEND_NEW, NULL, NULL);
5423
5424
72.2k
  if (class_node.op_type == IS_CONST) {
5425
68.9k
    opline->op1_type = IS_CONST;
5426
68.9k
    opline->op1.constant = zend_add_class_name_literal(
5427
68.9k
      Z_STR(class_node.u.constant));
5428
68.9k
    opline->op2.num = zend_alloc_cache_slot();
5429
68.9k
  } else {
5430
3.32k
    SET_NODE(opline->op1, &class_node);
5431
3.32k
  }
5432
5433
72.2k
  zend_compile_call_common(&ctor_result, args_ast, NULL, ast->lineno);
5434
72.2k
  zend_do_free(&ctor_result);
5435
72.2k
}
5436
/* }}} */
5437
5438
static void zend_compile_global_var(zend_ast *ast) /* {{{ */
5439
2.13k
{
5440
2.13k
  zend_ast *var_ast = ast->child[0];
5441
2.13k
  zend_ast *name_ast = var_ast->child[0];
5442
5443
2.13k
  znode name_node, result;
5444
5445
2.13k
  zend_compile_expr(&name_node, name_ast);
5446
2.13k
  if (name_node.op_type == IS_CONST) {
5447
1.93k
    convert_to_string(&name_node.u.constant);
5448
1.93k
  }
5449
5450
  // TODO(GLOBALS) Forbid "global $GLOBALS"?
5451
2.13k
  if (is_this_fetch(var_ast)) {
5452
7
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as global variable");
5453
2.13k
  } else if (zend_try_compile_cv(&result, var_ast, BP_VAR_R) == SUCCESS) {
5454
1.74k
    zend_op *opline = zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node);
5455
1.74k
    opline->extended_value = zend_alloc_cache_slot();
5456
1.74k
  } else {
5457
    /* name_ast should be evaluated only. FETCH_GLOBAL_LOCK instructs FETCH_W
5458
     * to not free the name_node operand, so it can be reused in the following
5459
     * ASSIGN_REF, which then frees it. */
5460
387
    zend_op *opline = zend_emit_op(&result, ZEND_FETCH_W, &name_node, NULL);
5461
387
    opline->extended_value = ZEND_FETCH_GLOBAL_LOCK;
5462
5463
387
    if (name_node.op_type == IS_CONST) {
5464
181
      zend_string_addref(Z_STR(name_node.u.constant));
5465
181
    }
5466
5467
387
    zend_emit_assign_ref_znode(
5468
387
      zend_ast_create(ZEND_AST_VAR, zend_ast_create_znode(&name_node)),
5469
387
      &result
5470
387
    );
5471
387
  }
5472
2.13k
}
5473
/* }}} */
5474
5475
static void zend_compile_static_var_common(zend_string *var_name, zval *value, uint32_t mode) /* {{{ */
5476
110k
{
5477
110k
  zend_op *opline;
5478
110k
  if (!CG(active_op_array)->static_variables) {
5479
0
    if (CG(active_op_array)->scope) {
5480
0
      CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
5481
0
    }
5482
0
    CG(active_op_array)->static_variables = zend_new_array(8);
5483
0
  }
5484
5485
110k
  value = zend_hash_update(CG(active_op_array)->static_variables, var_name, value);
5486
5487
110k
  if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) {
5488
0
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as static variable");
5489
0
  }
5490
5491
110k
  opline = zend_emit_op(NULL, ZEND_BIND_STATIC, NULL, NULL);
5492
110k
  opline->op1_type = IS_CV;
5493
110k
  opline->op1.var = lookup_cv(var_name);
5494
110k
  opline->extended_value = (uint32_t)((char*)value - (char*)CG(active_op_array)->static_variables->arData) | mode;
5495
110k
}
5496
/* }}} */
5497
5498
static void zend_compile_static_var(zend_ast *ast) /* {{{ */
5499
1.48k
{
5500
1.48k
  zend_ast *var_ast = ast->child[0];
5501
1.48k
  zend_string *var_name = zend_ast_get_str(var_ast);
5502
5503
1.48k
  if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) {
5504
7
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as static variable");
5505
7
  }
5506
5507
1.48k
  if (!CG(active_op_array)->static_variables) {
5508
1.09k
    if (CG(active_op_array)->scope) {
5509
290
      CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
5510
290
    }
5511
1.09k
    CG(active_op_array)->static_variables = zend_new_array(8);
5512
1.09k
  }
5513
5514
1.48k
  if (zend_hash_exists(CG(active_op_array)->static_variables, var_name)) {
5515
23
    zend_error_noreturn_unchecked(E_COMPILE_ERROR, "Duplicate declaration of static variable $%S", var_name);
5516
23
  }
5517
5518
1.45k
  zend_eval_const_expr(&ast->child[1]);
5519
1.45k
  zend_ast *value_ast = ast->child[1];
5520
5521
1.45k
  if (!value_ast || value_ast->kind == ZEND_AST_ZVAL) {
5522
1.01k
    zval *value_zv = value_ast
5523
1.01k
      ? zend_ast_get_zval(value_ast)
5524
1.01k
      : &EG(uninitialized_zval);
5525
1.01k
    Z_TRY_ADDREF_P(value_zv);
5526
1.01k
    zend_compile_static_var_common(var_name, value_zv, ZEND_BIND_REF);
5527
1.01k
  } else {
5528
443
    zend_op *opline;
5529
5530
443
    zval *placeholder_ptr = zend_hash_update(CG(active_op_array)->static_variables, var_name, &EG(uninitialized_zval));
5531
443
    uint32_t placeholder_offset = (uint32_t)((char*)placeholder_ptr - (char*)CG(active_op_array)->static_variables->arData);
5532
5533
443
    uint32_t static_def_jmp_opnum = get_next_op_number();
5534
443
    opline = zend_emit_op(NULL, ZEND_BIND_INIT_STATIC_OR_JMP, NULL, NULL);
5535
443
    opline->op1_type = IS_CV;
5536
443
    opline->op1.var = lookup_cv(var_name);
5537
443
    opline->extended_value = placeholder_offset;
5538
5539
443
    znode expr;
5540
443
    zend_compile_expr(&expr, value_ast);
5541
5542
443
    opline = zend_emit_op(NULL, ZEND_BIND_STATIC, NULL, &expr);
5543
443
    opline->op1_type = IS_CV;
5544
443
    opline->op1.var = lookup_cv(var_name);
5545
443
    opline->extended_value = placeholder_offset | ZEND_BIND_REF;
5546
5547
443
    zend_update_jump_target_to_next(static_def_jmp_opnum);
5548
443
  }
5549
1.45k
}
5550
/* }}} */
5551
5552
static void zend_compile_unset(zend_ast *ast) /* {{{ */
5553
8.49k
{
5554
8.49k
  zend_ast *var_ast = ast->child[0];
5555
8.49k
  znode var_node;
5556
8.49k
  zend_op *opline;
5557
5558
8.49k
  zend_ensure_writable_variable(var_ast);
5559
5560
8.49k
  if (is_global_var_fetch(var_ast)) {
5561
1.70k
    if (!var_ast->child[1]) {
5562
7
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting");
5563
7
    }
5564
5565
1.69k
    zend_compile_expr(&var_node, var_ast->child[1]);
5566
1.69k
    if (var_node.op_type == IS_CONST) {
5567
1.62k
      convert_to_string(&var_node.u.constant);
5568
1.62k
    }
5569
5570
1.69k
    opline = zend_emit_op(NULL, ZEND_UNSET_VAR, &var_node, NULL);
5571
1.69k
    opline->extended_value = ZEND_FETCH_GLOBAL;
5572
1.69k
    return;
5573
1.70k
  }
5574
5575
6.79k
  switch (var_ast->kind) {
5576
3.65k
    case ZEND_AST_VAR:
5577
3.65k
      if (is_this_fetch(var_ast)) {
5578
10
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot unset $this");
5579
3.64k
      } else if (zend_try_compile_cv(&var_node, var_ast, BP_VAR_UNSET) == SUCCESS) {
5580
3.41k
        opline = zend_emit_op(NULL, ZEND_UNSET_CV, &var_node, NULL);
5581
3.41k
      } else {
5582
227
        opline = zend_compile_simple_var_no_cv(NULL, var_ast, BP_VAR_UNSET, false);
5583
227
        opline->opcode = ZEND_UNSET_VAR;
5584
227
      }
5585
3.64k
      return;
5586
3.64k
    case ZEND_AST_DIM:
5587
1.68k
      opline = zend_compile_dim(NULL, var_ast, BP_VAR_UNSET, /* by_ref */ false);
5588
1.68k
      opline->opcode = ZEND_UNSET_DIM;
5589
1.68k
      return;
5590
1.38k
    case ZEND_AST_PROP:
5591
1.38k
    case ZEND_AST_NULLSAFE_PROP:
5592
1.38k
      opline = zend_compile_prop(NULL, var_ast, BP_VAR_UNSET, false);
5593
1.38k
      opline->opcode = ZEND_UNSET_OBJ;
5594
1.38k
      return;
5595
59
    case ZEND_AST_STATIC_PROP:
5596
59
      opline = zend_compile_static_prop(NULL, var_ast, BP_VAR_UNSET, false, false);
5597
59
      opline->opcode = ZEND_UNSET_STATIC_PROP;
5598
59
      return;
5599
6.79k
    EMPTY_SWITCH_DEFAULT_CASE()
5600
6.79k
  }
5601
6.79k
}
5602
/* }}} */
5603
5604
static bool zend_handle_loops_and_finally_ex(zend_long depth, znode *return_value) /* {{{ */
5605
43.6k
{
5606
43.6k
  zend_loop_var *base;
5607
43.6k
  zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack));
5608
5609
43.6k
  if (!loop_var) {
5610
1.24k
    return 1;
5611
1.24k
  }
5612
42.4k
  base = zend_stack_base(&CG(loop_var_stack));
5613
52.6k
  for (; loop_var >= base; loop_var--) {
5614
49.9k
    if (loop_var->opcode == ZEND_FAST_CALL) {
5615
5.17k
      zend_op *opline = get_next_op();
5616
5617
5.17k
      opline->opcode = ZEND_FAST_CALL;
5618
5.17k
      opline->result_type = IS_TMP_VAR;
5619
5.17k
      opline->result.var = loop_var->var_num;
5620
5.17k
      if (return_value) {
5621
2.11k
        SET_NODE(opline->op2, return_value);
5622
2.11k
      }
5623
5.17k
      opline->op1.num = loop_var->try_catch_offset;
5624
44.7k
    } else if (loop_var->opcode == ZEND_DISCARD_EXCEPTION) {
5625
2.33k
      zend_op *opline = get_next_op();
5626
2.33k
      opline->opcode = ZEND_DISCARD_EXCEPTION;
5627
2.33k
      opline->op1_type = IS_TMP_VAR;
5628
2.33k
      opline->op1.var = loop_var->var_num;
5629
42.4k
    } else if (loop_var->opcode == ZEND_RETURN) {
5630
      /* Stack separator */
5631
38.0k
      break;
5632
38.0k
    } else if (depth <= 1) {
5633
1.68k
      return 1;
5634
2.69k
    } else if (loop_var->opcode == ZEND_NOP) {
5635
      /* Loop doesn't have freeable variable */
5636
1.71k
      depth--;
5637
1.71k
    } else {
5638
985
      zend_op *opline;
5639
5640
985
      ZEND_ASSERT(loop_var->var_type & (IS_VAR|IS_TMP_VAR));
5641
985
      opline = get_next_op();
5642
985
      opline->opcode = loop_var->opcode;
5643
985
      opline->op1_type = loop_var->var_type;
5644
985
      opline->op1.var = loop_var->var_num;
5645
985
      opline->extended_value = ZEND_FREE_ON_RETURN;
5646
985
      depth--;
5647
985
      }
5648
49.9k
  }
5649
40.7k
  return (depth == 0);
5650
42.4k
}
5651
/* }}} */
5652
5653
static bool zend_handle_loops_and_finally(znode *return_value) /* {{{ */
5654
41.9k
{
5655
41.9k
  return zend_handle_loops_and_finally_ex(zend_stack_count(&CG(loop_var_stack)) + 1, return_value);
5656
41.9k
}
5657
/* }}} */
5658
5659
static bool zend_has_finally_ex(zend_long depth) /* {{{ */
5660
2.24k
{
5661
2.24k
  zend_loop_var *base;
5662
2.24k
  zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack));
5663
5664
2.24k
  if (!loop_var) {
5665
270
    return 0;
5666
270
  }
5667
1.97k
  base = zend_stack_base(&CG(loop_var_stack));
5668
3.88k
  for (; loop_var >= base; loop_var--) {
5669
3.83k
    if (loop_var->opcode == ZEND_FAST_CALL) {
5670
595
      return 1;
5671
3.23k
    } else if (loop_var->opcode == ZEND_DISCARD_EXCEPTION) {
5672
1.82k
    } else if (loop_var->opcode == ZEND_RETURN) {
5673
      /* Stack separator */
5674
1.32k
      return 0;
5675
1.32k
    } else if (depth <= 1) {
5676
0
      return 0;
5677
501
    } else {
5678
501
      depth--;
5679
501
      }
5680
3.83k
  }
5681
54
  return 0;
5682
1.97k
}
5683
/* }}} */
5684
5685
static bool zend_has_finally(void) /* {{{ */
5686
2.24k
{
5687
2.24k
  return zend_has_finally_ex(zend_stack_count(&CG(loop_var_stack)) + 1);
5688
2.24k
}
5689
/* }}} */
5690
5691
static void zend_compile_return(zend_ast *ast) /* {{{ */
5692
39.2k
{
5693
39.2k
  zend_ast *expr_ast = ast->child[0];
5694
39.2k
  bool is_generator = (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0;
5695
39.2k
  bool by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
5696
5697
39.2k
  znode expr_node;
5698
39.2k
  zend_op *opline;
5699
5700
39.2k
  if (is_generator) {
5701
    /* For generators the by-ref flag refers to yields, not returns */
5702
4.54k
    by_ref = false;
5703
4.54k
  }
5704
5705
39.2k
  if (!expr_ast) {
5706
1.13k
    expr_node.op_type = IS_CONST;
5707
1.13k
    ZVAL_NULL(&expr_node.u.constant);
5708
38.0k
  } else if (by_ref && zend_is_variable(expr_ast)) {
5709
2.19k
    zend_assert_not_short_circuited(expr_ast);
5710
2.19k
    zend_compile_var(&expr_node, expr_ast, BP_VAR_W, true);
5711
35.8k
  } else {
5712
35.8k
    zend_compile_expr(&expr_node, expr_ast);
5713
35.8k
  }
5714
5715
39.2k
  if ((CG(active_op_array)->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)
5716
2.85k
   && (expr_node.op_type == IS_CV || (by_ref && expr_node.op_type == IS_VAR))
5717
2.24k
   && zend_has_finally()) {
5718
    /* Copy return value into temporary VAR to avoid modification in finally code */
5719
595
    if (by_ref) {
5720
103
      zend_emit_op(&expr_node, ZEND_MAKE_REF, &expr_node, NULL);
5721
492
    } else {
5722
492
      zend_emit_op_tmp(&expr_node, ZEND_QM_ASSIGN, &expr_node, NULL);
5723
492
    }
5724
595
  }
5725
5726
  /* Generator return types are handled separately */
5727
39.2k
  if (!is_generator && (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
5728
7.62k
    zend_emit_return_type_check(
5729
7.62k
      expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1, false);
5730
7.62k
  }
5731
5732
39.2k
  uint32_t opnum_before_finally = get_next_op_number();
5733
5734
39.2k
  zend_handle_loops_and_finally((expr_node.op_type & (IS_TMP_VAR | IS_VAR)) ? &expr_node : NULL);
5735
5736
  /* Content of reference might have changed in finally, repeat type check. */
5737
39.2k
  if (by_ref
5738
   /* Check if any opcodes were emitted since the last return type check. */
5739
4.87k
   && opnum_before_finally != get_next_op_number()
5740
1.56k
   && !is_generator
5741
1.56k
   && (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
5742
5
    zend_emit_return_type_check(
5743
5
      expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1, false);
5744
5
  }
5745
5746
39.2k
  opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN,
5747
39.2k
    &expr_node, NULL);
5748
5749
39.2k
  if (by_ref && expr_ast) {
5750
4.24k
    if (zend_is_call(expr_ast)) {
5751
542
      opline->extended_value = ZEND_RETURNS_FUNCTION;
5752
3.69k
    } else if (!zend_is_variable(expr_ast) || zend_ast_is_short_circuited(expr_ast)) {
5753
1.51k
      opline->extended_value = ZEND_RETURNS_VALUE;
5754
1.51k
    }
5755
4.24k
  }
5756
39.2k
}
5757
/* }}} */
5758
5759
static void zend_compile_void_cast(znode *result, zend_ast *ast)
5760
1.24k
{
5761
1.24k
  zend_ast *expr_ast = ast->child[0];
5762
1.24k
  znode expr_node;
5763
1.24k
  zend_op *opline;
5764
5765
1.24k
  zend_compile_expr(&expr_node, expr_ast);
5766
5767
1.24k
  switch (expr_node.op_type) {
5768
305
    case IS_TMP_VAR:
5769
448
    case IS_VAR:
5770
448
      opline = zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
5771
448
      opline->extended_value = ZEND_FREE_VOID_CAST;
5772
448
      break;
5773
759
    case IS_CONST:
5774
759
      zend_do_free(&expr_node);
5775
759
      break;
5776
1.24k
  }
5777
1.24k
}
5778
5779
static void zend_compile_echo(zend_ast *ast) /* {{{ */
5780
940k
{
5781
940k
  zend_op *opline;
5782
940k
  zend_ast *expr_ast = ast->child[0];
5783
5784
940k
  znode expr_node;
5785
940k
  zend_compile_expr(&expr_node, expr_ast);
5786
5787
940k
  opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL);
5788
940k
  opline->extended_value = 0;
5789
940k
}
5790
/* }}} */
5791
5792
static void zend_compile_throw(znode *result, zend_ast *ast) /* {{{ */
5793
4.17k
{
5794
4.17k
  zend_ast *expr_ast = ast->child[0];
5795
5796
4.17k
  znode expr_node;
5797
4.17k
  zend_compile_expr(&expr_node, expr_ast);
5798
5799
4.17k
  zend_op *opline = zend_emit_op(NULL, ZEND_THROW, &expr_node, NULL);
5800
4.17k
  if (result) {
5801
    /* Mark this as an "expression throw" for opcache. */
5802
1.66k
    opline->extended_value = ZEND_THROW_IS_EXPR;
5803
1.66k
    result->op_type = IS_CONST;
5804
1.66k
    ZVAL_TRUE(&result->u.constant);
5805
1.66k
  }
5806
4.17k
}
5807
/* }}} */
5808
5809
static void zend_compile_break_continue(zend_ast *ast) /* {{{ */
5810
1.87k
{
5811
1.87k
  zend_ast *depth_ast = ast->child[0];
5812
5813
1.87k
  zend_op *opline;
5814
1.87k
  zend_long depth;
5815
5816
1.87k
  ZEND_ASSERT(ast->kind == ZEND_AST_BREAK || ast->kind == ZEND_AST_CONTINUE);
5817
5818
1.87k
  if (depth_ast) {
5819
448
    zval *depth_zv;
5820
448
    if (depth_ast->kind != ZEND_AST_ZVAL) {
5821
27
      zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-integer operand "
5822
27
        "is no longer supported", ast->kind == ZEND_AST_BREAK ? "break" : "continue");
5823
27
    }
5824
5825
421
    depth_zv = zend_ast_get_zval(depth_ast);
5826
421
    if (Z_TYPE_P(depth_zv) != IS_LONG || Z_LVAL_P(depth_zv) < 1) {
5827
10
      zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive integers",
5828
10
        ast->kind == ZEND_AST_BREAK ? "break" : "continue");
5829
10
    }
5830
5831
411
    depth = Z_LVAL_P(depth_zv);
5832
1.42k
  } else {
5833
1.42k
    depth = 1;
5834
1.42k
  }
5835
5836
1.83k
  if (CG(context).current_brk_cont == -1) {
5837
50
    zend_error_noreturn(E_COMPILE_ERROR, "'%s' not in the 'loop' or 'switch' context",
5838
50
      ast->kind == ZEND_AST_BREAK ? "break" : "continue");
5839
1.78k
  } else {
5840
1.78k
    if (!zend_handle_loops_and_finally_ex(depth, NULL)) {
5841
103
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot '%s' " ZEND_LONG_FMT " level%s",
5842
103
        ast->kind == ZEND_AST_BREAK ? "break" : "continue",
5843
103
        depth, depth == 1 ? "" : "s");
5844
103
    }
5845
1.78k
  }
5846
5847
1.68k
  if (ast->kind == ZEND_AST_CONTINUE) {
5848
898
    int d, cur = CG(context).current_brk_cont;
5849
1.01k
    for (d = depth - 1; d > 0; d--) {
5850
115
      cur = CG(context).brk_cont_array[cur].parent;
5851
115
      ZEND_ASSERT(cur != -1);
5852
115
    }
5853
5854
898
    if (CG(context).brk_cont_array[cur].is_switch) {
5855
264
      if (depth == 1) {
5856
184
        if (CG(context).brk_cont_array[cur].parent == -1) {
5857
168
          zend_error(E_WARNING,
5858
168
            "\"continue\" targeting switch is equivalent to \"break\"");
5859
168
        } else {
5860
16
          zend_error(E_WARNING,
5861
16
            "\"continue\" targeting switch is equivalent to \"break\". " \
5862
16
            "Did you mean to use \"continue " ZEND_LONG_FMT "\"?",
5863
16
            depth + 1);
5864
16
        }
5865
184
      } else {
5866
80
        if (CG(context).brk_cont_array[cur].parent == -1) {
5867
30
          zend_error(E_WARNING,
5868
30
            "\"continue " ZEND_LONG_FMT "\" targeting switch is equivalent to \"break " ZEND_LONG_FMT "\"",
5869
30
            depth, depth);
5870
50
        } else {
5871
50
          zend_error(E_WARNING,
5872
50
            "\"continue " ZEND_LONG_FMT "\" targeting switch is equivalent to \"break " ZEND_LONG_FMT "\". " \
5873
50
            "Did you mean to use \"continue " ZEND_LONG_FMT "\"?",
5874
50
            depth, depth, depth + 1);
5875
50
        }
5876
80
      }
5877
264
    }
5878
898
  }
5879
5880
1.68k
  opline = zend_emit_op(NULL, ast->kind == ZEND_AST_BREAK ? ZEND_BRK : ZEND_CONT, NULL, NULL);
5881
1.68k
  opline->op1.num = CG(context).current_brk_cont;
5882
1.68k
  opline->op2.num = depth;
5883
1.68k
}
5884
/* }}} */
5885
5886
void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline) /* {{{ */
5887
2.47k
{
5888
2.47k
  zend_label *dest;
5889
2.47k
  int current, remove_oplines = opline->op1.num;
5890
2.47k
  zval *label;
5891
2.47k
  uint32_t opnum = opline - op_array->opcodes;
5892
5893
2.47k
  label = CT_CONSTANT_EX(op_array, opline->op2.constant);
5894
2.47k
  if (CG(context).labels == NULL ||
5895
2.44k
      (dest = zend_hash_find_ptr(CG(context).labels, Z_STR_P(label))) == NULL
5896
2.47k
  ) {
5897
76
    CG(in_compilation) = 1;
5898
76
    CG(active_op_array) = op_array;
5899
76
    CG(zend_lineno) = opline->lineno;
5900
76
    zend_error_noreturn(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL_P(label));
5901
76
  }
5902
5903
2.40k
  zval_ptr_dtor_str(label);
5904
2.40k
  ZVAL_NULL(label);
5905
5906
2.40k
  current = opline->extended_value;
5907
3.48k
  for (; current != dest->brk_cont; current = CG(context).brk_cont_array[current].parent) {
5908
1.10k
    if (current == -1) {
5909
19
      CG(in_compilation) = 1;
5910
19
      CG(active_op_array) = op_array;
5911
19
      CG(zend_lineno) = opline->lineno;
5912
19
      zend_error_noreturn(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
5913
19
    }
5914
1.08k
    if (CG(context).brk_cont_array[current].start >= 0) {
5915
599
      remove_oplines--;
5916
599
    }
5917
1.08k
  }
5918
5919
6.18k
  for (current = 0; current < op_array->last_try_catch; ++current) {
5920
4.11k
    zend_try_catch_element *elem = &op_array->try_catch_array[current];
5921
4.11k
    if (elem->try_op > opnum) {
5922
316
      break;
5923
316
    }
5924
3.80k
    if (elem->finally_op && opnum < elem->finally_op - 1
5925
2.58k
      && (dest->opline_num > elem->finally_end || dest->opline_num < elem->try_op)
5926
3.80k
    ) {
5927
1.66k
      remove_oplines--;
5928
1.66k
    }
5929
3.80k
  }
5930
5931
2.38k
  opline->opcode = ZEND_JMP;
5932
2.38k
  SET_UNUSED(opline->op1);
5933
2.38k
  SET_UNUSED(opline->op2);
5934
2.38k
  SET_UNUSED(opline->result);
5935
2.38k
  opline->op1.opline_num = dest->opline_num;
5936
2.38k
  opline->extended_value = 0;
5937
5938
2.38k
  ZEND_ASSERT(remove_oplines >= 0);
5939
3.36k
  while (remove_oplines--) {
5940
982
    opline--;
5941
982
    MAKE_NOP(opline);
5942
982
    ZEND_VM_SET_OPCODE_HANDLER(opline);
5943
982
  }
5944
2.38k
}
5945
/* }}} */
5946
5947
static void zend_compile_goto(zend_ast *ast) /* {{{ */
5948
2.82k
{
5949
2.82k
  zend_ast *label_ast = ast->child[0];
5950
2.82k
  znode label_node;
5951
2.82k
  zend_op *opline;
5952
5953
2.82k
  zend_compile_expr(&label_node, label_ast);
5954
5955
  /* Label resolution and unwinding adjustments happen in pass two. */
5956
2.82k
  uint32_t opnum_start = get_next_op_number();
5957
2.82k
  zend_handle_loops_and_finally(NULL);
5958
2.82k
  opline = zend_emit_op(NULL, ZEND_GOTO, NULL, &label_node);
5959
2.82k
  opline->op1.num = get_next_op_number() - opnum_start - 1;
5960
2.82k
  opline->extended_value = CG(context).current_brk_cont;
5961
2.82k
}
5962
/* }}} */
5963
5964
static void zend_compile_label(zend_ast *ast) /* {{{ */
5965
4.46k
{
5966
4.46k
  zend_string *label = zend_ast_get_str(ast->child[0]);
5967
4.46k
  zend_label dest;
5968
5969
4.46k
  if (!CG(context).labels) {
5970
3.16k
    ALLOC_HASHTABLE(CG(context).labels);
5971
3.16k
    zend_hash_init(CG(context).labels, 8, NULL, label_ptr_dtor, 0);
5972
3.16k
  }
5973
5974
4.46k
  dest.brk_cont = CG(context).current_brk_cont;
5975
4.46k
  dest.opline_num = get_next_op_number();
5976
5977
4.46k
  if (!zend_hash_add_mem(CG(context).labels, label, &dest, sizeof(zend_label))) {
5978
62
    zend_error_noreturn(E_COMPILE_ERROR, "Label '%s' already defined", ZSTR_VAL(label));
5979
62
  }
5980
4.46k
}
5981
/* }}} */
5982
5983
static void zend_compile_while(zend_ast *ast) /* {{{ */
5984
17.4k
{
5985
17.4k
  zend_ast *cond_ast = ast->child[0];
5986
17.4k
  zend_ast *stmt_ast = ast->child[1];
5987
17.4k
  znode cond_node;
5988
17.4k
  uint32_t opnum_start, opnum_jmp, opnum_cond;
5989
5990
17.4k
  opnum_jmp = zend_emit_jump(0);
5991
5992
17.4k
  zend_begin_loop(ZEND_NOP, NULL, false);
5993
5994
17.4k
  opnum_start = get_next_op_number();
5995
17.4k
  zend_compile_stmt(stmt_ast);
5996
5997
17.4k
  opnum_cond = get_next_op_number();
5998
17.4k
  zend_update_jump_target(opnum_jmp, opnum_cond);
5999
17.4k
  zend_compile_expr(&cond_node, cond_ast);
6000
6001
17.4k
  zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
6002
6003
17.4k
  zend_end_loop(opnum_cond, NULL);
6004
17.4k
}
6005
/* }}} */
6006
6007
static void zend_compile_do_while(zend_ast *ast) /* {{{ */
6008
1.30k
{
6009
1.30k
  zend_ast *stmt_ast = ast->child[0];
6010
1.30k
  zend_ast *cond_ast = ast->child[1];
6011
6012
1.30k
  znode cond_node;
6013
1.30k
  uint32_t opnum_start, opnum_cond;
6014
6015
1.30k
  zend_begin_loop(ZEND_NOP, NULL, false);
6016
6017
1.30k
  opnum_start = get_next_op_number();
6018
1.30k
  zend_compile_stmt(stmt_ast);
6019
6020
1.30k
  opnum_cond = get_next_op_number();
6021
1.30k
  zend_compile_expr(&cond_node, cond_ast);
6022
6023
1.30k
  zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
6024
6025
1.30k
  zend_end_loop(opnum_cond, NULL);
6026
1.30k
}
6027
/* }}} */
6028
6029
static void zend_compile_for_expr_list(znode *result, zend_ast *ast) /* {{{ */
6030
39.2k
{
6031
39.2k
  zend_ast_list *list;
6032
39.2k
  uint32_t i;
6033
6034
39.2k
  result->op_type = IS_CONST;
6035
39.2k
  ZVAL_TRUE(&result->u.constant);
6036
6037
39.2k
  if (!ast) {
6038
11.9k
    return;
6039
11.9k
  }
6040
6041
27.2k
  list = zend_ast_get_list(ast);
6042
56.8k
  for (i = 0; i < list->children; ++i) {
6043
29.5k
    zend_ast *expr_ast = list->child[i];
6044
6045
29.5k
    zend_do_free(result);
6046
29.5k
    if (expr_ast->kind == ZEND_AST_CAST_VOID) {
6047
64
      zend_compile_void_cast(NULL, expr_ast);
6048
64
      result->op_type = IS_CONST;
6049
64
      ZVAL_NULL(&result->u.constant);
6050
29.4k
    } else {
6051
29.4k
      zend_compile_expr(result, expr_ast);
6052
29.4k
    }
6053
29.5k
  }
6054
27.2k
}
6055
/* }}} */
6056
6057
static void zend_compile_for(zend_ast *ast) /* {{{ */
6058
13.1k
{
6059
13.1k
  zend_ast *init_ast = ast->child[0];
6060
13.1k
  zend_ast *cond_ast = ast->child[1];
6061
13.1k
  zend_ast *loop_ast = ast->child[2];
6062
13.1k
  zend_ast *stmt_ast = ast->child[3];
6063
6064
13.1k
  znode result;
6065
13.1k
  uint32_t opnum_start, opnum_jmp, opnum_loop;
6066
6067
13.1k
  zend_compile_for_expr_list(&result, init_ast);
6068
13.1k
  zend_do_free(&result);
6069
6070
13.1k
  opnum_jmp = zend_emit_jump(0);
6071
6072
13.1k
  zend_begin_loop(ZEND_NOP, NULL, false);
6073
6074
13.1k
  opnum_start = get_next_op_number();
6075
13.1k
  zend_compile_stmt(stmt_ast);
6076
6077
13.1k
  opnum_loop = get_next_op_number();
6078
13.1k
  zend_compile_for_expr_list(&result, loop_ast);
6079
13.1k
  zend_do_free(&result);
6080
6081
13.1k
  zend_update_jump_target_to_next(opnum_jmp);
6082
13.1k
  zend_compile_for_expr_list(&result, cond_ast);
6083
13.1k
  zend_do_extended_stmt(NULL);
6084
6085
13.1k
  zend_emit_cond_jump(ZEND_JMPNZ, &result, opnum_start);
6086
6087
13.1k
  zend_end_loop(opnum_loop, NULL);
6088
13.1k
}
6089
/* }}} */
6090
6091
static void zend_compile_foreach(zend_ast *ast) /* {{{ */
6092
42.3k
{
6093
42.3k
  zend_ast *expr_ast = ast->child[0];
6094
42.3k
  zend_ast *value_ast = ast->child[1];
6095
42.3k
  zend_ast *key_ast = ast->child[2];
6096
42.3k
  zend_ast *stmt_ast = ast->child[3];
6097
42.3k
  bool by_ref = value_ast->kind == ZEND_AST_REF;
6098
42.3k
  bool is_variable = zend_is_variable(expr_ast) && zend_can_write_to_variable(expr_ast);
6099
6100
42.3k
  znode expr_node, reset_node, value_node, key_node;
6101
42.3k
  zend_op *opline;
6102
42.3k
  uint32_t opnum_reset, opnum_fetch;
6103
6104
42.3k
  if (key_ast) {
6105
1.67k
    if (key_ast->kind == ZEND_AST_REF) {
6106
12
      zend_error_noreturn(E_COMPILE_ERROR, "Key element cannot be a reference");
6107
12
    }
6108
1.65k
    if (key_ast->kind == ZEND_AST_ARRAY) {
6109
12
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use list as key element");
6110
12
    }
6111
1.65k
  }
6112
6113
42.3k
  if (by_ref) {
6114
1.60k
    value_ast = value_ast->child[0];
6115
1.60k
  }
6116
6117
42.3k
  if (value_ast->kind == ZEND_AST_ARRAY && zend_propagate_list_refs(value_ast)) {
6118
209
    by_ref = true;
6119
209
  }
6120
6121
42.3k
  if (by_ref && is_variable) {
6122
1.02k
    zend_compile_var(&expr_node, expr_ast, BP_VAR_W, true);
6123
41.3k
  } else {
6124
41.3k
    zend_compile_expr(&expr_node, expr_ast);
6125
41.3k
  }
6126
6127
42.3k
  if (by_ref) {
6128
1.81k
    zend_separate_if_call_and_write(&expr_node, expr_ast, BP_VAR_W);
6129
1.81k
  }
6130
6131
42.3k
  opnum_reset = get_next_op_number();
6132
42.3k
  opline = zend_emit_op(&reset_node, by_ref ? ZEND_FE_RESET_RW : ZEND_FE_RESET_R, &expr_node, NULL);
6133
6134
42.3k
  zend_begin_loop(ZEND_FE_FREE, &reset_node, false);
6135
6136
42.3k
  opnum_fetch = get_next_op_number();
6137
42.3k
  opline = zend_emit_op(NULL, by_ref ? ZEND_FE_FETCH_RW : ZEND_FE_FETCH_R, &reset_node, NULL);
6138
6139
42.3k
  if (is_this_fetch(value_ast)) {
6140
11
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
6141
42.3k
  } else if (value_ast->kind == ZEND_AST_VAR &&
6142
41.7k
    zend_try_compile_cv(&value_node, value_ast, BP_VAR_R) == SUCCESS) {
6143
41.4k
    SET_NODE(opline->op2, &value_node);
6144
41.4k
  } else {
6145
911
    opline->op2_type = IS_VAR;
6146
911
    opline->op2.var = get_temporary_variable();
6147
911
    GET_NODE(&value_node, opline->op2);
6148
911
    if (value_ast->kind == ZEND_AST_ARRAY) {
6149
408
      zend_compile_list_assign(NULL, value_ast, &value_node, value_ast->attr);
6150
503
    } else if (by_ref) {
6151
114
      zend_emit_assign_ref_znode(value_ast, &value_node);
6152
389
    } else {
6153
389
      zend_emit_assign_znode(value_ast, &value_node);
6154
389
    }
6155
911
  }
6156
6157
42.3k
  if (key_ast) {
6158
1.63k
    opline = &CG(active_op_array)->opcodes[opnum_fetch];
6159
1.63k
    zend_make_tmp_result(&key_node, opline);
6160
1.63k
    zend_emit_assign_znode(key_ast, &key_node);
6161
1.63k
  }
6162
6163
42.3k
  zend_compile_stmt(stmt_ast);
6164
6165
  /* Place JMP and FE_FREE on the line where foreach starts. It would be
6166
   * better to use the end line, but this information is not available
6167
   * currently. */
6168
42.3k
  CG(zend_lineno) = ast->lineno;
6169
42.3k
  zend_emit_jump(opnum_fetch);
6170
6171
42.3k
  opline = &CG(active_op_array)->opcodes[opnum_reset];
6172
42.3k
  opline->op2.opline_num = get_next_op_number();
6173
6174
42.3k
  opline = &CG(active_op_array)->opcodes[opnum_fetch];
6175
42.3k
  opline->extended_value = get_next_op_number();
6176
6177
42.3k
  zend_end_loop(opnum_fetch, &reset_node);
6178
6179
42.3k
  opline = zend_emit_op(NULL, ZEND_FE_FREE, &reset_node, NULL);
6180
42.3k
}
6181
/* }}} */
6182
6183
static void zend_compile_if(zend_ast *ast) /* {{{ */
6184
21.7k
{
6185
21.7k
  zend_ast_list *list = zend_ast_get_list(ast);
6186
21.7k
  uint32_t i;
6187
21.7k
  uint32_t *jmp_opnums = NULL;
6188
6189
21.7k
  if (list->children > 1) {
6190
4.99k
    jmp_opnums = safe_emalloc(sizeof(uint32_t), list->children - 1, 0);
6191
4.99k
  }
6192
6193
52.0k
  for (i = 0; i < list->children; ++i) {
6194
30.2k
    zend_ast *elem_ast = list->child[i];
6195
30.2k
    zend_ast *cond_ast = elem_ast->child[0];
6196
30.2k
    zend_ast *stmt_ast = elem_ast->child[1];
6197
6198
30.2k
    if (cond_ast) {
6199
25.5k
      znode cond_node;
6200
25.5k
      uint32_t opnum_jmpz;
6201
6202
25.5k
      if (i > 0) {
6203
3.76k
        CG(zend_lineno) = cond_ast->lineno;
6204
3.76k
        zend_do_extended_stmt(NULL);
6205
3.76k
      }
6206
6207
25.5k
      zend_compile_expr(&cond_node, cond_ast);
6208
25.5k
      opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
6209
6210
25.5k
      zend_compile_stmt(stmt_ast);
6211
6212
25.5k
      if (i != list->children - 1) {
6213
        /* Set the lineno of JMP to the position of the if keyword, as we don't want to
6214
         * report the last line in the if branch as covered if it hasn't actually executed. */
6215
8.47k
        CG(zend_lineno) = elem_ast->lineno;
6216
8.47k
        jmp_opnums[i] = zend_emit_jump(0);
6217
8.47k
      }
6218
25.5k
      zend_update_jump_target_to_next(opnum_jmpz);
6219
25.5k
    } else {
6220
      /* "else" can only occur as last element. */
6221
4.71k
      ZEND_ASSERT(i == list->children - 1);
6222
4.71k
      zend_compile_stmt(stmt_ast);
6223
4.71k
    }
6224
30.2k
  }
6225
6226
21.7k
  if (list->children > 1) {
6227
13.4k
    for (i = 0; i < list->children - 1; ++i) {
6228
8.45k
      zend_update_jump_target_to_next(jmp_opnums[i]);
6229
8.45k
    }
6230
4.98k
    efree(jmp_opnums);
6231
4.98k
  }
6232
21.7k
}
6233
/* }}} */
6234
6235
16.4k
static uint8_t determine_switch_jumptable_type(zend_ast_list *cases) {
6236
16.4k
  uint32_t i;
6237
16.4k
  uint8_t common_type = IS_UNDEF;
6238
48.5k
  for (i = 0; i < cases->children; i++) {
6239
44.7k
    zend_ast *case_ast = cases->child[i];
6240
44.7k
    zend_ast **cond_ast = &case_ast->child[0];
6241
44.7k
    zval *cond_zv;
6242
44.7k
    if (!case_ast->child[0]) {
6243
      /* Skip default clause */
6244
248
      continue;
6245
248
    }
6246
6247
44.5k
    zend_eval_const_expr(cond_ast);
6248
44.5k
    if ((*cond_ast)->kind != ZEND_AST_ZVAL) {
6249
      /* Non-constant case */
6250
400
      return IS_UNDEF;
6251
400
    }
6252
6253
44.1k
    cond_zv = zend_ast_get_zval(case_ast->child[0]);
6254
44.1k
    if (Z_TYPE_P(cond_zv) != IS_LONG && Z_TYPE_P(cond_zv) != IS_STRING) {
6255
      /* We only optimize switched on integers and strings */
6256
10.4k
      return IS_UNDEF;
6257
10.4k
    }
6258
6259
33.6k
    if (common_type == IS_UNDEF) {
6260
15.7k
      common_type = Z_TYPE_P(cond_zv);
6261
17.9k
    } else if (common_type != Z_TYPE_P(cond_zv)) {
6262
      /* Non-uniform case types */
6263
195
      return IS_UNDEF;
6264
195
    }
6265
6266
33.4k
    if (Z_TYPE_P(cond_zv) == IS_STRING
6267
25.9k
        && is_numeric_string(Z_STRVAL_P(cond_zv), Z_STRLEN_P(cond_zv), NULL, NULL, 0)) {
6268
      /* Numeric strings cannot be compared with a simple hash lookup */
6269
1.60k
      return IS_UNDEF;
6270
1.60k
    }
6271
33.4k
  }
6272
6273
3.76k
  return common_type;
6274
16.4k
}
6275
6276
3.28k
static bool should_use_jumptable(zend_ast_list *cases, uint8_t jumptable_type) {
6277
3.28k
  if (CG(compiler_options) & ZEND_COMPILE_NO_JUMPTABLES) {
6278
0
    return 0;
6279
0
  }
6280
6281
  /* Thresholds are chosen based on when the average switch time for equidistributed
6282
   * input becomes smaller when using the jumptable optimization. */
6283
3.28k
  if (jumptable_type == IS_LONG) {
6284
903
    return cases->children >= 5;
6285
2.38k
  } else {
6286
2.38k
    ZEND_ASSERT(jumptable_type == IS_STRING);
6287
2.38k
    return cases->children >= 2;
6288
2.38k
  }
6289
3.28k
}
6290
6291
static void zend_compile_switch(zend_ast *ast) /* {{{ */
6292
16.4k
{
6293
16.4k
  zend_ast *expr_ast = ast->child[0];
6294
16.4k
  zend_ast_list *cases = zend_ast_get_list(ast->child[1]);
6295
6296
16.4k
  uint32_t i;
6297
16.4k
  bool has_default_case = false;
6298
6299
16.4k
  znode expr_node, case_node;
6300
16.4k
  zend_op *opline;
6301
16.4k
  uint32_t *jmpnz_opnums, opnum_default_jmp, opnum_switch = (uint32_t)-1;
6302
16.4k
  uint8_t jumptable_type;
6303
16.4k
  HashTable *jumptable = NULL;
6304
6305
16.4k
  zend_compile_expr(&expr_node, expr_ast);
6306
6307
16.4k
  zend_begin_loop(ZEND_FREE, &expr_node, true);
6308
6309
16.4k
  case_node.op_type = IS_TMP_VAR;
6310
16.4k
  case_node.u.op.var = get_temporary_variable();
6311
6312
16.4k
  jumptable_type = determine_switch_jumptable_type(cases);
6313
16.4k
  if (jumptable_type != IS_UNDEF && should_use_jumptable(cases, jumptable_type)) {
6314
2.46k
    znode jumptable_op;
6315
6316
2.46k
    ALLOC_HASHTABLE(jumptable);
6317
2.46k
    zend_hash_init(jumptable, cases->children, NULL, NULL, 0);
6318
2.46k
    jumptable_op.op_type = IS_CONST;
6319
2.46k
    ZVAL_ARR(&jumptable_op.u.constant, jumptable);
6320
6321
2.46k
    opline = zend_emit_op(NULL,
6322
2.46k
      jumptable_type == IS_LONG ? ZEND_SWITCH_LONG : ZEND_SWITCH_STRING,
6323
2.46k
      &expr_node, &jumptable_op);
6324
2.46k
    if (opline->op1_type == IS_CONST) {
6325
2.11k
      Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
6326
2.11k
    }
6327
2.46k
    opnum_switch = opline - CG(active_op_array)->opcodes;
6328
2.46k
  }
6329
6330
16.4k
  jmpnz_opnums = safe_emalloc(sizeof(uint32_t), cases->children, 0);
6331
64.8k
  for (i = 0; i < cases->children; ++i) {
6332
48.4k
    zend_ast *case_ast = cases->child[i];
6333
48.4k
    zend_ast *cond_ast = case_ast->child[0];
6334
48.4k
    znode cond_node;
6335
6336
48.4k
    if (!cond_ast) {
6337
249
      if (has_default_case) {
6338
15
        CG(zend_lineno) = case_ast->lineno;
6339
15
        zend_error_noreturn(E_COMPILE_ERROR,
6340
15
          "Switch statements may only contain one default clause");
6341
15
      }
6342
234
      has_default_case = true;
6343
234
      continue;
6344
249
    }
6345
6346
48.1k
    if (case_ast->attr == ZEND_ALT_CASE_SYNTAX) {
6347
1.92k
      CG(zend_lineno) = case_ast->lineno;
6348
1.92k
      zend_error(E_DEPRECATED, "Case statements followed by a semicolon (;) are deprecated, use a colon (:) instead");
6349
1.92k
    }
6350
6351
48.1k
    zend_compile_expr(&cond_node, cond_ast);
6352
6353
48.1k
    if (expr_node.op_type == IS_CONST
6354
32.7k
      && Z_TYPE(expr_node.u.constant) == IS_FALSE) {
6355
1.54k
      jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
6356
46.6k
    } else if (expr_node.op_type == IS_CONST
6357
31.2k
      && Z_TYPE(expr_node.u.constant) == IS_TRUE) {
6358
481
      jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, 0);
6359
46.1k
    } else {
6360
46.1k
      opline = zend_emit_op(NULL,
6361
46.1k
        (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) ? ZEND_CASE : ZEND_IS_EQUAL,
6362
46.1k
        &expr_node, &cond_node);
6363
46.1k
      SET_NODE(opline->result, &case_node);
6364
46.1k
      if (opline->op1_type == IS_CONST) {
6365
30.7k
        Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
6366
30.7k
      }
6367
6368
46.1k
      jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0);
6369
46.1k
    }
6370
48.1k
  }
6371
6372
16.4k
  opnum_default_jmp = zend_emit_jump(0);
6373
6374
64.5k
  for (i = 0; i < cases->children; ++i) {
6375
48.1k
    zend_ast *case_ast = cases->child[i];
6376
48.1k
    zend_ast *cond_ast = case_ast->child[0];
6377
48.1k
    zend_ast *stmt_ast = case_ast->child[1];
6378
6379
48.1k
    if (cond_ast) {
6380
47.9k
      zend_update_jump_target_to_next(jmpnz_opnums[i]);
6381
6382
47.9k
      if (jumptable) {
6383
10.3k
        zval *cond_zv = zend_ast_get_zval(cond_ast);
6384
10.3k
        zval jmp_target;
6385
10.3k
        ZVAL_LONG(&jmp_target, get_next_op_number());
6386
6387
10.3k
        ZEND_ASSERT(Z_TYPE_P(cond_zv) == jumptable_type);
6388
10.3k
        if (Z_TYPE_P(cond_zv) == IS_LONG) {
6389
5.15k
          zend_hash_index_add(jumptable, Z_LVAL_P(cond_zv), &jmp_target);
6390
5.17k
        } else {
6391
5.17k
          ZEND_ASSERT(Z_TYPE_P(cond_zv) == IS_STRING);
6392
5.17k
          zend_hash_add(jumptable, Z_STR_P(cond_zv), &jmp_target);
6393
5.17k
        }
6394
10.3k
      }
6395
47.9k
    } else {
6396
219
      zend_update_jump_target_to_next(opnum_default_jmp);
6397
6398
219
      if (jumptable) {
6399
42
        ZEND_ASSERT(opnum_switch != (uint32_t)-1);
6400
42
        opline = &CG(active_op_array)->opcodes[opnum_switch];
6401
42
        opline->extended_value = get_next_op_number();
6402
42
      }
6403
219
    }
6404
6405
48.1k
    zend_compile_stmt(stmt_ast);
6406
48.1k
  }
6407
6408
16.4k
  if (!has_default_case) {
6409
16.1k
    zend_update_jump_target_to_next(opnum_default_jmp);
6410
6411
16.1k
    if (jumptable) {
6412
2.40k
      opline = &CG(active_op_array)->opcodes[opnum_switch];
6413
2.40k
      opline->extended_value = get_next_op_number();
6414
2.40k
    }
6415
16.1k
  }
6416
6417
16.4k
  zend_end_loop(get_next_op_number(), &expr_node);
6418
6419
16.4k
  if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) {
6420
5.37k
    opline = zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
6421
5.37k
    opline->extended_value = ZEND_FREE_SWITCH;
6422
11.0k
  } else if (expr_node.op_type == IS_CONST) {
6423
10.3k
    zval_ptr_dtor_nogc(&expr_node.u.constant);
6424
10.3k
  }
6425
6426
16.4k
  efree(jmpnz_opnums);
6427
16.4k
}
6428
/* }}} */
6429
6430
static uint32_t count_match_conds(zend_ast_list *arms)
6431
3.56k
{
6432
3.56k
  uint32_t num_conds = 0;
6433
6434
8.95k
  for (uint32_t i = 0; i < arms->children; i++) {
6435
5.39k
    zend_ast *arm_ast = arms->child[i];
6436
5.39k
    if (arm_ast->child[0] == NULL) {
6437
645
      continue;
6438
645
    }
6439
6440
4.74k
    zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
6441
4.74k
    num_conds += conds->children;
6442
4.74k
  }
6443
6444
3.56k
  return num_conds;
6445
3.56k
}
6446
6447
3.56k
static bool can_match_use_jumptable(zend_ast_list *arms) {
6448
6.30k
  for (uint32_t i = 0; i < arms->children; i++) {
6449
4.64k
    zend_ast *arm_ast = arms->child[i];
6450
4.64k
    if (!arm_ast->child[0]) {
6451
      /* Skip default arm */
6452
586
      continue;
6453
586
    }
6454
6455
4.05k
    zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
6456
9.86k
    for (uint32_t j = 0; j < conds->children; j++) {
6457
7.71k
      zend_ast **cond_ast = &conds->child[j];
6458
6459
7.71k
      zend_eval_const_expr(cond_ast);
6460
7.71k
      if ((*cond_ast)->kind != ZEND_AST_ZVAL) {
6461
1.19k
        return 0;
6462
1.19k
      }
6463
6464
6.51k
      zval *cond_zv = zend_ast_get_zval(*cond_ast);
6465
6.51k
      if (Z_TYPE_P(cond_zv) != IS_LONG && Z_TYPE_P(cond_zv) != IS_STRING) {
6466
704
        return 0;
6467
704
      }
6468
6.51k
    }
6469
4.05k
  }
6470
6471
1.66k
  return 1;
6472
3.56k
}
6473
6474
static bool zend_is_pipe_optimizable_callable_name(zend_ast *ast)
6475
364
{
6476
364
  if (ast->kind == ZEND_AST_ZVAL && Z_TYPE_P(zend_ast_get_zval(ast)) == IS_STRING) {
6477
    /* Assert compilation adds a message operand, but this is incompatible with the
6478
     * pipe optimization that uses a temporary znode for the reference elimination.
6479
     * Therefore, disable the optimization for assert.
6480
     * Note that "assert" as a name is always treated as fully qualified. */
6481
321
    zend_string *str = zend_ast_get_str(ast);
6482
321
    return !zend_string_equals_literal_ci(str, "assert");
6483
321
  }
6484
6485
43
  return true;
6486
364
}
6487
6488
static void zend_compile_pipe(znode *result, zend_ast *ast)
6489
71.9k
{
6490
71.9k
  zend_ast *operand_ast = ast->child[0];
6491
71.9k
  zend_ast *callable_ast = ast->child[1];
6492
6493
71.9k
  if (callable_ast->kind == ZEND_AST_ARROW_FUNC && !(callable_ast->attr & ZEND_PARENTHESIZED_ARROW_FUNC)) {
6494
9
    zend_error_noreturn(E_COMPILE_ERROR, "Arrow functions on the right hand side of |> must be parenthesized");
6495
9
  }
6496
6497
  /* Compile the left hand side down to a value first. */
6498
71.9k
  znode operand_result;
6499
71.9k
  zend_compile_expr(&operand_result, operand_ast);
6500
6501
  /* Wrap simple values in a ZEND_QM_ASSIGN opcode to ensure references
6502
   * always fail. They will already fail in complex cases like arrays,
6503
   * so those don't need a wrapper. */
6504
71.9k
  znode wrapped_operand_result;
6505
71.9k
  if (operand_result.op_type & (IS_CV|IS_VAR)) {
6506
58.2k
    zend_emit_op_tmp(&wrapped_operand_result, ZEND_QM_ASSIGN, &operand_result, NULL);
6507
58.2k
  } else {
6508
13.7k
    wrapped_operand_result = operand_result;
6509
13.7k
  }
6510
6511
  /* Turn the operand into a function parameter list. */
6512
71.9k
  zend_ast *arg_list_ast = zend_ast_create_list(1, ZEND_AST_ARG_LIST, zend_ast_create_znode(&wrapped_operand_result));
6513
6514
71.9k
  zend_ast *fcall_ast;
6515
71.9k
  znode callable_result;
6516
6517
  /* Turn $foo |> bar(...) into bar($foo). */
6518
71.9k
  if (callable_ast->kind == ZEND_AST_CALL
6519
897
    && callable_ast->child[1]->kind == ZEND_AST_CALLABLE_CONVERT
6520
364
    && zend_is_pipe_optimizable_callable_name(callable_ast->child[0])) {
6521
328
    fcall_ast = zend_ast_create(ZEND_AST_CALL,
6522
328
        callable_ast->child[0], arg_list_ast);
6523
  /* Turn $foo |> bar::baz(...) into bar::baz($foo). */
6524
71.6k
  } else if (callable_ast->kind == ZEND_AST_STATIC_CALL
6525
490
      && callable_ast->child[2]->kind == ZEND_AST_CALLABLE_CONVERT) {
6526
133
    fcall_ast = zend_ast_create(ZEND_AST_STATIC_CALL,
6527
133
      callable_ast->child[0], callable_ast->child[1], arg_list_ast);
6528
  /* Turn $foo |> $bar->baz(...) into $bar->baz($foo). */
6529
71.5k
  } else if (callable_ast->kind == ZEND_AST_METHOD_CALL
6530
2.72k
      && callable_ast->child[2]->kind == ZEND_AST_CALLABLE_CONVERT) {
6531
2.17k
    fcall_ast = zend_ast_create(ZEND_AST_METHOD_CALL,
6532
2.17k
      callable_ast->child[0], callable_ast->child[1], arg_list_ast);
6533
  /* Turn $foo |> $expr into ($expr)($foo) */
6534
69.3k
  } else {
6535
69.3k
    zend_compile_expr(&callable_result, callable_ast);
6536
69.3k
    callable_ast = zend_ast_create_znode(&callable_result);
6537
69.3k
    fcall_ast = zend_ast_create(ZEND_AST_CALL,
6538
69.3k
      callable_ast, arg_list_ast);
6539
69.3k
  }
6540
6541
71.9k
  zend_do_extended_stmt(&operand_result);
6542
6543
71.9k
  zend_compile_expr(result, fcall_ast);
6544
71.9k
}
6545
6546
static void zend_compile_match(znode *result, zend_ast *ast)
6547
3.56k
{
6548
3.56k
  zend_ast *expr_ast = ast->child[0];
6549
3.56k
  zend_ast_list *arms = zend_ast_get_list(ast->child[1]);
6550
3.56k
  bool has_default_arm = false;
6551
3.56k
  uint32_t opnum_match = (uint32_t)-1;
6552
6553
3.56k
  znode expr_node;
6554
3.56k
  zend_compile_expr(&expr_node, expr_ast);
6555
6556
3.56k
  znode case_node;
6557
3.56k
  case_node.op_type = IS_TMP_VAR;
6558
3.56k
  case_node.u.op.var = get_temporary_variable();
6559
6560
3.56k
  uint32_t num_conds = count_match_conds(arms);
6561
3.56k
  uint8_t can_use_jumptable = can_match_use_jumptable(arms);
6562
3.56k
  bool uses_jumptable = can_use_jumptable && num_conds >= 2;
6563
3.56k
  HashTable *jumptable = NULL;
6564
3.56k
  uint32_t *jmpnz_opnums = NULL;
6565
6566
8.94k
  for (uint32_t i = 0; i < arms->children; ++i) {
6567
5.39k
    zend_ast *arm_ast = arms->child[i];
6568
6569
5.39k
    if (!arm_ast->child[0]) {
6570
645
      if (has_default_arm) {
6571
8
        CG(zend_lineno) = arm_ast->lineno;
6572
8
        zend_error_noreturn(E_COMPILE_ERROR,
6573
8
          "Match expressions may only contain one default arm");
6574
8
      }
6575
637
      has_default_arm = true;
6576
637
    }
6577
5.39k
  }
6578
6579
3.55k
  if (uses_jumptable) {
6580
867
    znode jumptable_op;
6581
6582
867
    ALLOC_HASHTABLE(jumptable);
6583
867
    zend_hash_init(jumptable, num_conds, NULL, NULL, 0);
6584
867
    jumptable_op.op_type = IS_CONST;
6585
867
    ZVAL_ARR(&jumptable_op.u.constant, jumptable);
6586
6587
867
    zend_op *opline = zend_emit_op(NULL, ZEND_MATCH, &expr_node, &jumptable_op);
6588
867
    if (opline->op1_type == IS_CONST) {
6589
316
      Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
6590
316
    }
6591
867
    opnum_match = opline - CG(active_op_array)->opcodes;
6592
2.69k
  } else {
6593
2.69k
    jmpnz_opnums = safe_emalloc(sizeof(uint32_t), num_conds, 0);
6594
2.69k
    uint32_t cond_count = 0;
6595
5.98k
    for (uint32_t i = 0; i < arms->children; ++i) {
6596
3.28k
      zend_ast *arm_ast = arms->child[i];
6597
6598
3.28k
      if (!arm_ast->child[0]) {
6599
343
        continue;
6600
343
      }
6601
6602
2.94k
      zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
6603
9.98k
      for (uint32_t j = 0; j < conds->children; j++) {
6604
7.03k
        zend_ast *cond_ast = conds->child[j];
6605
6606
7.03k
        znode cond_node;
6607
7.03k
        zend_compile_expr(&cond_node, cond_ast);
6608
6609
7.03k
        uint32_t opcode = (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) ? ZEND_CASE_STRICT : ZEND_IS_IDENTICAL;
6610
7.03k
        zend_op *opline = zend_emit_op(NULL, opcode, &expr_node, &cond_node);
6611
7.03k
        SET_NODE(opline->result, &case_node);
6612
7.03k
        if (opline->op1_type == IS_CONST) {
6613
2.10k
          Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
6614
2.10k
        }
6615
6616
7.03k
        jmpnz_opnums[cond_count] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0);
6617
6618
7.03k
        cond_count++;
6619
7.03k
      }
6620
2.94k
    }
6621
2.69k
  }
6622
6623
3.55k
  uint32_t opnum_default_jmp = 0;
6624
3.55k
  if (!uses_jumptable) {
6625
2.69k
    opnum_default_jmp = zend_emit_jump(0);
6626
2.69k
  }
6627
6628
3.55k
  bool is_first_case = true;
6629
3.55k
  uint32_t cond_count = 0;
6630
3.55k
  uint32_t *jmp_end_opnums = safe_emalloc(sizeof(uint32_t), arms->children, 0);
6631
6632
  // The generated default arm is emitted first to avoid live range issues where the tmpvar
6633
  // for the arm result is freed even though it has not been initialized yet.
6634
3.55k
  if (!has_default_arm) {
6635
2.92k
    if (!uses_jumptable) {
6636
2.34k
      zend_update_jump_target_to_next(opnum_default_jmp);
6637
2.34k
    }
6638
6639
2.92k
    if (jumptable) {
6640
581
      zend_op *opline = &CG(active_op_array)->opcodes[opnum_match];
6641
581
      opline->extended_value = get_next_op_number();
6642
581
    }
6643
6644
2.92k
    zend_op *opline = zend_emit_op(NULL, ZEND_MATCH_ERROR, &expr_node, NULL);
6645
2.92k
    if (opline->op1_type == IS_CONST) {
6646
588
      Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
6647
588
    }
6648
2.92k
    if (arms->children == 0) {
6649
      /* Mark this as an "expression throw" for opcache. */
6650
461
      opline->extended_value = ZEND_THROW_IS_EXPR;
6651
461
    }
6652
2.92k
  }
6653
6654
8.91k
  for (uint32_t i = 0; i < arms->children; ++i) {
6655
5.35k
    zend_ast *arm_ast = arms->child[i];
6656
5.35k
    zend_ast *body_ast = arm_ast->child[1];
6657
6658
5.35k
    if (arm_ast->child[0] != NULL) {
6659
4.72k
      zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
6660
6661
15.5k
      for (uint32_t j = 0; j < conds->children; j++) {
6662
10.8k
        zend_ast *cond_ast = conds->child[j];
6663
6664
10.8k
        if (jmpnz_opnums != NULL) {
6665
7.03k
          zend_update_jump_target_to_next(jmpnz_opnums[cond_count]);
6666
7.03k
        }
6667
6668
10.8k
        if (jumptable) {
6669
3.79k
          zval *cond_zv = zend_ast_get_zval(cond_ast);
6670
3.79k
          zval jmp_target;
6671
3.79k
          ZVAL_LONG(&jmp_target, get_next_op_number());
6672
6673
3.79k
          if (Z_TYPE_P(cond_zv) == IS_LONG) {
6674
3.20k
            zend_hash_index_add(jumptable, Z_LVAL_P(cond_zv), &jmp_target);
6675
3.20k
          } else {
6676
595
            ZEND_ASSERT(Z_TYPE_P(cond_zv) == IS_STRING);
6677
595
            zend_hash_add(jumptable, Z_STR_P(cond_zv), &jmp_target);
6678
595
          }
6679
3.79k
        }
6680
6681
10.8k
        cond_count++;
6682
10.8k
      }
6683
4.72k
    } else {
6684
629
      if (!uses_jumptable) {
6685
343
        zend_update_jump_target_to_next(opnum_default_jmp);
6686
343
      }
6687
6688
629
      if (jumptable) {
6689
286
        ZEND_ASSERT(opnum_match != (uint32_t)-1);
6690
286
        zend_op *opline = &CG(active_op_array)->opcodes[opnum_match];
6691
286
        opline->extended_value = get_next_op_number();
6692
286
      }
6693
629
    }
6694
6695
5.35k
    znode body_node;
6696
5.35k
    zend_compile_expr(&body_node, body_ast);
6697
6698
5.35k
    if (is_first_case) {
6699
3.09k
      zend_emit_op_tmp(result, ZEND_QM_ASSIGN, &body_node, NULL);
6700
3.09k
      is_first_case = false;
6701
3.09k
    } else {
6702
2.26k
      zend_op *opline_qm_assign = zend_emit_op(NULL, ZEND_QM_ASSIGN, &body_node, NULL);
6703
2.26k
      SET_NODE(opline_qm_assign->result, result);
6704
2.26k
    }
6705
6706
5.35k
    jmp_end_opnums[i] = zend_emit_jump(0);
6707
5.35k
  }
6708
6709
  // Initialize result in case there is no arm
6710
3.55k
  if (arms->children == 0) {
6711
461
    result->op_type = IS_CONST;
6712
461
    ZVAL_NULL(&result->u.constant);
6713
461
  }
6714
6715
8.91k
  for (uint32_t i = 0; i < arms->children; ++i) {
6716
5.35k
    zend_update_jump_target_to_next(jmp_end_opnums[i]);
6717
5.35k
  }
6718
6719
3.55k
  if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) {
6720
2.31k
    zend_op *opline = zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
6721
2.31k
    opline->extended_value = ZEND_FREE_SWITCH;
6722
2.31k
  } else if (expr_node.op_type == IS_CONST) {
6723
840
    zval_ptr_dtor_nogc(&expr_node.u.constant);
6724
840
  }
6725
6726
3.55k
  if (jmpnz_opnums != NULL) {
6727
2.69k
    efree(jmpnz_opnums);
6728
2.69k
  }
6729
3.55k
  efree(jmp_end_opnums);
6730
3.55k
}
6731
6732
static void zend_compile_try(zend_ast *ast) /* {{{ */
6733
46.9k
{
6734
46.9k
  zend_ast *try_ast = ast->child[0];
6735
46.9k
  zend_ast_list *catches = zend_ast_get_list(ast->child[1]);
6736
46.9k
  zend_ast *finally_ast = ast->child[2];
6737
6738
46.9k
  uint32_t i, j;
6739
46.9k
  zend_op *opline;
6740
46.9k
  uint32_t try_catch_offset;
6741
46.9k
  uint32_t *jmp_opnums = safe_emalloc(sizeof(uint32_t), catches->children, 0);
6742
46.9k
  uint32_t orig_fast_call_var = CG(context).fast_call_var;
6743
46.9k
  uint32_t orig_try_catch_offset = CG(context).try_catch_offset;
6744
6745
46.9k
  if (catches->children == 0 && !finally_ast) {
6746
70
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally");
6747
70
  }
6748
6749
  /* label: try { } must not be equal to try { label: } */
6750
46.9k
  if (CG(context).labels) {
6751
451
    zend_label *label;
6752
451
    ZEND_HASH_MAP_REVERSE_FOREACH_PTR(CG(context).labels, label) {
6753
451
      if (label->opline_num == get_next_op_number()) {
6754
245
        zend_emit_op(NULL, ZEND_NOP, NULL, NULL);
6755
245
      }
6756
451
      break;
6757
1.35k
    } ZEND_HASH_FOREACH_END();
6758
451
  }
6759
6760
46.9k
  try_catch_offset = zend_add_try_element(get_next_op_number());
6761
6762
46.9k
  if (finally_ast) {
6763
12.4k
    zend_loop_var fast_call;
6764
12.4k
    if (!(CG(active_op_array)->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) {
6765
2.29k
      CG(active_op_array)->fn_flags |= ZEND_ACC_HAS_FINALLY_BLOCK;
6766
2.29k
    }
6767
12.4k
    CG(context).fast_call_var = get_temporary_variable();
6768
6769
    /* Push FAST_CALL on unwind stack */
6770
12.4k
    fast_call.opcode = ZEND_FAST_CALL;
6771
12.4k
    fast_call.var_type = IS_TMP_VAR;
6772
12.4k
    fast_call.var_num = CG(context).fast_call_var;
6773
12.4k
    fast_call.try_catch_offset = try_catch_offset;
6774
12.4k
    zend_stack_push(&CG(loop_var_stack), &fast_call);
6775
12.4k
  }
6776
6777
46.9k
  CG(context).try_catch_offset = try_catch_offset;
6778
6779
46.9k
  zend_compile_stmt(try_ast);
6780
6781
46.9k
  if (catches->children != 0) {
6782
34.5k
    jmp_opnums[0] = zend_emit_jump(0);
6783
34.5k
  }
6784
6785
86.2k
  for (i = 0; i < catches->children; ++i) {
6786
39.3k
    zend_ast *catch_ast = catches->child[i];
6787
39.3k
    zend_ast_list *classes = zend_ast_get_list(catch_ast->child[0]);
6788
39.3k
    zend_ast *var_ast = catch_ast->child[1];
6789
39.3k
    zend_ast *stmt_ast = catch_ast->child[2];
6790
39.3k
    zend_string *var_name = var_ast ? zval_make_interned_string(zend_ast_get_zval(var_ast)) : NULL;
6791
39.3k
    bool is_last_catch = (i + 1 == catches->children);
6792
6793
39.3k
    uint32_t *jmp_multicatch = safe_emalloc(sizeof(uint32_t), classes->children - 1, 0);
6794
39.3k
    uint32_t opnum_catch = (uint32_t)-1;
6795
6796
39.3k
    CG(zend_lineno) = catch_ast->lineno;
6797
6798
83.9k
    for (j = 0; j < classes->children; j++) {
6799
44.5k
      zend_ast *class_ast = classes->child[j];
6800
44.5k
      bool is_last_class = (j + 1 == classes->children);
6801
6802
44.5k
      if (!zend_is_const_default_class_ref(class_ast)) {
6803
7
        zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement");
6804
7
      }
6805
6806
44.5k
      opnum_catch = get_next_op_number();
6807
44.5k
      if (i == 0 && j == 0) {
6808
34.5k
        CG(active_op_array)->try_catch_array[try_catch_offset].catch_op = opnum_catch;
6809
34.5k
      }
6810
6811
44.5k
      opline = get_next_op();
6812
44.5k
      opline->opcode = ZEND_CATCH;
6813
44.5k
      opline->op1_type = IS_CONST;
6814
44.5k
      opline->op1.constant = zend_add_class_name_literal(
6815
44.5k
          zend_resolve_class_name_ast(class_ast));
6816
44.5k
      opline->extended_value = zend_alloc_cache_slot();
6817
6818
44.5k
      if (var_name && zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) {
6819
7
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
6820
7
      }
6821
6822
44.5k
      opline->result_type = var_name ? IS_CV : IS_UNUSED;
6823
44.5k
      opline->result.var = var_name ? lookup_cv(var_name) : -1;
6824
6825
44.5k
      if (is_last_catch && is_last_class) {
6826
34.5k
        opline->extended_value |= ZEND_LAST_CATCH;
6827
34.5k
      }
6828
6829
44.5k
      if (!is_last_class) {
6830
5.21k
        jmp_multicatch[j] = zend_emit_jump(0);
6831
5.21k
        opline = &CG(active_op_array)->opcodes[opnum_catch];
6832
5.21k
        opline->op2.opline_num = get_next_op_number();
6833
5.21k
      }
6834
44.5k
    }
6835
6836
44.5k
    for (j = 0; j < classes->children - 1; j++) {
6837
5.21k
      zend_update_jump_target_to_next(jmp_multicatch[j]);
6838
5.21k
    }
6839
6840
39.3k
    efree(jmp_multicatch);
6841
6842
39.3k
    zend_compile_stmt(stmt_ast);
6843
6844
39.3k
    if (!is_last_catch) {
6845
4.77k
      jmp_opnums[i + 1] = zend_emit_jump(0);
6846
4.77k
    }
6847
6848
39.3k
    ZEND_ASSERT(opnum_catch != (uint32_t)-1 && "Should have at least one class");
6849
39.3k
    opline = &CG(active_op_array)->opcodes[opnum_catch];
6850
39.3k
    if (!is_last_catch) {
6851
4.77k
      opline->op2.opline_num = get_next_op_number();
6852
4.77k
    }
6853
39.3k
  }
6854
6855
86.2k
  for (i = 0; i < catches->children; ++i) {
6856
39.3k
    zend_update_jump_target_to_next(jmp_opnums[i]);
6857
39.3k
  }
6858
6859
46.8k
  if (finally_ast) {
6860
12.4k
    zend_loop_var discard_exception;
6861
12.4k
    uint32_t opnum_jmp = get_next_op_number() + 1;
6862
6863
    /* Pop FAST_CALL from unwind stack */
6864
12.4k
    zend_stack_del_top(&CG(loop_var_stack));
6865
6866
    /* Push DISCARD_EXCEPTION on unwind stack */
6867
12.4k
    discard_exception.opcode = ZEND_DISCARD_EXCEPTION;
6868
12.4k
    discard_exception.var_type = IS_TMP_VAR;
6869
12.4k
    discard_exception.var_num = CG(context).fast_call_var;
6870
12.4k
    zend_stack_push(&CG(loop_var_stack), &discard_exception);
6871
6872
12.4k
    CG(zend_lineno) = finally_ast->lineno;
6873
6874
12.4k
    opline = zend_emit_op(NULL, ZEND_FAST_CALL, NULL, NULL);
6875
12.4k
    opline->op1.num = try_catch_offset;
6876
12.4k
    opline->result_type = IS_TMP_VAR;
6877
12.4k
    opline->result.var = CG(context).fast_call_var;
6878
6879
12.4k
    zend_emit_op(NULL, ZEND_JMP, NULL, NULL);
6880
6881
12.4k
    zend_compile_stmt(finally_ast);
6882
6883
12.4k
    CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = opnum_jmp + 1;
6884
12.4k
    CG(active_op_array)->try_catch_array[try_catch_offset].finally_end
6885
12.4k
      = get_next_op_number();
6886
6887
12.4k
    opline = zend_emit_op(NULL, ZEND_FAST_RET, NULL, NULL);
6888
12.4k
    opline->op1_type = IS_TMP_VAR;
6889
12.4k
    opline->op1.var = CG(context).fast_call_var;
6890
12.4k
    opline->op2.num = orig_try_catch_offset;
6891
6892
12.4k
    zend_update_jump_target_to_next(opnum_jmp);
6893
6894
12.4k
    CG(context).fast_call_var = orig_fast_call_var;
6895
6896
    /* Pop DISCARD_EXCEPTION from unwind stack */
6897
12.4k
    zend_stack_del_top(&CG(loop_var_stack));
6898
12.4k
  }
6899
6900
46.8k
  CG(context).try_catch_offset = orig_try_catch_offset;
6901
6902
46.8k
  efree(jmp_opnums);
6903
46.8k
}
6904
/* }}} */
6905
6906
/* Encoding declarations must already be handled during parsing */
6907
bool zend_handle_encoding_declaration(zend_ast *ast) /* {{{ */
6908
2.62k
{
6909
2.62k
  zend_ast_list *declares = zend_ast_get_list(ast);
6910
2.62k
  uint32_t i;
6911
8.24k
  for (i = 0; i < declares->children; ++i) {
6912
5.63k
    zend_ast *declare_ast = declares->child[i];
6913
5.63k
    zend_ast *name_ast = declare_ast->child[0];
6914
5.63k
    zend_ast *value_ast = declare_ast->child[1];
6915
5.63k
    zend_string *name = zend_ast_get_str(name_ast);
6916
6917
5.63k
    if (zend_string_equals_literal_ci(name, "encoding")) {
6918
210
      if (value_ast->kind != ZEND_AST_ZVAL) {
6919
20
        zend_throw_exception(zend_ce_compile_error, "Encoding must be a literal", 0);
6920
20
        return 0;
6921
20
      }
6922
6923
190
      if (CG(multibyte)) {
6924
0
        zend_string *encoding_name = zval_get_string(zend_ast_get_zval(value_ast));
6925
6926
0
        const zend_encoding *new_encoding, *old_encoding;
6927
0
        zend_encoding_filter old_input_filter;
6928
6929
0
        CG(encoding_declared) = 1;
6930
6931
0
        new_encoding = zend_multibyte_fetch_encoding(ZSTR_VAL(encoding_name));
6932
0
        if (!new_encoding) {
6933
0
          zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", ZSTR_VAL(encoding_name));
6934
0
        } else {
6935
0
          old_input_filter = LANG_SCNG(input_filter);
6936
0
          old_encoding = LANG_SCNG(script_encoding);
6937
0
          zend_multibyte_set_filter(new_encoding);
6938
6939
          /* need to re-scan if input filter changed */
6940
0
          if (old_input_filter != LANG_SCNG(input_filter) ||
6941
0
             (old_input_filter && new_encoding != old_encoding)) {
6942
0
            zend_multibyte_yyinput_again(old_input_filter, old_encoding);
6943
0
          }
6944
0
        }
6945
6946
0
        zend_string_release_ex(encoding_name, 0);
6947
190
      } else {
6948
190
        zend_error(E_COMPILE_WARNING, "declare(encoding=...) ignored because "
6949
190
          "Zend multibyte feature is turned off by settings");
6950
190
      }
6951
190
    }
6952
5.63k
  }
6953
6954
2.60k
  return 1;
6955
2.62k
}
6956
/* }}} */
6957
6958
/* Check whether this is the first statement, not counting declares. */
6959
static zend_result zend_is_first_statement(zend_ast *ast, bool allow_nop) /* {{{ */
6960
4.02k
{
6961
4.02k
  uint32_t i = 0;
6962
4.02k
  zend_ast_list *file_ast = zend_ast_get_list(CG(ast));
6963
6964
23.0k
  while (i < file_ast->children) {
6965
23.0k
    if (file_ast->child[i] == ast) {
6966
3.96k
      return SUCCESS;
6967
19.1k
    } else if (file_ast->child[i] == NULL) {
6968
339
      if (!allow_nop) {
6969
0
        return FAILURE;
6970
0
      }
6971
18.7k
    } else if (file_ast->child[i]->kind != ZEND_AST_DECLARE) {
6972
62
      return FAILURE;
6973
62
    }
6974
19.0k
    i++;
6975
19.0k
  }
6976
2
  return FAILURE;
6977
4.02k
}
6978
/* }}} */
6979
6980
static void zend_compile_declare(zend_ast *ast) /* {{{ */
6981
5.24k
{
6982
5.24k
  zend_ast_list *declares = zend_ast_get_list(ast->child[0]);
6983
5.24k
  zend_ast *stmt_ast = ast->child[1];
6984
5.24k
  zend_declarables orig_declarables = FC(declarables);
6985
5.24k
  uint32_t i;
6986
6987
13.7k
  for (i = 0; i < declares->children; ++i) {
6988
8.62k
    zend_ast *declare_ast = declares->child[i];
6989
8.62k
    zend_ast *name_ast = declare_ast->child[0];
6990
8.62k
    zend_ast **value_ast_ptr = &declare_ast->child[1];
6991
8.62k
    zend_string *name = zend_ast_get_str(name_ast);
6992
6993
8.62k
    if ((*value_ast_ptr)->kind != ZEND_AST_ZVAL) {
6994
30
      zend_error_noreturn(E_COMPILE_ERROR, "declare(%s) value must be a literal", ZSTR_VAL(name));
6995
30
    }
6996
6997
8.59k
    if (zend_string_equals_literal_ci(name, "ticks")) {
6998
2.34k
      zval value_zv;
6999
2.34k
      zend_const_expr_to_zval(&value_zv, value_ast_ptr, /* allow_dynamic */ false);
7000
2.34k
      FC(declarables).ticks = zval_get_long(&value_zv);
7001
2.34k
      zval_ptr_dtor_nogc(&value_zv);
7002
6.24k
    } else if (zend_string_equals_literal_ci(name, "encoding")) {
7003
7004
141
      if (FAILURE == zend_is_first_statement(ast, /* allow_nop */ false)) {
7005
9
        zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be "
7006
9
          "the very first statement in the script");
7007
9
      }
7008
6.10k
    } else if (zend_string_equals_literal_ci(name, "strict_types")) {
7009
597
      zval value_zv;
7010
7011
597
      if (FAILURE == zend_is_first_statement(ast, /* allow_nop */ true)) {
7012
17
        zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must be "
7013
17
          "the very first statement in the script");
7014
17
      }
7015
7016
580
      if (ast->child[1] != NULL) {
7017
7
        zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must not "
7018
7
          "use block mode");
7019
7
      }
7020
7021
573
      zend_const_expr_to_zval(&value_zv, value_ast_ptr, /* allow_dynamic */ false);
7022
7023
573
      if (Z_TYPE(value_zv) != IS_LONG || (Z_LVAL(value_zv) != 0 && Z_LVAL(value_zv) != 1)) {
7024
56
        zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must have 0 or 1 as its value");
7025
56
      }
7026
7027
517
      if (Z_LVAL(value_zv) == 1) {
7028
379
        CG(active_op_array)->fn_flags |= ZEND_ACC_STRICT_TYPES;
7029
379
      }
7030
7031
5.51k
    } else {
7032
5.51k
      zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", ZSTR_VAL(name));
7033
5.51k
    }
7034
8.59k
  }
7035
7036
5.12k
  if (stmt_ast) {
7037
876
    zend_compile_stmt(stmt_ast);
7038
7039
876
    FC(declarables) = orig_declarables;
7040
876
  }
7041
5.12k
}
7042
/* }}} */
7043
7044
static void zend_compile_stmt_list(zend_ast *ast) /* {{{ */
7045
1.03M
{
7046
1.03M
  zend_ast_list *list = zend_ast_get_list(ast);
7047
1.03M
  uint32_t i;
7048
4.02M
  for (i = 0; i < list->children; ++i) {
7049
2.98M
    zend_compile_stmt(list->child[i]);
7050
2.98M
  }
7051
1.03M
}
7052
/* }}} */
7053
7054
ZEND_API void zend_set_function_arg_flags(zend_function *func) /* {{{ */
7055
684k
{
7056
684k
  uint32_t i, n;
7057
7058
684k
  func->common.arg_flags[0] = 0;
7059
684k
  func->common.arg_flags[1] = 0;
7060
684k
  func->common.arg_flags[2] = 0;
7061
684k
  if (func->common.arg_info) {
7062
684k
    n = MIN(func->common.num_args, MAX_ARG_FLAG_NUM);
7063
684k
    i = 0;
7064
1.42M
    while (i < n) {
7065
744k
      ZEND_SET_ARG_FLAG(func, i + 1, ZEND_ARG_SEND_MODE(&func->common.arg_info[i]));
7066
744k
      i++;
7067
744k
    }
7068
684k
    if (UNEXPECTED((func->common.fn_flags & ZEND_ACC_VARIADIC) && ZEND_ARG_SEND_MODE(&func->common.arg_info[i]))) {
7069
608
      uint32_t pass_by_reference = ZEND_ARG_SEND_MODE(&func->common.arg_info[i]);
7070
7.80k
      while (i < MAX_ARG_FLAG_NUM) {
7071
7.19k
        ZEND_SET_ARG_FLAG(func, i + 1, pass_by_reference);
7072
7.19k
        i++;
7073
7.19k
      }
7074
608
    }
7075
684k
  }
7076
684k
}
7077
/* }}} */
7078
7079
static zend_type zend_compile_single_typename(zend_ast *ast)
7080
456k
{
7081
456k
  ZEND_ASSERT(!(ast->attr & ZEND_TYPE_NULLABLE));
7082
456k
  if (ast->kind == ZEND_AST_TYPE) {
7083
6.09k
    if (ast->attr == IS_STATIC && !CG(active_class_entry) && zend_is_scope_known()) {
7084
10
      zend_error_noreturn(E_COMPILE_ERROR,
7085
10
        "Cannot use \"static\" when no class scope is active");
7086
10
    }
7087
7088
6.08k
    return (zend_type) ZEND_TYPE_INIT_CODE(ast->attr, 0, 0);
7089
450k
  } else {
7090
450k
    zend_string *type_name = zend_ast_get_str(ast);
7091
450k
    uint8_t type_code = zend_lookup_builtin_type_by_name(type_name);
7092
7093
450k
    if (type_code != 0) {
7094
265k
      if ((ast->attr & ZEND_NAME_NOT_FQ) != ZEND_NAME_NOT_FQ) {
7095
7
        zend_error_noreturn(E_COMPILE_ERROR,
7096
7
          "Type declaration '%s' must be unqualified",
7097
7
          ZSTR_VAL(zend_string_tolower(type_name)));
7098
7
      }
7099
7100
      /* Transform iterable into a type union alias */
7101
265k
      if (type_code == IS_ITERABLE) {
7102
        /* Set iterable bit for BC compat during Reflection and string representation of type */
7103
234k
        zend_type iterable = (zend_type) ZEND_TYPE_INIT_CLASS_MASK(ZSTR_KNOWN(ZEND_STR_TRAVERSABLE),
7104
234k
                  (MAY_BE_ARRAY|_ZEND_TYPE_ITERABLE_BIT));
7105
234k
        return iterable;
7106
234k
      }
7107
7108
30.1k
      return (zend_type) ZEND_TYPE_INIT_CODE(type_code, 0, 0);
7109
265k
    } else {
7110
185k
      const char *correct_name;
7111
185k
      uint32_t fetch_type = zend_get_class_fetch_type_ast(ast);
7112
185k
      zend_string *class_name = type_name;
7113
7114
185k
      if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
7115
184k
        class_name = zend_resolve_class_name_ast(ast);
7116
184k
        zend_assert_valid_class_name(class_name, "a type name");
7117
184k
      } else {
7118
922
        ZEND_ASSERT(fetch_type == ZEND_FETCH_CLASS_SELF || fetch_type == ZEND_FETCH_CLASS_PARENT);
7119
7120
922
        zend_ensure_valid_class_fetch_type(fetch_type);
7121
7122
922
        bool substitute_self_parent = zend_is_scope_known()
7123
517
          && !(CG(active_class_entry)->ce_flags & ZEND_ACC_ANON_CLASS);
7124
7125
922
        if (fetch_type == ZEND_FETCH_CLASS_SELF) {
7126
          /* Scope might be unknown for unbound closures and traits */
7127
698
          if (substitute_self_parent) {
7128
363
            class_name = CG(active_class_entry)->name;
7129
363
            ZEND_ASSERT(class_name && "must know class name when resolving self type at compile time");
7130
363
          }
7131
698
        } else {
7132
224
          ZEND_ASSERT(fetch_type == ZEND_FETCH_CLASS_PARENT);
7133
          /* Scope might be unknown for unbound closures and traits */
7134
224
          if (substitute_self_parent) {
7135
139
            class_name = CG(active_class_entry)->parent_name;
7136
139
            ZEND_ASSERT(class_name && "must know class name when resolving parent type at compile time");
7137
139
          }
7138
201
        }
7139
922
        zend_string_addref(class_name);
7140
899
      }
7141
7142
185k
      if (ast->attr == ZEND_NAME_NOT_FQ
7143
184k
          && zend_is_confusable_type(type_name, &correct_name)
7144
914
          && zend_is_not_imported(type_name)) {
7145
900
        const char *extra =
7146
900
          FC(current_namespace) ? " or import the class with \"use\"" : "";
7147
900
        if (correct_name) {
7148
374
          zend_error(E_COMPILE_WARNING,
7149
374
            "\"%s\" will be interpreted as a class name. Did you mean \"%s\"? "
7150
374
            "Write \"\\%s\"%s to suppress this warning",
7151
374
            ZSTR_VAL(type_name), correct_name, ZSTR_VAL(class_name), extra);
7152
526
        } else {
7153
526
          zend_error(E_COMPILE_WARNING,
7154
526
            "\"%s\" is not a supported builtin type "
7155
526
            "and will be interpreted as a class name. "
7156
526
            "Write \"\\%s\"%s to suppress this warning",
7157
526
            ZSTR_VAL(type_name), ZSTR_VAL(class_name), extra);
7158
526
        }
7159
900
      }
7160
7161
185k
      class_name = zend_new_interned_string(class_name);
7162
185k
      zend_alloc_ce_cache(class_name);
7163
185k
      return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, /* allow null */ false, 0);
7164
185k
    }
7165
450k
  }
7166
456k
}
7167
7168
static void zend_are_intersection_types_redundant(const zend_type left_type, const zend_type right_type)
7169
12.7k
{
7170
12.7k
  ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(left_type));
7171
12.7k
  ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(right_type));
7172
12.7k
  zend_type_list *l_type_list = ZEND_TYPE_LIST(left_type);
7173
12.7k
  zend_type_list *r_type_list = ZEND_TYPE_LIST(right_type);
7174
12.7k
  zend_type_list *smaller_type_list, *larger_type_list;
7175
12.7k
  bool flipped = false;
7176
7177
12.7k
  if (r_type_list->num_types < l_type_list->num_types) {
7178
3.85k
    smaller_type_list = r_type_list;
7179
3.85k
    larger_type_list = l_type_list;
7180
3.85k
    flipped = true;
7181
8.90k
  } else {
7182
8.90k
    smaller_type_list = l_type_list;
7183
8.90k
    larger_type_list = r_type_list;
7184
8.90k
  }
7185
7186
12.7k
  unsigned int sum = 0;
7187
12.7k
  const zend_type *outer_type;
7188
49.6k
  ZEND_TYPE_LIST_FOREACH(smaller_type_list, outer_type)
7189
49.6k
    const zend_type *inner_type;
7190
166k
    ZEND_TYPE_LIST_FOREACH(larger_type_list, inner_type)
7191
166k
      if (zend_string_equals_ci(ZEND_TYPE_NAME(*inner_type), ZEND_TYPE_NAME(*outer_type))) {
7192
13.0k
        sum++;
7193
13.0k
        break;
7194
13.0k
      }
7195
166k
    ZEND_TYPE_LIST_FOREACH_END();
7196
49.6k
  ZEND_TYPE_LIST_FOREACH_END();
7197
7198
12.7k
  if (sum == smaller_type_list->num_types) {
7199
27
    zend_string *smaller_type_str;
7200
27
    zend_string *larger_type_str;
7201
27
    if (flipped) {
7202
7
      smaller_type_str = zend_type_to_string(right_type);
7203
7
      larger_type_str = zend_type_to_string(left_type);
7204
20
    } else {
7205
20
      smaller_type_str = zend_type_to_string(left_type);
7206
20
      larger_type_str = zend_type_to_string(right_type);
7207
20
    }
7208
27
    if (smaller_type_list->num_types == larger_type_list->num_types) {
7209
14
      zend_error_noreturn(E_COMPILE_ERROR, "Type %s is redundant with type %s",
7210
14
        ZSTR_VAL(smaller_type_str), ZSTR_VAL(larger_type_str));
7211
14
    } else {
7212
13
      zend_error_noreturn(E_COMPILE_ERROR, "Type %s is redundant as it is more restrictive than type %s",
7213
13
        ZSTR_VAL(larger_type_str), ZSTR_VAL(smaller_type_str));
7214
13
    }
7215
27
  }
7216
12.7k
}
7217
7218
static void zend_is_intersection_type_redundant_by_single_type(const zend_type intersection_type, const zend_type single_type)
7219
19.6k
{
7220
19.6k
  ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(intersection_type));
7221
19.6k
  ZEND_ASSERT(!ZEND_TYPE_IS_INTERSECTION(single_type));
7222
7223
19.6k
  const zend_type *single_intersection_type = NULL;
7224
69.3k
  ZEND_TYPE_FOREACH(intersection_type, single_intersection_type)
7225
69.3k
    if (zend_string_equals_ci(ZEND_TYPE_NAME(*single_intersection_type), ZEND_TYPE_NAME(single_type))) {
7226
10
      zend_string *single_type_str = zend_type_to_string(single_type);
7227
10
      zend_string *complete_type = zend_type_to_string(intersection_type);
7228
10
      zend_error_noreturn(E_COMPILE_ERROR, "Type %s is redundant as it is more restrictive than type %s",
7229
10
          ZSTR_VAL(complete_type), ZSTR_VAL(single_type_str));
7230
10
    }
7231
69.3k
  ZEND_TYPE_FOREACH_END();
7232
19.6k
}
7233
7234
/* Used by both intersection and union types prior to transforming the type list to a full zend_type */
7235
static void zend_is_type_list_redundant_by_single_type(const zend_type_list *type_list, const zend_type type)
7236
74.8k
{
7237
74.8k
  ZEND_ASSERT(!ZEND_TYPE_IS_INTERSECTION(type));
7238
143k
  for (size_t i = 0; i < type_list->num_types - 1; i++) {
7239
68.4k
    if (ZEND_TYPE_IS_INTERSECTION(type_list->types[i])) {
7240
15.7k
      zend_is_intersection_type_redundant_by_single_type(type_list->types[i], type);
7241
15.7k
      continue;
7242
15.7k
    }
7243
52.6k
    if (zend_string_equals_ci(ZEND_TYPE_NAME(type_list->types[i]), ZEND_TYPE_NAME(type))) {
7244
52
      zend_string *single_type_str = zend_type_to_string(type);
7245
52
      zend_error_noreturn(E_COMPILE_ERROR, "Duplicate type %s is redundant", ZSTR_VAL(single_type_str));
7246
52
    }
7247
52.6k
  }
7248
74.8k
}
7249
7250
static zend_type zend_compile_typename(zend_ast *ast);
7251
7252
static zend_type zend_compile_typename_ex(
7253
    zend_ast *ast, bool force_allow_null, bool *forced_allow_null) /* {{{ */
7254
408k
{
7255
408k
  bool is_marked_nullable = ast->attr & ZEND_TYPE_NULLABLE;
7256
408k
  zend_ast_attr orig_ast_attr = ast->attr;
7257
408k
  zend_type type = ZEND_TYPE_INIT_NONE(0);
7258
7259
408k
  if (is_marked_nullable) {
7260
2.81k
    ast->attr &= ~ZEND_TYPE_NULLABLE;
7261
2.81k
  }
7262
7263
408k
  if (ast->kind == ZEND_AST_TYPE_UNION) {
7264
34.1k
    zend_ast_list *list = zend_ast_get_list(ast);
7265
34.1k
    zend_type_list *type_list;
7266
34.1k
    bool is_composite = false;
7267
34.1k
    bool has_only_iterable_class = true;
7268
34.1k
    ALLOCA_FLAG(use_heap)
7269
7270
34.1k
    type_list = do_alloca(ZEND_TYPE_LIST_SIZE(list->children), use_heap);
7271
34.1k
    type_list->num_types = 0;
7272
7273
107k
    for (uint32_t i = 0; i < list->children; i++) {
7274
72.9k
      zend_ast *type_ast = list->child[i];
7275
72.9k
      zend_type single_type;
7276
72.9k
      uint32_t type_mask = ZEND_TYPE_FULL_MASK(type);
7277
7278
72.9k
      if (type_ast->kind == ZEND_AST_TYPE_INTERSECTION) {
7279
14.7k
        has_only_iterable_class = false;
7280
14.7k
        is_composite = true;
7281
        /* The first class type can be stored directly as the type ptr payload. */
7282
14.7k
        if (ZEND_TYPE_IS_COMPLEX(type) && !ZEND_TYPE_HAS_LIST(type)) {
7283
          /* Switch from single name to name list. */
7284
346
          type_list->num_types = 1;
7285
346
          type_list->types[0] = type;
7286
          /* Clear MAY_BE_* type flags */
7287
346
          ZEND_TYPE_FULL_MASK(type_list->types[0]) &= ~_ZEND_TYPE_MAY_BE_MASK;
7288
346
        }
7289
        /* Mark type as list type */
7290
14.7k
        ZEND_TYPE_SET_LIST(type, type_list);
7291
7292
14.7k
        single_type = zend_compile_typename(type_ast);
7293
14.7k
        ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(single_type));
7294
7295
14.7k
        type_list->types[type_list->num_types++] = single_type;
7296
7297
        /* Check for trivially redundant class types */
7298
31.3k
        for (size_t i = 0; i < type_list->num_types - 1; i++) {
7299
16.6k
          if (ZEND_TYPE_IS_INTERSECTION(type_list->types[i])) {
7300
12.7k
            zend_are_intersection_types_redundant(single_type, type_list->types[i]);
7301
12.7k
            continue;
7302
12.7k
          }
7303
          /* Type from type list is a simple type */
7304
3.84k
          zend_is_intersection_type_redundant_by_single_type(single_type, type_list->types[i]);
7305
3.84k
        }
7306
14.7k
        continue;
7307
14.7k
      }
7308
7309
58.1k
      single_type = zend_compile_single_typename(type_ast);
7310
58.1k
      uint32_t single_type_mask = ZEND_TYPE_PURE_MASK(single_type);
7311
7312
58.1k
      if (single_type_mask == MAY_BE_ANY) {
7313
7
        zend_error_noreturn(E_COMPILE_ERROR, "Type mixed can only be used as a standalone type");
7314
7
      }
7315
58.1k
      if (ZEND_TYPE_IS_COMPLEX(single_type) && !ZEND_TYPE_IS_ITERABLE_FALLBACK(single_type)) {
7316
51.1k
        has_only_iterable_class = false;
7317
51.1k
      }
7318
7319
58.1k
      uint32_t type_mask_overlap = ZEND_TYPE_PURE_MASK(type) & single_type_mask;
7320
58.1k
      if (type_mask_overlap) {
7321
48
        zend_type overlap_type = ZEND_TYPE_INIT_MASK(type_mask_overlap);
7322
48
        zend_string *overlap_type_str = zend_type_to_string(overlap_type);
7323
48
        zend_error_noreturn(E_COMPILE_ERROR,
7324
48
          "Duplicate type %s is redundant", ZSTR_VAL(overlap_type_str));
7325
48
      }
7326
7327
58.1k
      if ( ((type_mask & MAY_BE_TRUE) && (single_type_mask == MAY_BE_FALSE))
7328
58.1k
          || ((type_mask & MAY_BE_FALSE) && (single_type_mask == MAY_BE_TRUE)) ) {
7329
14
        zend_error_noreturn(E_COMPILE_ERROR,
7330
14
          "Type contains both true and false, bool must be used instead");
7331
14
      }
7332
58.0k
      ZEND_TYPE_FULL_MASK(type) |= ZEND_TYPE_PURE_MASK(single_type);
7333
      /* Clear MAY_BE_* type flags */
7334
58.0k
      ZEND_TYPE_FULL_MASK(single_type) &= ~_ZEND_TYPE_MAY_BE_MASK;
7335
7336
58.0k
      if (ZEND_TYPE_IS_COMPLEX(single_type)) {
7337
51.6k
        if (!ZEND_TYPE_IS_COMPLEX(type) && !is_composite) {
7338
          /* The first class type can be stored directly as the type ptr payload. */
7339
20.1k
          ZEND_TYPE_SET_PTR(type, ZEND_TYPE_NAME(single_type));
7340
20.1k
          ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_NAME_BIT;
7341
31.4k
        } else {
7342
31.4k
          if (type_list->num_types == 0) {
7343
            /* Switch from single name to name list. */
7344
18.4k
            type_list->num_types = 1;
7345
18.4k
            type_list->types[0] = type;
7346
            /* Clear MAY_BE_* type flags */
7347
18.4k
            ZEND_TYPE_FULL_MASK(type_list->types[0]) &= ~_ZEND_TYPE_MAY_BE_MASK;
7348
18.4k
            ZEND_TYPE_SET_LIST(type, type_list);
7349
18.4k
          }
7350
7351
31.4k
          type_list->types[type_list->num_types++] = single_type;
7352
7353
          /* Check for trivially redundant class types */
7354
31.4k
          zend_is_type_list_redundant_by_single_type(type_list, single_type);
7355
31.4k
        }
7356
51.6k
      }
7357
58.0k
    }
7358
7359
34.0k
    if (type_list->num_types) {
7360
30.6k
      zend_type_list *list = zend_arena_alloc(
7361
30.6k
        &CG(arena), ZEND_TYPE_LIST_SIZE(type_list->num_types));
7362
30.6k
      memcpy(list, type_list, ZEND_TYPE_LIST_SIZE(type_list->num_types));
7363
30.6k
      ZEND_TYPE_SET_LIST(type, list);
7364
30.6k
      ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT;
7365
      /* Inform that the type list is a union type */
7366
30.6k
      ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_UNION_BIT;
7367
30.6k
    }
7368
7369
34.0k
    free_alloca(type_list, use_heap);
7370
7371
34.0k
    uint32_t type_mask = ZEND_TYPE_FULL_MASK(type);
7372
34.0k
    if ((type_mask & MAY_BE_OBJECT) &&
7373
545
        ((!has_only_iterable_class && ZEND_TYPE_IS_COMPLEX(type)) || (type_mask & MAY_BE_STATIC))) {
7374
38
      zend_string *type_str = zend_type_to_string(type);
7375
38
      zend_error_noreturn(E_COMPILE_ERROR,
7376
38
        "Type %s contains both object and a class type, which is redundant",
7377
38
        ZSTR_VAL(type_str));
7378
38
    }
7379
374k
  } else if (ast->kind == ZEND_AST_TYPE_INTERSECTION) {
7380
19.9k
    zend_ast_list *list = zend_ast_get_list(ast);
7381
19.9k
    zend_type_list *type_list;
7382
7383
    /* Allocate the type list directly on the arena as it must be a type
7384
     * list of the same number of elements as the AST list has children */
7385
19.9k
    type_list = zend_arena_alloc(&CG(arena), ZEND_TYPE_LIST_SIZE(list->children));
7386
19.9k
    type_list->num_types = 0;
7387
7388
19.9k
    ZEND_ASSERT(list->children > 1);
7389
7390
63.3k
    for (uint32_t i = 0; i < list->children; i++) {
7391
43.5k
      zend_ast *type_ast = list->child[i];
7392
43.5k
      zend_type single_type = zend_compile_single_typename(type_ast);
7393
7394
      /* An intersection of union types cannot exist so invalidate it
7395
       * Currently only can happen with iterable getting canonicalized to Traversable|array */
7396
43.5k
      if (ZEND_TYPE_IS_ITERABLE_FALLBACK(single_type)) {
7397
7
        zend_string *standard_type_str = zend_type_to_string(single_type);
7398
7
        zend_error_noreturn(E_COMPILE_ERROR,
7399
7
          "Type %s cannot be part of an intersection type", ZSTR_VAL(standard_type_str));
7400
0
        zend_string_release_ex(standard_type_str, false);
7401
0
      }
7402
      /* An intersection of standard types cannot exist so invalidate it */
7403
43.5k
      if (ZEND_TYPE_IS_ONLY_MASK(single_type)) {
7404
83
        zend_string *standard_type_str = zend_type_to_string(single_type);
7405
83
        zend_error_noreturn(E_COMPILE_ERROR,
7406
83
          "Type %s cannot be part of an intersection type", ZSTR_VAL(standard_type_str));
7407
0
        zend_string_release_ex(standard_type_str, false);
7408
0
      }
7409
      /* Check for "self" and "parent" too */
7410
43.4k
      if (
7411
43.4k
        zend_string_equals_ci(ZEND_TYPE_NAME(single_type), ZSTR_KNOWN(ZEND_STR_SELF))
7412
43.4k
        || zend_string_equals_ci(ZEND_TYPE_NAME(single_type), ZSTR_KNOWN(ZEND_STR_PARENT))
7413
43.4k
      ) {
7414
14
        zend_error_noreturn(E_COMPILE_ERROR,
7415
14
          "Type %s cannot be part of an intersection type", ZSTR_VAL(ZEND_TYPE_NAME(single_type)));
7416
14
      }
7417
7418
      /* Add type to the type list */
7419
43.4k
      type_list->types[type_list->num_types++] = single_type;
7420
7421
      /* Check for trivially redundant class types */
7422
43.4k
      zend_is_type_list_redundant_by_single_type(type_list, single_type);
7423
43.4k
    }
7424
7425
19.8k
    ZEND_ASSERT(list->children == type_list->num_types);
7426
7427
    /* An implicitly nullable intersection type needs to be converted to a DNF type */
7428
19.8k
    if (force_allow_null) {
7429
3.10k
      zend_type intersection_type = ZEND_TYPE_INIT_NONE(0);
7430
3.10k
      ZEND_TYPE_SET_LIST(intersection_type, type_list);
7431
3.10k
      ZEND_TYPE_FULL_MASK(intersection_type) |= _ZEND_TYPE_INTERSECTION_BIT;
7432
3.10k
      ZEND_TYPE_FULL_MASK(intersection_type) |= _ZEND_TYPE_ARENA_BIT;
7433
7434
3.10k
      zend_type_list *dnf_type_list = zend_arena_alloc(&CG(arena), ZEND_TYPE_LIST_SIZE(1));
7435
3.10k
      dnf_type_list->num_types = 1;
7436
3.10k
      dnf_type_list->types[0] = intersection_type;
7437
3.10k
      ZEND_TYPE_SET_LIST(type, dnf_type_list);
7438
      /* Inform that the type list is a DNF type */
7439
3.10k
      ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_UNION_BIT;
7440
3.10k
      ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT;
7441
16.7k
    } else {
7442
16.7k
      ZEND_TYPE_SET_LIST(type, type_list);
7443
      /* Inform that the type list is an intersection type */
7444
16.7k
      ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_INTERSECTION_BIT;
7445
16.7k
      ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT;
7446
16.7k
    }
7447
354k
  } else {
7448
354k
    type = zend_compile_single_typename(ast);
7449
354k
  }
7450
7451
408k
  uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
7452
7453
408k
  if (type_mask == MAY_BE_ANY && is_marked_nullable) {
7454
22
    zend_error_noreturn(E_COMPILE_ERROR, "Type mixed cannot be marked as nullable since mixed already includes null");
7455
22
  }
7456
7457
408k
  if ((type_mask & MAY_BE_NULL) && is_marked_nullable) {
7458
7
    zend_error_noreturn(E_COMPILE_ERROR, "null cannot be marked as nullable");
7459
7
  }
7460
7461
408k
  if (force_allow_null && !is_marked_nullable && !(type_mask & MAY_BE_NULL)) {
7462
3.95k
    *forced_allow_null = true;
7463
3.95k
  }
7464
7465
408k
  if (is_marked_nullable || force_allow_null) {
7466
6.84k
    ZEND_TYPE_FULL_MASK(type) |= MAY_BE_NULL;
7467
6.84k
    type_mask = ZEND_TYPE_PURE_MASK(type);
7468
6.84k
  }
7469
7470
408k
  if ((type_mask & MAY_BE_VOID) && (ZEND_TYPE_IS_COMPLEX(type) || type_mask != MAY_BE_VOID)) {
7471
14
    zend_error_noreturn(E_COMPILE_ERROR, "Void can only be used as a standalone type");
7472
14
  }
7473
7474
408k
  if ((type_mask & MAY_BE_NEVER) && (ZEND_TYPE_IS_COMPLEX(type) || type_mask != MAY_BE_NEVER)) {
7475
8
    zend_error_noreturn(E_COMPILE_ERROR, "never can only be used as a standalone type");
7476
8
  }
7477
7478
408k
  ast->attr = orig_ast_attr;
7479
408k
  return type;
7480
408k
}
7481
/* }}} */
7482
7483
static zend_type zend_compile_typename(zend_ast *ast)
7484
74.5k
{
7485
74.5k
  bool forced_allow_null;
7486
74.5k
  return zend_compile_typename_ex(ast, false, &forced_allow_null);
7487
74.5k
}
7488
7489
/* May convert value from int to float. */
7490
static bool zend_is_valid_default_value(zend_type type, zval *value)
7491
2.62k
{
7492
2.62k
  ZEND_ASSERT(ZEND_TYPE_IS_SET(type));
7493
2.62k
  if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(value))) {
7494
2.20k
    return 1;
7495
2.20k
  }
7496
420
  if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_DOUBLE) && Z_TYPE_P(value) == IS_LONG) {
7497
    /* Integers are allowed as initializers for floating-point values. */
7498
245
    convert_to_double(value);
7499
245
    return 1;
7500
245
  }
7501
175
  return 0;
7502
420
}
7503
7504
static void zend_compile_attributes(
7505
  HashTable **attributes, zend_ast *ast, uint32_t offset, uint32_t target, uint32_t promoted
7506
666k
) /* {{{ */ {
7507
666k
  zend_attribute *attr;
7508
666k
  zend_internal_attribute *config;
7509
7510
666k
  zend_ast_list *list = zend_ast_get_list(ast);
7511
666k
  uint32_t g, i, j;
7512
7513
666k
  ZEND_ASSERT(ast->kind == ZEND_AST_ATTRIBUTE_LIST);
7514
7515
1.33M
  for (g = 0; g < list->children; g++) {
7516
669k
    zend_ast_list *group = zend_ast_get_list(list->child[g]);
7517
7518
669k
    ZEND_ASSERT(group->kind == ZEND_AST_ATTRIBUTE_GROUP);
7519
7520
2.30M
    for (i = 0; i < group->children; i++) {
7521
1.63M
      ZEND_ASSERT(group->child[i]->kind == ZEND_AST_ATTRIBUTE);
7522
7523
1.63M
      zend_ast *el = group->child[i];
7524
7525
1.63M
      if (el->child[1] &&
7526
57.9k
          el->child[1]->kind == ZEND_AST_CALLABLE_CONVERT) {
7527
14
          zend_error_noreturn(E_COMPILE_ERROR,
7528
14
              "Cannot create Closure as attribute argument");
7529
14
      }
7530
7531
1.63M
      zend_string *name = zend_resolve_class_name_ast(el->child[0]);
7532
1.63M
      zend_string *lcname = zend_string_tolower_ex(name, false);
7533
1.63M
      zend_ast_list *args = el->child[1] ? zend_ast_get_list(el->child[1]) : NULL;
7534
7535
1.63M
      config = zend_internal_attribute_get(lcname);
7536
1.63M
      zend_string_release(lcname);
7537
7538
      /* Exclude internal attributes that do not match on promoted properties. */
7539
1.63M
      if (config && !(target & (config->flags & ZEND_ATTRIBUTE_TARGET_ALL))) {
7540
448
        if (promoted & (config->flags & ZEND_ATTRIBUTE_TARGET_ALL)) {
7541
12
          zend_string_release(name);
7542
12
          continue;
7543
12
        }
7544
448
      }
7545
7546
1.63M
      uint32_t flags = (CG(active_op_array)->fn_flags & ZEND_ACC_STRICT_TYPES)
7547
1.63M
        ? ZEND_ATTRIBUTE_STRICT_TYPES : 0;
7548
1.63M
      attr = zend_add_attribute(
7549
1.63M
        attributes, name, args ? args->children : 0, flags, offset, el->lineno);
7550
1.63M
      zend_string_release(name);
7551
7552
      /* Populate arguments */
7553
1.63M
      if (args) {
7554
57.8k
        ZEND_ASSERT(args->kind == ZEND_AST_ARG_LIST);
7555
7556
57.8k
        bool uses_named_args = false;
7557
128k
        for (j = 0; j < args->children; j++) {
7558
70.6k
          zend_ast **arg_ast_ptr = &args->child[j];
7559
70.6k
          zend_ast *arg_ast = *arg_ast_ptr;
7560
7561
70.6k
          if (arg_ast->kind == ZEND_AST_UNPACK) {
7562
7
            zend_error_noreturn(E_COMPILE_ERROR,
7563
7
              "Cannot use unpacking in attribute argument list");
7564
7
          }
7565
7566
70.6k
          if (arg_ast->kind == ZEND_AST_NAMED_ARG) {
7567
2.77k
            attr->args[j].name = zend_string_copy(zend_ast_get_str(arg_ast->child[0]));
7568
2.77k
            arg_ast_ptr = &arg_ast->child[1];
7569
2.77k
            uses_named_args = true;
7570
7571
14.2k
            for (uint32_t k = 0; k < j; k++) {
7572
11.5k
              if (attr->args[k].name &&
7573
9.19k
                  zend_string_equals(attr->args[k].name, attr->args[j].name)) {
7574
12
                zend_error_noreturn(E_COMPILE_ERROR, "Duplicate named parameter $%s",
7575
12
                  ZSTR_VAL(attr->args[j].name));
7576
12
              }
7577
11.5k
            }
7578
67.8k
          } else if (uses_named_args) {
7579
38
            zend_error_noreturn(E_COMPILE_ERROR,
7580
38
              "Cannot use positional argument after named argument");
7581
38
          }
7582
7583
70.5k
          zend_const_expr_to_zval(
7584
70.5k
            &attr->args[j].value, arg_ast_ptr, /* allow_dynamic */ true);
7585
70.5k
        }
7586
57.8k
      }
7587
1.63M
    }
7588
669k
  }
7589
7590
666k
  if (*attributes != NULL) {
7591
    /* Allow delaying target validation for forward compatibility. */
7592
666k
    zend_attribute *delayed_target_validation = NULL;
7593
666k
    if (target == ZEND_ATTRIBUTE_TARGET_PARAMETER) {
7594
55.3k
      ZEND_ASSERT(offset >= 1);
7595
      /* zend_get_parameter_attribute_str will add 1 too */
7596
55.3k
      delayed_target_validation = zend_get_parameter_attribute_str(
7597
55.3k
        *attributes,
7598
55.3k
        "delayedtargetvalidation",
7599
55.3k
        strlen("delayedtargetvalidation"),
7600
55.3k
        offset - 1
7601
55.3k
      );
7602
610k
    } else {
7603
610k
      delayed_target_validation = zend_get_attribute_str(
7604
610k
        *attributes,
7605
610k
        "delayedtargetvalidation",
7606
610k
        strlen("delayedtargetvalidation")
7607
610k
      );
7608
610k
    }
7609
    /* Validate attributes in a secondary loop (needed to detect repeated attributes). */
7610
6.29M
    ZEND_HASH_PACKED_FOREACH_PTR(*attributes, attr) {
7611
6.29M
      if (attr->offset != offset || NULL == (config = zend_internal_attribute_get(attr->lcname))) {
7612
2.47M
        continue;
7613
2.47M
      }
7614
7615
6.29M
      bool run_validator = true;
7616
3.96k
      if (!(target & (config->flags & ZEND_ATTRIBUTE_TARGET_ALL))) {
7617
252
        if (delayed_target_validation == NULL) {
7618
44
          zend_string *location = zend_get_attribute_target_names(target);
7619
44
          zend_string *allowed = zend_get_attribute_target_names(config->flags);
7620
7621
44
          zend_error_noreturn(E_ERROR, "Attribute \"%s\" cannot target %s (allowed targets: %s)",
7622
44
            ZSTR_VAL(attr->name), ZSTR_VAL(location), ZSTR_VAL(allowed)
7623
44
          );
7624
44
        }
7625
208
        run_validator = false;
7626
208
      }
7627
7628
3.92k
      if (!(config->flags & ZEND_ATTRIBUTE_IS_REPEATABLE)) {
7629
3.92k
        if (zend_is_attribute_repeated(*attributes, attr)) {
7630
26
          zend_error_noreturn(E_ERROR, "Attribute \"%s\" must not be repeated", ZSTR_VAL(attr->name));
7631
26
        }
7632
3.92k
      }
7633
7634
      /* Validators are not run if the target is already invalid */
7635
3.89k
      if (run_validator && config->validator != NULL) {
7636
1.89k
        zend_string *error = config->validator(attr, target, CG(active_class_entry));
7637
1.89k
        if (error != NULL) {
7638
355
          if (delayed_target_validation == NULL) {
7639
104
            zend_error_noreturn(E_COMPILE_ERROR, "%s", ZSTR_VAL(error));
7640
0
            zend_string_efree(error);
7641
251
          } else {
7642
251
            attr->validation_error = error;
7643
251
          }
7644
355
        }
7645
1.89k
      }
7646
3.89k
    } ZEND_HASH_FOREACH_END();
7647
666k
  }
7648
666k
}
7649
/* }}} */
7650
7651
static void zend_compile_property_hooks(
7652
    zend_property_info *prop_info, zend_string *prop_name,
7653
    zend_ast *prop_type_ast, zend_ast_list *hooks);
7654
7655
typedef struct {
7656
  zend_string *property_name;
7657
  bool uses_property;
7658
} find_property_usage_context;
7659
7660
static void zend_property_hook_find_property_usage(zend_ast **ast_ptr, void *_context) /* {{{ */
7661
27.9k
{
7662
27.9k
  zend_ast *ast = *ast_ptr;
7663
27.9k
  find_property_usage_context *context = (find_property_usage_context *) _context;
7664
7665
27.9k
  if (ast == NULL) {
7666
669
    return;
7667
27.3k
  } else if (ast->kind == ZEND_AST_PROP || ast->kind == ZEND_AST_NULLSAFE_PROP) {
7668
1.94k
    zend_ast *object_ast = ast->child[0];
7669
1.94k
    zend_ast *property_ast = ast->child[1];
7670
7671
1.94k
    if (object_ast->kind == ZEND_AST_VAR
7672
1.79k
     && object_ast->child[0]->kind == ZEND_AST_ZVAL
7673
1.72k
     && property_ast->kind == ZEND_AST_ZVAL) {
7674
1.69k
      zval *object = zend_ast_get_zval(object_ast->child[0]);
7675
1.69k
      zval *property = zend_ast_get_zval(property_ast);
7676
1.69k
      if (Z_TYPE_P(object) == IS_STRING
7677
1.68k
        && Z_TYPE_P(property) == IS_STRING
7678
1.68k
        && zend_string_equals_literal(Z_STR_P(object), "this")
7679
1.46k
        && zend_string_equals(Z_STR_P(property), context->property_name)) {
7680
657
        context->uses_property = true;
7681
        /* No need to look for references in this branch. */
7682
657
        return;
7683
657
      }
7684
1.69k
    }
7685
1.94k
  }
7686
7687
  /* Don't search across function/class boundaries. */
7688
26.6k
  if (!zend_ast_is_special(ast)) {
7689
17.3k
    zend_ast_apply(ast, zend_property_hook_find_property_usage, context);
7690
17.3k
  }
7691
26.6k
}
7692
7693
static bool zend_property_hook_uses_property(zend_string *property_name, zend_string *hook_name, zend_ast *hook_ast)
7694
5.16k
{
7695
5.16k
  if (zend_string_equals_literal_ci(hook_name, "set")
7696
1.93k
   && hook_ast->kind == ZEND_AST_PROPERTY_HOOK_SHORT_BODY) {
7697
483
    return true;
7698
483
  }
7699
7700
4.67k
  find_property_usage_context context = { property_name, false };
7701
4.67k
  zend_property_hook_find_property_usage(&hook_ast, &context);
7702
4.67k
  return context.uses_property;
7703
5.16k
}
7704
7705
static bool zend_property_is_virtual(zend_class_entry *ce, zend_string *property_name, zend_ast *hooks_ast, uint32_t flags)
7706
49.1k
{
7707
49.1k
  if (ce->ce_flags & ZEND_ACC_INTERFACE) {
7708
276
    return true;
7709
276
  }
7710
48.8k
  if (!hooks_ast) {
7711
45.0k
    return false;
7712
45.0k
  }
7713
7714
48.8k
  bool is_virtual = true;
7715
7716
3.78k
  zend_ast_list *hooks = zend_ast_get_list(hooks_ast);
7717
9.64k
  for (uint32_t i = 0; i < hooks->children; i++) {
7718
5.86k
    zend_ast_decl *hook = (zend_ast_decl *) hooks->child[i];
7719
5.86k
    zend_ast *body = hook->child[2];
7720
5.86k
    if (body && zend_property_hook_uses_property(property_name, hook->name, body)) {
7721
1.11k
      is_virtual = false;
7722
1.11k
    }
7723
5.86k
  }
7724
7725
3.78k
  return is_virtual;
7726
48.8k
}
7727
7728
static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fallback_return_type) /* {{{ */
7729
711k
{
7730
711k
  zend_ast_list *list = zend_ast_get_list(ast);
7731
711k
  uint32_t i;
7732
711k
  zend_op_array *op_array = CG(active_op_array);
7733
711k
  zend_arg_info *arg_infos;
7734
7735
711k
  if (return_type_ast || fallback_return_type) {
7736
    /* Use op_array->arg_info[-1] for return type */
7737
21.5k
    arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children + 1, 0);
7738
21.5k
    arg_infos->name = NULL;
7739
21.5k
    if (return_type_ast) {
7740
20.9k
      arg_infos->type = zend_compile_typename(return_type_ast);
7741
20.9k
      ZEND_TYPE_FULL_MASK(arg_infos->type) |= _ZEND_ARG_INFO_FLAGS(
7742
20.9k
        (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0, /* is_tentative */ 0);
7743
20.9k
    } else {
7744
621
      arg_infos->type = (zend_type) ZEND_TYPE_INIT_CODE(fallback_return_type, 0, 0);
7745
621
    }
7746
21.5k
    arg_infos++;
7747
21.5k
    op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
7748
7749
21.5k
    if (ZEND_TYPE_CONTAINS_CODE(arg_infos[-1].type, IS_VOID)
7750
4.77k
        && (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
7751
202
      zend_string *func_name = get_function_or_method_name((zend_function *) op_array);
7752
202
      zend_error(E_DEPRECATED, "%s(): Returning by reference from a void function is deprecated", ZSTR_VAL(func_name));
7753
202
      zend_string_release(func_name);
7754
202
    }
7755
689k
  } else {
7756
689k
    if (list->children == 0) {
7757
53.5k
      return;
7758
53.5k
    }
7759
636k
    arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children, 0);
7760
636k
  }
7761
7762
  /* Find last required parameter number for deprecation message. */
7763
657k
  uint32_t last_required_param = (uint32_t) -1;
7764
1.37M
  for (i = 0; i < list->children; ++i) {
7765
719k
    zend_ast *param_ast = list->child[i];
7766
719k
    zend_ast *default_ast_ptr = param_ast->child[2];
7767
719k
    bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
7768
719k
    if (!default_ast_ptr && !is_variadic) {
7769
707k
      last_required_param = i;
7770
707k
    }
7771
719k
  }
7772
7773
1.37M
  for (i = 0; i < list->children; ++i) {
7774
719k
    zend_ast *param_ast = list->child[i];
7775
719k
    zend_ast *type_ast = param_ast->child[0];
7776
719k
    zend_ast *var_ast = param_ast->child[1];
7777
719k
    zend_ast **default_ast_ptr = &param_ast->child[2];
7778
719k
    zend_ast *attributes_ast = param_ast->child[3];
7779
719k
    zend_ast *doc_comment_ast = param_ast->child[4];
7780
719k
    zend_ast *hooks_ast = param_ast->child[5];
7781
719k
    zend_string *name = zval_make_interned_string(zend_ast_get_zval(var_ast));
7782
719k
    bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
7783
719k
    bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
7784
719k
    uint32_t property_flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY | ZEND_ACC_FINAL);
7785
719k
    bool is_promoted = property_flags || hooks_ast;
7786
7787
719k
    CG(zend_lineno) = param_ast->lineno;
7788
7789
719k
    znode var_node, default_node;
7790
719k
    uint8_t opcode;
7791
719k
    zend_op *opline;
7792
719k
    zend_arg_info *arg_info;
7793
7794
719k
    if (zend_is_auto_global(name)) {
7795
2
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign auto-global variable %s",
7796
2
        ZSTR_VAL(name));
7797
2
    }
7798
7799
719k
    var_node.op_type = IS_CV;
7800
719k
    var_node.u.op.var = lookup_cv(name);
7801
7802
719k
    if (EX_VAR_TO_NUM(var_node.u.op.var) != i) {
7803
23
      zend_error_noreturn(E_COMPILE_ERROR, "Redefinition of parameter $%s",
7804
23
        ZSTR_VAL(name));
7805
719k
    } else if (zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS))) {
7806
7
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as parameter");
7807
719k
    } else if (zend_string_equals_literal(name, "http_response_header")) {
7808
97
      CG(context).has_assigned_to_http_response_header = true;
7809
97
    }
7810
7811
719k
    if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
7812
9
      zend_error_noreturn(E_COMPILE_ERROR, "Only the last parameter can be variadic");
7813
9
    }
7814
7815
719k
    if (is_variadic) {
7816
1.08k
      opcode = ZEND_RECV_VARIADIC;
7817
1.08k
      default_node.op_type = IS_UNUSED;
7818
1.08k
      op_array->fn_flags |= ZEND_ACC_VARIADIC;
7819
7820
1.08k
      if (*default_ast_ptr) {
7821
7
        zend_error_noreturn(E_COMPILE_ERROR,
7822
7
          "Variadic parameter cannot have a default value");
7823
7
      }
7824
718k
    } else if (*default_ast_ptr) {
7825
      /* we cannot substitute constants here or it will break ReflectionParameter::getDefaultValueConstantName() and ReflectionParameter::isDefaultValueConstant() */
7826
10.7k
      uint32_t cops = CG(compiler_options);
7827
10.7k
      CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION;
7828
10.7k
      opcode = ZEND_RECV_INIT;
7829
10.7k
      default_node.op_type = IS_CONST;
7830
10.7k
      zend_const_expr_to_zval(
7831
10.7k
        &default_node.u.constant, default_ast_ptr, /* allow_dynamic */ true);
7832
10.7k
      CG(compiler_options) = cops;
7833
707k
    } else {
7834
707k
      opcode = ZEND_RECV;
7835
707k
      default_node.op_type = IS_UNUSED;
7836
707k
      op_array->required_num_args = i + 1;
7837
707k
    }
7838
7839
719k
    arg_info = &arg_infos[i];
7840
719k
    arg_info->name = zend_string_copy(name);
7841
719k
    arg_info->type = (zend_type) ZEND_TYPE_INIT_NONE(0);
7842
7843
719k
    if (attributes_ast) {
7844
55.3k
      zend_compile_attributes(
7845
55.3k
        &op_array->attributes, attributes_ast, i + 1, ZEND_ATTRIBUTE_TARGET_PARAMETER,
7846
55.3k
        is_promoted ? ZEND_ATTRIBUTE_TARGET_PROPERTY : 0
7847
55.3k
      );
7848
55.3k
    }
7849
7850
719k
    bool forced_allow_nullable = false;
7851
719k
    if (type_ast) {
7852
334k
      uint32_t default_type = *default_ast_ptr ? Z_TYPE(default_node.u.constant) : IS_UNDEF;
7853
334k
      bool force_nullable = default_type == IS_NULL && !is_promoted;
7854
7855
334k
      op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
7856
334k
      arg_info->type = zend_compile_typename_ex(type_ast, force_nullable, &forced_allow_nullable);
7857
334k
      if (forced_allow_nullable) {
7858
3.95k
        zend_string *func_name = get_function_or_method_name((zend_function *) op_array);
7859
3.95k
        zend_error(E_DEPRECATED,
7860
3.95k
           "%s(): Implicitly marking parameter $%s as nullable is deprecated, the explicit nullable type "
7861
3.95k
           "must be used instead", ZSTR_VAL(func_name), ZSTR_VAL(name));
7862
3.95k
        zend_string_release(func_name);
7863
3.95k
      }
7864
7865
334k
      if (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_VOID) {
7866
7
        zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type");
7867
7
      }
7868
7869
334k
      if (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_NEVER) {
7870
7
        zend_error_noreturn(E_COMPILE_ERROR, "never cannot be used as a parameter type");
7871
7
      }
7872
7873
334k
      if (default_type != IS_UNDEF && default_type != IS_CONSTANT_AST && !force_nullable
7874
546
          && !zend_is_valid_default_value(arg_info->type, &default_node.u.constant)) {
7875
40
        zend_string *type_str = zend_type_to_string(arg_info->type);
7876
40
        zend_error_noreturn(E_COMPILE_ERROR,
7877
40
          "Cannot use %s as default value for parameter $%s of type %s",
7878
40
          zend_get_type_by_const(default_type),
7879
40
          ZSTR_VAL(name), ZSTR_VAL(type_str));
7880
40
      }
7881
334k
    }
7882
719k
    if (last_required_param != (uint32_t) -1
7883
713k
     && i < last_required_param
7884
71.5k
     && default_node.op_type == IS_CONST) {
7885
      /* Ignore parameters of the form "Type $param = null".
7886
       * This is the PHP 5 style way of writing "?Type $param", so allow it for now. */
7887
4.95k
      if (!forced_allow_nullable) {
7888
1.47k
        zend_string *func_name = get_function_or_method_name((zend_function *) op_array);
7889
1.47k
        zend_ast *required_param_ast = list->child[last_required_param];
7890
1.47k
        zend_error(E_DEPRECATED,
7891
1.47k
          "%s(): Optional parameter $%s declared before required parameter $%s "
7892
1.47k
          "is implicitly treated as a required parameter",
7893
1.47k
          ZSTR_VAL(func_name), ZSTR_VAL(name), ZSTR_VAL(zend_ast_get_str(required_param_ast->child[1])));
7894
1.47k
        zend_string_release(func_name);
7895
1.47k
      }
7896
7897
      /* Regardless of whether we issue a deprecation, convert this parameter into
7898
       * a required parameter without a default value. This ensures that it cannot be
7899
       * used as an optional parameter even with named parameters. */
7900
4.95k
      opcode = ZEND_RECV;
7901
4.95k
      default_node.op_type = IS_UNUSED;
7902
4.95k
      zval_ptr_dtor(&default_node.u.constant);
7903
4.95k
    }
7904
7905
719k
    opline = zend_emit_op(NULL, opcode, NULL, &default_node);
7906
719k
    SET_NODE(opline->result, &var_node);
7907
719k
    opline->op1.num = i + 1;
7908
7909
719k
    uint32_t arg_info_flags = _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic, /* is_tentative */ 0)
7910
719k
      | (is_promoted ? _ZEND_IS_PROMOTED_BIT : 0);
7911
719k
    ZEND_TYPE_FULL_MASK(arg_info->type) |= arg_info_flags;
7912
719k
    if (opcode == ZEND_RECV) {
7913
712k
      opline->op2.num = type_ast ?
7914
381k
        ZEND_TYPE_FULL_MASK(arg_info->type) : MAY_BE_ANY;
7915
712k
    }
7916
7917
719k
    if (is_promoted) {
7918
1.02k
      zend_op_array *op_array = CG(active_op_array);
7919
1.02k
      zend_class_entry *scope = op_array->scope;
7920
7921
1.02k
      bool is_ctor =
7922
1.02k
        scope && zend_is_constructor(op_array->function_name);
7923
1.02k
      if (!is_ctor) {
7924
50
        zend_error_noreturn(E_COMPILE_ERROR,
7925
50
          "Cannot declare promoted property outside a constructor");
7926
50
      }
7927
977
      if ((op_array->fn_flags & ZEND_ACC_ABSTRACT)
7928
970
          || (scope->ce_flags & ZEND_ACC_INTERFACE)) {
7929
7
        zend_error_noreturn(E_COMPILE_ERROR,
7930
7
          "Cannot declare promoted property in an abstract constructor");
7931
7
      }
7932
970
      if (is_variadic) {
7933
7
        zend_error_noreturn(E_COMPILE_ERROR,
7934
7
          "Cannot declare variadic promoted property");
7935
7
      }
7936
963
      if (zend_hash_exists(&scope->properties_info, name)) {
7937
7
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s",
7938
7
          ZSTR_VAL(scope->name), ZSTR_VAL(name));
7939
7
      }
7940
956
      if (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_CALLABLE) {
7941
7
        zend_string *str = zend_type_to_string(arg_info->type);
7942
7
        zend_error_noreturn(E_COMPILE_ERROR,
7943
7
          "Property %s::$%s cannot have type %s",
7944
7
          ZSTR_VAL(scope->name), ZSTR_VAL(name), ZSTR_VAL(str));
7945
7
      }
7946
7947
949
      if (!(property_flags & ZEND_ACC_READONLY) && (scope->ce_flags & ZEND_ACC_READONLY_CLASS)) {
7948
25
        property_flags |= ZEND_ACC_READONLY;
7949
25
      }
7950
7951
      /* Recompile the type, as it has different memory management requirements. */
7952
949
      zend_type type = ZEND_TYPE_INIT_NONE(0);
7953
949
      if (type_ast) {
7954
725
        type = zend_compile_typename(type_ast);
7955
725
      }
7956
7957
      /* Don't give the property an explicit default value. For typed properties this means
7958
       * uninitialized, for untyped properties it means an implicit null default value.
7959
       * Properties with hooks get an implicit default value of undefined until inheritance,
7960
       * where it is changed to null only once we know it is not virtual. If we were to set it
7961
       * here, we couldn't verify that a true virtual property must not have an explicit
7962
       * default value. */
7963
949
      zval default_value;
7964
949
      if (ZEND_TYPE_IS_SET(type) || hooks_ast) {
7965
757
        ZVAL_UNDEF(&default_value);
7966
757
      } else {
7967
192
        if (property_flags & ZEND_ACC_READONLY) {
7968
14
          zend_error_noreturn(E_COMPILE_ERROR, "Readonly property %s::$%s must have type",
7969
14
            ZSTR_VAL(scope->name), ZSTR_VAL(name));
7970
14
        }
7971
7972
178
        ZVAL_NULL(&default_value);
7973
178
      }
7974
7975
935
      zend_string *doc_comment =
7976
935
        doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL;
7977
935
      zend_property_info *prop = zend_declare_typed_property(
7978
935
        scope, name, &default_value,
7979
935
        property_flags | (zend_property_is_virtual(scope, name, hooks_ast, property_flags) ? ZEND_ACC_VIRTUAL : 0) | ZEND_ACC_PROMOTED,
7980
935
        doc_comment, type);
7981
935
      if (hooks_ast) {
7982
107
        zend_ast_list *hooks = zend_ast_get_list(hooks_ast);
7983
107
        zend_compile_property_hooks(prop, name, type_ast, hooks);
7984
107
      }
7985
935
      if (attributes_ast) {
7986
80
        zend_compile_attributes(
7987
80
          &prop->attributes, attributes_ast, 0, ZEND_ATTRIBUTE_TARGET_PROPERTY, ZEND_ATTRIBUTE_TARGET_PARAMETER);
7988
7989
80
        zend_attribute *override_attribute = zend_get_attribute_str(prop->attributes, "override", sizeof("override")-1);
7990
80
        if (override_attribute) {
7991
10
          prop->flags |= ZEND_ACC_OVERRIDE;
7992
10
        }
7993
80
      }
7994
935
    }
7995
719k
  }
7996
7997
  /* These are assigned at the end to avoid uninitialized memory in case of an error */
7998
657k
  op_array->num_args = list->children;
7999
657k
  op_array->arg_info = arg_infos;
8000
8001
  /* Don't count the variadic argument */
8002
657k
  if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
8003
1.06k
    op_array->num_args--;
8004
1.06k
  }
8005
657k
  zend_set_function_arg_flags((zend_function*)op_array);
8006
8007
1.37M
  for (i = 0; i < list->children; i++) {
8008
718k
    zend_ast *param_ast = list->child[i];
8009
718k
    zend_ast *hooks_ast = param_ast->child[5];
8010
718k
    bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
8011
718k
    uint32_t flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY);
8012
718k
    bool is_promoted = flags || hooks_ast;
8013
718k
    if (!is_promoted) {
8014
717k
      continue;
8015
717k
    }
8016
8017
904
    CG(zend_lineno) = param_ast->lineno;
8018
8019
    /* Emit $this->prop = $prop for promoted properties. */
8020
904
    zend_string *name = zend_ast_get_str(param_ast->child[1]);
8021
904
    znode name_node, value_node;
8022
904
    name_node.op_type = IS_CONST;
8023
904
    ZVAL_STR_COPY(&name_node.u.constant, name);
8024
904
    value_node.op_type = IS_CV;
8025
904
    value_node.u.op.var = lookup_cv(name);
8026
8027
904
    zend_op *opline = zend_emit_op(NULL,
8028
904
      is_ref ? ZEND_ASSIGN_OBJ_REF : ZEND_ASSIGN_OBJ, NULL, &name_node);
8029
904
    opline->extended_value = zend_alloc_cache_slots(3);
8030
904
    zend_emit_op_data(&value_node);
8031
904
  }
8032
657k
}
8033
/* }}} */
8034
8035
static void zend_compile_closure_binding(znode *closure, zend_op_array *op_array, zend_ast *uses_ast) /* {{{ */
8036
2.27k
{
8037
2.27k
  zend_ast_list *list = zend_ast_get_list(uses_ast);
8038
2.27k
  uint32_t i;
8039
8040
2.27k
  if (!list->children) {
8041
0
    return;
8042
0
  }
8043
8044
2.27k
  if (!op_array->static_variables) {
8045
2.27k
    op_array->static_variables = zend_new_array(8);
8046
2.27k
  }
8047
8048
9.03k
  for (i = 0; i < list->children; ++i) {
8049
6.78k
    zend_ast *var_name_ast = list->child[i];
8050
6.78k
    zend_string *var_name = zval_make_interned_string(zend_ast_get_zval(var_name_ast));
8051
6.78k
    uint32_t mode = var_name_ast->attr;
8052
6.78k
    zend_op *opline;
8053
6.78k
    zval *value;
8054
8055
6.78k
    if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) {
8056
7
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
8057
7
    }
8058
8059
6.77k
    if (zend_is_auto_global(var_name)) {
8060
7
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use auto-global as lexical variable");
8061
7
    }
8062
8063
6.77k
    value = zend_hash_add(op_array->static_variables, var_name, &EG(uninitialized_zval));
8064
6.77k
    if (!value) {
8065
11
      zend_error_noreturn_unchecked(E_COMPILE_ERROR,
8066
11
        "Cannot use variable $%S twice", var_name);
8067
11
    }
8068
8069
6.75k
    CG(zend_lineno) = zend_ast_get_lineno(var_name_ast);
8070
8071
6.75k
    opline = zend_emit_op(NULL, ZEND_BIND_LEXICAL, closure, NULL);
8072
6.75k
    opline->op2_type = IS_CV;
8073
6.75k
    opline->op2.var = lookup_cv(var_name);
8074
6.75k
    opline->extended_value =
8075
6.75k
      (uint32_t)((char*)value - (char*)op_array->static_variables->arData) | mode;
8076
6.75k
  }
8077
2.27k
}
8078
/* }}} */
8079
8080
typedef struct {
8081
  HashTable uses;
8082
  bool varvars_used;
8083
} closure_info;
8084
8085
1.35M
static void find_implicit_binds_recursively(closure_info *info, zend_ast *ast) {
8086
1.35M
  if (!ast) {
8087
8.10k
    return;
8088
8.10k
  }
8089
8090
1.34M
  if (ast->kind == ZEND_AST_VAR) {
8091
249k
    zend_ast *name_ast = ast->child[0];
8092
249k
    if (name_ast->kind == ZEND_AST_ZVAL && Z_TYPE_P(zend_ast_get_zval(name_ast)) == IS_STRING) {
8093
247k
      zend_string *name = zend_ast_get_str(name_ast);
8094
247k
      if (zend_is_auto_global(name)) {
8095
        /* These is no need to explicitly import auto-globals. */
8096
3.60k
        return;
8097
3.60k
      }
8098
8099
244k
      if (zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS))) {
8100
        /* $this does not need to be explicitly imported. */
8101
3.60k
        return;
8102
3.60k
      }
8103
8104
240k
      zend_hash_add_empty_element(&info->uses, name);
8105
240k
    } else {
8106
1.87k
      info->varvars_used = true;
8107
1.87k
      find_implicit_binds_recursively(info, name_ast);
8108
1.87k
    }
8109
1.09M
  } else if (zend_ast_is_list(ast)) {
8110
61.6k
    zend_ast_list *list = zend_ast_get_list(ast);
8111
61.6k
    uint32_t i;
8112
507k
    for (i = 0; i < list->children; i++) {
8113
445k
      find_implicit_binds_recursively(info, list->child[i]);
8114
445k
    }
8115
1.03M
  } else if (ast->kind == ZEND_AST_CLOSURE) {
8116
    /* For normal closures add the use() list. */
8117
851
    zend_ast_decl *closure_ast = (zend_ast_decl *) ast;
8118
851
    zend_ast *uses_ast = closure_ast->child[1];
8119
851
    if (uses_ast) {
8120
531
      zend_ast_list *uses_list = zend_ast_get_list(uses_ast);
8121
531
      uint32_t i;
8122
3.82k
      for (i = 0; i < uses_list->children; i++) {
8123
3.29k
        zend_hash_add_empty_element(&info->uses, zend_ast_get_str(uses_list->child[i]));
8124
3.29k
      }
8125
531
    }
8126
1.03M
  } else if (ast->kind == ZEND_AST_ARROW_FUNC) {
8127
    /* For arrow functions recursively check the expression. */
8128
315k
    zend_ast_decl *closure_ast = (zend_ast_decl *) ast;
8129
315k
    find_implicit_binds_recursively(info, closure_ast->child[2]);
8130
719k
  } else if (!zend_ast_is_special(ast)) {
8131
444k
    uint32_t i, children = zend_ast_get_num_children(ast);
8132
1.01M
    for (i = 0; i < children; i++) {
8133
571k
      find_implicit_binds_recursively(info, ast->child[i]);
8134
571k
    }
8135
444k
  }
8136
1.34M
}
8137
8138
static void find_implicit_binds(closure_info *info, zend_ast *params_ast, zend_ast *stmt_ast)
8139
21.0k
{
8140
21.0k
  zend_ast_list *param_list = zend_ast_get_list(params_ast);
8141
21.0k
  uint32_t i;
8142
8143
21.0k
  zend_hash_init(&info->uses, param_list->children, NULL, NULL, 0);
8144
8145
21.0k
  find_implicit_binds_recursively(info, stmt_ast);
8146
8147
  /* Remove variables that are parameters */
8148
31.7k
  for (i = 0; i < param_list->children; i++) {
8149
10.7k
    zend_ast *param_ast = param_list->child[i];
8150
10.7k
    zend_hash_del(&info->uses, zend_ast_get_str(param_ast->child[1]));
8151
10.7k
  }
8152
21.0k
}
8153
8154
static void compile_implicit_lexical_binds(
8155
    closure_info *info, znode *closure, zend_op_array *op_array)
8156
21.0k
{
8157
21.0k
  zend_string *var_name;
8158
21.0k
  zend_op *opline;
8159
8160
  /* TODO We might want to use a special binding mode if varvars_used is set. */
8161
21.0k
  if (zend_hash_num_elements(&info->uses) == 0) {
8162
11.8k
    return;
8163
11.8k
  }
8164
8165
9.16k
  if (!op_array->static_variables) {
8166
9.16k
    op_array->static_variables = zend_new_array(8);
8167
9.16k
  }
8168
8169
226k
  ZEND_HASH_MAP_FOREACH_STR_KEY(&info->uses, var_name)
8170
226k
    zval *value = zend_hash_add(
8171
226k
      op_array->static_variables, var_name, &EG(uninitialized_zval));
8172
226k
    uint32_t offset = (uint32_t)((char*)value - (char*)op_array->static_variables->arData);
8173
8174
226k
    opline = zend_emit_op(NULL, ZEND_BIND_LEXICAL, closure, NULL);
8175
226k
    opline->op2_type = IS_CV;
8176
226k
    opline->op2.var = lookup_cv(var_name);
8177
226k
    opline->extended_value = offset | ZEND_BIND_IMPLICIT;
8178
226k
  ZEND_HASH_FOREACH_END();
8179
9.16k
}
8180
8181
static void zend_compile_closure_uses(zend_ast *ast) /* {{{ */
8182
2.25k
{
8183
2.25k
  zend_op_array *op_array = CG(active_op_array);
8184
2.25k
  zend_ast_list *list = zend_ast_get_list(ast);
8185
2.25k
  uint32_t i;
8186
8187
8.97k
  for (i = 0; i < list->children; ++i) {
8188
6.72k
    uint32_t mode = ZEND_BIND_EXPLICIT;
8189
6.72k
    zend_ast *var_ast = list->child[i];
8190
6.72k
    zend_string *var_name = zend_ast_get_str(var_ast);
8191
6.72k
    zval zv;
8192
6.72k
    ZVAL_NULL(&zv);
8193
8194
6.72k
    {
8195
6.72k
      int i;
8196
21.7k
      for (i = 0; i < op_array->last_var; i++) {
8197
15.0k
        if (zend_string_equals(op_array->vars[i], var_name)) {
8198
7
          zend_error_noreturn_unchecked(E_COMPILE_ERROR,
8199
7
            "Cannot use lexical variable $%S as a parameter name", var_name);
8200
7
        }
8201
15.0k
      }
8202
6.72k
    }
8203
8204
6.72k
    CG(zend_lineno) = zend_ast_get_lineno(var_ast);
8205
8206
6.72k
    if (var_ast->attr) {
8207
2.07k
      mode |= ZEND_BIND_REF;
8208
2.07k
    }
8209
8210
6.72k
    zend_compile_static_var_common(var_name, &zv, mode);
8211
6.72k
  }
8212
2.25k
}
8213
/* }}} */
8214
8215
static void zend_compile_implicit_closure_uses(closure_info *info)
8216
20.9k
{
8217
20.9k
  zend_string *var_name;
8218
249k
  ZEND_HASH_MAP_FOREACH_STR_KEY(&info->uses, var_name)
8219
249k
    zval zv;
8220
249k
    ZVAL_NULL(&zv);
8221
249k
    zend_compile_static_var_common(var_name, &zv, ZEND_BIND_IMPLICIT);
8222
249k
  ZEND_HASH_FOREACH_END();
8223
20.9k
}
8224
8225
738
static void add_stringable_interface(zend_class_entry *ce) {
8226
1.18k
  for (uint32_t i = 0; i < ce->num_interfaces; i++) {
8227
471
    if (zend_string_equals_literal(ce->interface_names[i].lc_name, "stringable")) {
8228
      /* Interface already explicitly implemented */
8229
24
      return;
8230
24
    }
8231
471
  }
8232
8233
714
  ce->num_interfaces++;
8234
714
  ce->interface_names =
8235
714
    erealloc(ce->interface_names, sizeof(zend_class_name) * ce->num_interfaces);
8236
  // TODO: Add known interned strings instead?
8237
714
  ce->interface_names[ce->num_interfaces - 1].name =
8238
714
    ZSTR_INIT_LITERAL("Stringable", 0);
8239
714
  ce->interface_names[ce->num_interfaces - 1].lc_name =
8240
714
    ZSTR_INIT_LITERAL("stringable", 0);
8241
714
}
8242
8243
static zend_string *zend_begin_method_decl(zend_op_array *op_array, zend_string *name, bool has_body) /* {{{ */
8244
41.9k
{
8245
41.9k
  zend_class_entry *ce = CG(active_class_entry);
8246
41.9k
  bool in_interface = (ce->ce_flags & ZEND_ACC_INTERFACE) != 0;
8247
41.9k
  uint32_t fn_flags = op_array->fn_flags;
8248
8249
41.9k
  zend_string *lcname;
8250
8251
41.9k
  if (fn_flags & ZEND_ACC_READONLY) {
8252
0
    zend_error(E_COMPILE_ERROR, "Cannot use 'readonly' as method modifier");
8253
0
  }
8254
8255
41.9k
  if ((fn_flags & ZEND_ACC_PRIVATE) && (fn_flags & ZEND_ACC_FINAL) && !zend_is_constructor(name)) {
8256
121
    zend_error(E_COMPILE_WARNING, "Private methods cannot be final as they are never overridden by other classes");
8257
121
  }
8258
8259
41.9k
  if ((fn_flags & ZEND_ACC_ABSTRACT)
8260
531
   && !(ce->ce_flags & (ZEND_ACC_EXPLICIT_ABSTRACT_CLASS|ZEND_ACC_TRAIT))) {
8261
    // Don't say that the class should be declared abstract if it is
8262
    // anonymous or an enum and can't be abstract
8263
37
    if (ce->ce_flags & ZEND_ACC_ANON_CLASS) {
8264
7
      zend_error_noreturn(E_COMPILE_ERROR, "Anonymous class method %s() must not be abstract",
8265
7
        ZSTR_VAL(name));
8266
30
    } else if (ce->ce_flags & (ZEND_ACC_ENUM|ZEND_ACC_INTERFACE)) {
8267
18
      zend_error_noreturn(E_COMPILE_ERROR, "%s method %s::%s() must not be abstract",
8268
18
        zend_get_object_type_case(ce, true), ZSTR_VAL(ce->name), ZSTR_VAL(name));
8269
18
    } else {
8270
12
      zend_error_noreturn(E_COMPILE_ERROR, "Class %s declares abstract method %s() and must therefore be declared abstract",
8271
12
        ZSTR_VAL(ce->name), ZSTR_VAL(name));
8272
12
    }
8273
37
  }
8274
8275
41.9k
  if (in_interface) {
8276
991
    if (!(fn_flags & ZEND_ACC_PUBLIC)) {
8277
0
      zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method "
8278
0
        "%s::%s() must be public", ZSTR_VAL(ce->name), ZSTR_VAL(name));
8279
0
    }
8280
991
    if (fn_flags & ZEND_ACC_FINAL) {
8281
9
      zend_error_noreturn(E_COMPILE_ERROR, "Interface method "
8282
9
        "%s::%s() must not be final", ZSTR_VAL(ce->name), ZSTR_VAL(name));
8283
9
    }
8284
982
    op_array->fn_flags |= ZEND_ACC_ABSTRACT;
8285
982
  }
8286
8287
41.9k
  if (op_array->fn_flags & ZEND_ACC_ABSTRACT) {
8288
1.47k
    if ((op_array->fn_flags & ZEND_ACC_PRIVATE) && !(ce->ce_flags & ZEND_ACC_TRAIT)) {
8289
7
      zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private",
8290
7
        in_interface ? "Interface" : "Abstract", ZSTR_VAL(ce->name), ZSTR_VAL(name));
8291
7
    }
8292
8293
1.46k
    if (has_body) {
8294
12
      zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body",
8295
12
        in_interface ? "Interface" : "Abstract", ZSTR_VAL(ce->name), ZSTR_VAL(name));
8296
12
    }
8297
8298
1.45k
    ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
8299
40.4k
  } else if (!has_body) {
8300
7
    zend_error_noreturn(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body",
8301
7
      ZSTR_VAL(ce->name), ZSTR_VAL(name));
8302
7
  }
8303
8304
41.8k
  op_array->scope = ce;
8305
41.8k
  op_array->function_name = zend_string_copy(name);
8306
8307
41.8k
  lcname = zend_string_tolower(name);
8308
41.8k
  lcname = zend_new_interned_string(lcname);
8309
8310
41.8k
  if (zend_hash_add_ptr(&ce->function_table, lcname, op_array) == NULL) {
8311
32
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()",
8312
32
      ZSTR_VAL(ce->name), ZSTR_VAL(name));
8313
32
  }
8314
8315
41.8k
  zend_add_magic_method(ce, (zend_function *) op_array, lcname);
8316
41.8k
  if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)
8317
759
      && !(ce->ce_flags & ZEND_ACC_TRAIT)) {
8318
738
    add_stringable_interface(ce);
8319
738
  }
8320
8321
41.8k
  return lcname;
8322
41.8k
}
8323
/* }}} */
8324
8325
649k
static uint32_t zend_add_dynamic_func_def(zend_op_array *def) {
8326
649k
  zend_op_array *op_array = CG(active_op_array);
8327
649k
  uint32_t def_offset = op_array->num_dynamic_func_defs++;
8328
649k
  op_array->dynamic_func_defs = erealloc(
8329
649k
    op_array->dynamic_func_defs, op_array->num_dynamic_func_defs * sizeof(zend_op_array *));
8330
649k
  op_array->dynamic_func_defs[def_offset] = def;
8331
649k
  return def_offset;
8332
649k
}
8333
8334
enum func_decl_level {
8335
  FUNC_DECL_LEVEL_TOPLEVEL,
8336
  FUNC_DECL_LEVEL_NESTED,
8337
  FUNC_DECL_LEVEL_CONSTEXPR,
8338
};
8339
8340
static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl, enum func_decl_level level) /* {{{ */
8341
665k
{
8342
665k
  zend_string *unqualified_name, *name, *lcname;
8343
665k
  zend_op *opline;
8344
8345
665k
  if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
8346
643k
    zend_string *filename = op_array->filename;
8347
643k
    uint32_t start_lineno = decl->start_lineno;
8348
8349
643k
    zend_string *class = zend_empty_string;
8350
643k
    zend_string *separator = zend_empty_string;
8351
643k
    zend_string *function = filename;
8352
643k
    char *parens = "";
8353
8354
643k
    if (CG(active_op_array) && CG(active_op_array)->function_name) {
8355
629k
      if (CG(active_op_array)->fn_flags & ZEND_ACC_CLOSURE) {
8356
        /* If the parent function is a closure, don't redundantly
8357
         * add the classname and parentheses.
8358
         */
8359
627k
        function = CG(active_op_array)->function_name;
8360
627k
      } else {
8361
1.87k
        function = CG(active_op_array)->function_name;
8362
1.87k
        parens = "()";
8363
8364
1.87k
        if (CG(active_class_entry) && CG(active_class_entry)->name) {
8365
1.31k
          class = CG(active_class_entry)->name;
8366
1.31k
          separator = ZSTR_KNOWN(ZEND_STR_PAAMAYIM_NEKUDOTAYIM);
8367
1.31k
        }
8368
1.87k
      }
8369
629k
    }
8370
8371
643k
    unqualified_name = zend_strpprintf_unchecked(
8372
643k
      0,
8373
643k
      "{closure:%S%S%S%s:%" PRIu32 "}",
8374
643k
      class,
8375
643k
      separator,
8376
643k
      function,
8377
643k
      parens,
8378
643k
      start_lineno
8379
643k
    );
8380
8381
643k
    op_array->function_name = name = unqualified_name;
8382
643k
  } else {
8383
21.3k
    unqualified_name = decl->name;
8384
21.3k
    op_array->function_name = name = zend_prefix_with_ns(unqualified_name);
8385
21.3k
  }
8386
8387
665k
  lcname = zend_string_tolower(name);
8388
8389
665k
  if (FC(imports_function)) {
8390
100
    zend_string *import_name =
8391
100
      zend_hash_find_ptr_lc(FC(imports_function), unqualified_name);
8392
100
    if (import_name && !zend_string_equals_ci(lcname, import_name)) {
8393
15
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare function %s() (previously declared as local import)",
8394
15
        ZSTR_VAL(name));
8395
15
    }
8396
100
  }
8397
8398
665k
  if (zend_string_equals_literal(lcname, "__autoload")) {
8399
1
    zend_error_noreturn(E_COMPILE_ERROR,
8400
1
      "__autoload() is no longer supported, use spl_autoload_register() instead");
8401
1
  }
8402
8403
665k
  if (zend_string_equals_literal_ci(unqualified_name, "assert")) {
8404
7
    zend_error(E_COMPILE_ERROR,
8405
7
      "Defining a custom assert() function is not allowed, "
8406
7
      "as the function has special semantics");
8407
7
  }
8408
8409
665k
  zend_register_seen_symbol(lcname, ZEND_SYMBOL_FUNCTION);
8410
665k
  switch (level) {
8411
649k
    case FUNC_DECL_LEVEL_NESTED: {
8412
649k
      uint32_t func_ref = zend_add_dynamic_func_def(op_array);
8413
649k
      if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
8414
643k
        opline = zend_emit_op_tmp(result, ZEND_DECLARE_LAMBDA_FUNCTION, NULL, NULL);
8415
643k
        opline->op2.num = func_ref;
8416
643k
      } else {
8417
5.96k
        opline = get_next_op();
8418
5.96k
        opline->opcode = ZEND_DECLARE_FUNCTION;
8419
5.96k
        opline->op1_type = IS_CONST;
8420
5.96k
        LITERAL_STR(opline->op1, zend_string_copy(lcname));
8421
5.96k
        opline->op2.num = func_ref;
8422
5.96k
      }
8423
649k
      break;
8424
0
    }
8425
246
    case FUNC_DECL_LEVEL_CONSTEXPR:
8426
15.6k
    case FUNC_DECL_LEVEL_TOPLEVEL:
8427
      /* Nothing to do. */
8428
15.6k
      break;
8429
665k
  }
8430
664k
  return lcname;
8431
665k
}
8432
/* }}} */
8433
8434
static zend_op_array *zend_compile_func_decl_ex(
8435
  znode *result, zend_ast *ast, enum func_decl_level level,
8436
  zend_string *property_info_name,
8437
  zend_property_hook_kind hook_kind
8438
711k
) {
8439
711k
  zend_ast_decl *decl = (zend_ast_decl *) ast;
8440
711k
  zend_ast *params_ast = decl->child[0];
8441
711k
  zend_ast *uses_ast = decl->child[1];
8442
711k
  zend_ast *stmt_ast = decl->child[2];
8443
711k
  zend_ast *return_type_ast = decl->child[3];
8444
711k
  bool is_method = decl->kind == ZEND_AST_METHOD;
8445
711k
  zend_string *lcname = NULL;
8446
711k
  bool is_hook = decl->kind == ZEND_AST_PROPERTY_HOOK;
8447
8448
711k
  zend_class_entry *orig_class_entry = CG(active_class_entry);
8449
711k
  zend_op_array *orig_op_array = CG(active_op_array);
8450
711k
  zend_op_array *op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
8451
711k
  zend_oparray_context orig_oparray_context;
8452
711k
  closure_info info;
8453
711k
  memset(&info, 0, sizeof(closure_info));
8454
8455
711k
  init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE);
8456
8457
711k
  if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
8458
0
    op_array->fn_flags |= ZEND_ACC_PRELOADED;
8459
0
  }
8460
8461
711k
  op_array->fn_flags |= (orig_op_array->fn_flags & ZEND_ACC_STRICT_TYPES);
8462
711k
  op_array->fn_flags |= decl->flags;
8463
711k
  op_array->line_start = decl->start_lineno;
8464
711k
  op_array->line_end = decl->end_lineno;
8465
711k
  if (decl->doc_comment) {
8466
1.67k
    op_array->doc_comment = zend_string_copy(decl->doc_comment);
8467
1.67k
  }
8468
8469
711k
  if (decl->kind == ZEND_AST_CLOSURE || decl->kind == ZEND_AST_ARROW_FUNC) {
8470
643k
    op_array->fn_flags |= ZEND_ACC_CLOSURE;
8471
643k
  }
8472
8473
711k
  if (is_hook) {
8474
4.71k
    zend_class_entry *ce = CG(active_class_entry);
8475
4.71k
    op_array->scope = ce;
8476
4.71k
    op_array->function_name = zend_string_copy(decl->name);
8477
706k
  } else if (is_method) {
8478
41.9k
    bool has_body = stmt_ast != NULL;
8479
41.9k
    lcname = zend_begin_method_decl(op_array, decl->name, has_body);
8480
665k
  } else {
8481
665k
    lcname = zend_begin_func_decl(result, op_array, decl, level);
8482
665k
    if (decl->kind == ZEND_AST_ARROW_FUNC) {
8483
21.0k
      find_implicit_binds(&info, params_ast, stmt_ast);
8484
21.0k
      compile_implicit_lexical_binds(&info, result, op_array);
8485
644k
    } else if (uses_ast) {
8486
2.27k
      zend_compile_closure_binding(result, op_array, uses_ast);
8487
2.27k
    }
8488
665k
  }
8489
8490
711k
  CG(active_op_array) = op_array;
8491
8492
711k
  zend_oparray_context_begin(&orig_oparray_context, op_array);
8493
711k
  CG(context).active_property_info_name = property_info_name;
8494
711k
  CG(context).active_property_hook_kind = hook_kind;
8495
8496
711k
  if (decl->child[4]) {
8497
605k
    int target = ZEND_ATTRIBUTE_TARGET_FUNCTION;
8498
8499
605k
    if (is_method || is_hook) {
8500
1.51k
      target = ZEND_ATTRIBUTE_TARGET_METHOD;
8501
1.51k
    }
8502
8503
605k
    zend_compile_attributes(&op_array->attributes, decl->child[4], 0, target, 0);
8504
8505
605k
    zend_attribute *override_attribute = zend_get_attribute_str(
8506
605k
      op_array->attributes,
8507
605k
      "override",
8508
605k
      sizeof("override")-1
8509
605k
    );
8510
8511
605k
    if (override_attribute) {
8512
919
      op_array->fn_flags |= ZEND_ACC_OVERRIDE;
8513
919
    }
8514
8515
605k
    zend_attribute *deprecated_attribute = zend_get_attribute_str(
8516
605k
      op_array->attributes,
8517
605k
      "deprecated",
8518
605k
      sizeof("deprecated")-1
8519
605k
    );
8520
8521
605k
    if (deprecated_attribute) {
8522
262
      op_array->fn_flags |= ZEND_ACC_DEPRECATED;
8523
262
    }
8524
8525
    // ZEND_ACC_NODISCARD is added via an attribute validator
8526
605k
  }
8527
8528
  /* Do not leak the class scope into free standing functions, even if they are dynamically
8529
   * defined inside a class method. This is necessary for correct handling of magic constants.
8530
   * For example __CLASS__ should always be "" inside a free standing function. */
8531
711k
  if (decl->kind == ZEND_AST_FUNC_DECL) {
8532
21.3k
    CG(active_class_entry) = NULL;
8533
21.3k
  }
8534
8535
711k
  if (level == FUNC_DECL_LEVEL_TOPLEVEL) {
8536
15.3k
    op_array->fn_flags |= ZEND_ACC_TOP_LEVEL;
8537
15.3k
  }
8538
8539
711k
  {
8540
    /* Push a separator to the loop variable stack */
8541
711k
    zend_loop_var dummy_var;
8542
711k
    dummy_var.opcode = ZEND_RETURN;
8543
8544
711k
    zend_stack_push(&CG(loop_var_stack), (void *) &dummy_var);
8545
711k
  }
8546
8547
711k
  zend_compile_params(params_ast, return_type_ast,
8548
711k
    is_method && zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME) ? IS_STRING : 0);
8549
711k
  if (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) {
8550
9.72k
    zend_mark_function_as_generator();
8551
9.72k
    zend_emit_op(NULL, ZEND_GENERATOR_CREATE, NULL, NULL);
8552
9.72k
  }
8553
711k
  if (decl->kind == ZEND_AST_ARROW_FUNC) {
8554
20.9k
    zend_compile_implicit_closure_uses(&info);
8555
20.9k
    zend_hash_destroy(&info.uses);
8556
690k
  } else if (uses_ast) {
8557
2.25k
    zend_compile_closure_uses(uses_ast);
8558
2.25k
  }
8559
8560
711k
  if (ast->kind == ZEND_AST_ARROW_FUNC && decl->child[2]->kind != ZEND_AST_RETURN) {
8561
11.6k
    bool needs_return = true;
8562
11.6k
    if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
8563
1.22k
      zend_arg_info *return_info = CG(active_op_array)->arg_info - 1;
8564
1.22k
      needs_return = !ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_NEVER);
8565
1.22k
    }
8566
11.6k
    if (needs_return) {
8567
11.4k
      stmt_ast = zend_ast_create(ZEND_AST_RETURN, stmt_ast);
8568
11.4k
      decl->child[2] = stmt_ast;
8569
11.4k
    }
8570
11.6k
  }
8571
8572
711k
  if (op_array->fn_flags & ZEND_ACC_NODISCARD) {
8573
    /* ZEND_ACC_NODISCARD gets added by the attribute validator, but only
8574
     * if the method is not a hook; if it is a hook, then the validator
8575
     * will have returned an error message, even if the error message was
8576
     * delayed with #[\DelayedTargetValidation] that ZEND_ACC_NODISCARD
8577
     * flag should not have been added. */
8578
269
    ZEND_ASSERT(!is_hook);
8579
8580
269
    if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
8581
224
      zend_arg_info *return_info = CG(active_op_array)->arg_info - 1;
8582
224
      if (ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_VOID)) {
8583
7
        zend_error_noreturn(E_COMPILE_ERROR,
8584
7
          "A void %s does not return a value, but #[\\NoDiscard] requires a return value",
8585
7
          CG(active_class_entry) != NULL ? "method" : "function");
8586
7
      }
8587
8588
217
      if (ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_NEVER)) {
8589
7
        zend_error_noreturn(E_COMPILE_ERROR,
8590
7
          "A never returning %s does not return a value, but #[\\NoDiscard] requires a return value",
8591
7
          CG(active_class_entry) != NULL ? "method" : "function");
8592
7
      }
8593
217
    }
8594
269
  }
8595
8596
711k
  zend_compile_stmt(stmt_ast);
8597
8598
711k
  if (is_method) {
8599
41.5k
    CG(zend_lineno) = decl->start_lineno;
8600
41.5k
    zend_check_magic_method_implementation(
8601
41.5k
      CG(active_class_entry), (zend_function *) op_array, lcname, E_COMPILE_ERROR);
8602
670k
  } else if (level == FUNC_DECL_LEVEL_TOPLEVEL) {
8603
    /* Only register the function after a successful compile */
8604
14.7k
    if (UNEXPECTED(zend_hash_add_ptr(CG(function_table), lcname, op_array) == NULL)) {
8605
103
      CG(zend_lineno) = decl->start_lineno;
8606
103
      do_bind_function_error(lcname, op_array, true);
8607
103
    }
8608
14.7k
  }
8609
8610
  /* put the implicit return on the really last line */
8611
711k
  CG(zend_lineno) = decl->end_lineno;
8612
8613
711k
  zend_do_extended_stmt(NULL);
8614
711k
  zend_emit_final_return(false);
8615
8616
711k
  pass_two(CG(active_op_array));
8617
711k
  zend_oparray_context_end(&orig_oparray_context);
8618
8619
  /* Pop the loop variable stack separator */
8620
711k
  zend_stack_del_top(&CG(loop_var_stack));
8621
8622
711k
  if (level == FUNC_DECL_LEVEL_TOPLEVEL) {
8623
14.6k
    zend_observer_function_declared_notify(op_array, lcname);
8624
14.6k
  }
8625
8626
711k
  if (lcname != NULL) {
8627
704k
    zend_string_release_ex(lcname, 0);
8628
704k
  }
8629
8630
711k
  CG(active_op_array) = orig_op_array;
8631
711k
  CG(active_class_entry) = orig_class_entry;
8632
8633
711k
  return op_array;
8634
711k
}
8635
8636
static zend_op_array *zend_compile_func_decl(znode *result, zend_ast *ast, enum func_decl_level level)
8637
706k
{
8638
706k
  return zend_compile_func_decl_ex(result, ast, level, /* property_info */ NULL, (zend_property_hook_kind)-1);
8639
706k
}
8640
8641
5.56k
zend_property_hook_kind zend_get_property_hook_kind_from_name(zend_string *name) {
8642
5.56k
  if (zend_string_equals_literal_ci(name, "get")) {
8643
3.62k
    return ZEND_PROPERTY_HOOK_GET;
8644
3.62k
  } else if (zend_string_equals_literal_ci(name, "set")) {
8645
1.80k
    return ZEND_PROPERTY_HOOK_SET;
8646
1.80k
  } else {
8647
143
    return (zend_property_hook_kind)-1;
8648
143
  }
8649
5.56k
}
8650
8651
static void zend_compile_property_hooks(
8652
    zend_property_info *prop_info, zend_string *prop_name,
8653
    zend_ast *prop_type_ast, zend_ast_list *hooks)
8654
4.04k
{
8655
4.04k
  zend_class_entry *ce = CG(active_class_entry);
8656
8657
4.04k
  if (prop_info->flags & ZEND_ACC_READONLY) {
8658
19
    zend_error_noreturn(E_COMPILE_ERROR, "Hooked properties cannot be readonly");
8659
19
  }
8660
8661
4.03k
  if (hooks->children == 0) {
8662
15
    zend_error_noreturn(E_COMPILE_ERROR, "Property hook list must not be empty");
8663
15
  }
8664
8665
8.68k
  for (uint32_t i = 0; i < hooks->children; i++) {
8666
4.97k
    zend_ast_decl *hook = (zend_ast_decl *) hooks->child[i];
8667
4.97k
    zend_string *name = hook->name;
8668
4.97k
    zend_ast *stmt_ast = hook->child[2];
8669
4.97k
    zend_ast **return_type_ast_ptr = NULL;
8670
4.97k
    zend_ast **value_type_ast_ptr = NULL;
8671
4.97k
    CG(zend_lineno) = hook->start_lineno;
8672
8673
    /* Non-private hooks are always public. This avoids having to copy the hook when inheriting
8674
     * hooks from protected properties to public ones. */
8675
4.97k
    uint32_t hook_visibility = (prop_info->flags & ZEND_ACC_PPP_MASK) != ZEND_ACC_PRIVATE ? ZEND_ACC_PUBLIC : ZEND_ACC_PRIVATE;
8676
4.97k
    hook->flags |= hook_visibility;
8677
8678
4.97k
    if (prop_info->flags & ZEND_ACC_STATIC) {
8679
33
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare hooks for static property");
8680
33
    }
8681
4.93k
    if ((hook->flags & ZEND_ACC_FINAL) && (hook->flags & ZEND_ACC_PRIVATE)) {
8682
7
      zend_error_noreturn(E_COMPILE_ERROR, "Property hook cannot be both final and private");
8683
7
    }
8684
4.93k
    if ((ce->ce_flags & ZEND_ACC_INTERFACE)
8685
4.66k
     || ((prop_info->flags & ZEND_ACC_ABSTRACT) && !stmt_ast)) {
8686
836
      hook->flags |= ZEND_ACC_ABSTRACT;
8687
8688
836
      if (stmt_ast) {
8689
9
        zend_error_noreturn(E_COMPILE_ERROR, "Abstract property hook cannot have body");
8690
9
      }
8691
827
      if (hook->flags & ZEND_ACC_PRIVATE) {
8692
7
        zend_error_noreturn(E_COMPILE_ERROR,
8693
7
          "Property hook cannot be both abstract and private");
8694
7
      }
8695
820
      if (hook->flags & ZEND_ACC_FINAL) {
8696
8
        zend_error_noreturn(E_COMPILE_ERROR, "Property hook cannot be both abstract and final");
8697
8
      }
8698
4.09k
    } else if (!stmt_ast) {
8699
14
      zend_error_noreturn(E_COMPILE_ERROR, "Non-abstract property hook must have a body");
8700
14
    }
8701
8702
4.89k
    zend_property_hook_kind hook_kind = zend_get_property_hook_kind_from_name(name);
8703
4.89k
    if (hook_kind == (zend_property_hook_kind)-1) {
8704
143
      zend_error_noreturn(E_COMPILE_ERROR,
8705
143
        "Unknown hook \"%s\" for property %s::$%s, expected \"get\" or \"set\"",
8706
143
        ZSTR_VAL(name), ZSTR_VAL(ce->name), ZSTR_VAL(prop_name));
8707
143
    }
8708
8709
4.75k
    if (stmt_ast && stmt_ast->kind == ZEND_AST_PROPERTY_HOOK_SHORT_BODY) {
8710
1.62k
      stmt_ast = stmt_ast->child[0];
8711
1.62k
      if (hook_kind == ZEND_PROPERTY_HOOK_GET) {
8712
1.33k
        stmt_ast = zend_ast_create(ZEND_AST_RETURN, stmt_ast);
8713
1.33k
      } else {
8714
292
        ZEND_ASSERT(hook_kind == ZEND_PROPERTY_HOOK_SET);
8715
292
        stmt_ast = zend_ast_create(ZEND_AST_ASSIGN,
8716
292
          zend_ast_create(ZEND_AST_PROP,
8717
292
            zend_ast_create(ZEND_AST_VAR, zend_ast_create_zval_from_str(ZSTR_KNOWN(ZEND_STR_THIS))),
8718
292
            zend_ast_create_zval_from_str(zend_copy_unmangled_prop_name(prop_info->name))),
8719
292
          stmt_ast);
8720
292
      }
8721
1.62k
      stmt_ast = zend_ast_create_list(1, ZEND_AST_STMT_LIST, stmt_ast);
8722
1.62k
      hook->child[2] = stmt_ast;
8723
1.62k
    }
8724
8725
4.75k
    if (hook_kind == ZEND_PROPERTY_HOOK_GET) {
8726
3.00k
      if (hook->child[0]) {
8727
7
        zend_error_noreturn(E_COMPILE_ERROR, "get hook of property %s::$%s must not have a parameter list",
8728
7
          ZSTR_VAL(ce->name), ZSTR_VAL(prop_name));
8729
7
      }
8730
8731
2.99k
      hook->child[0] = zend_ast_create_list(0, ZEND_AST_PARAM_LIST);
8732
8733
2.99k
      return_type_ast_ptr = &hook->child[3];
8734
2.99k
      *return_type_ast_ptr = prop_type_ast;
8735
2.99k
    } else if (hook_kind == ZEND_PROPERTY_HOOK_SET) {
8736
1.74k
      if (hook->child[0]) {
8737
155
        zend_ast_list *param_list = zend_ast_get_list(hook->child[0]);
8738
155
        if (param_list->children != 1) {
8739
1
          zend_error_noreturn(E_COMPILE_ERROR, "%s hook of property %s::$%s must accept exactly one parameters",
8740
1
            ZSTR_VAL(name), ZSTR_VAL(ce->name), ZSTR_VAL(prop_name));
8741
1
        }
8742
154
        zend_ast *value_param_ast = param_list->child[0];
8743
154
        if (value_param_ast->attr & ZEND_PARAM_REF) {
8744
7
          zend_error_noreturn(E_COMPILE_ERROR, "Parameter $%s of %s hook %s::$%s must not be pass-by-reference",
8745
7
            ZSTR_VAL(zend_ast_get_str(value_param_ast->child[1])), ZSTR_VAL(name), ZSTR_VAL(ce->name), ZSTR_VAL(prop_name));
8746
7
        }
8747
147
        if (value_param_ast->attr & ZEND_PARAM_VARIADIC) {
8748
7
          zend_error_noreturn(E_COMPILE_ERROR, "Parameter $%s of %s hook %s::$%s must not be variadic",
8749
7
            ZSTR_VAL(zend_ast_get_str(value_param_ast->child[1])), ZSTR_VAL(name), ZSTR_VAL(ce->name), ZSTR_VAL(prop_name));
8750
7
        }
8751
140
        if (value_param_ast->child[2]) {
8752
7
          zend_error_noreturn(E_COMPILE_ERROR, "Parameter $%s of %s hook %s::$%s must not have a default value",
8753
7
            ZSTR_VAL(zend_ast_get_str(value_param_ast->child[1])), ZSTR_VAL(name), ZSTR_VAL(ce->name), ZSTR_VAL(prop_name));
8754
7
        }
8755
133
        if ((prop_type_ast != NULL) != (value_param_ast->child[0] != NULL)) {
8756
7
          zend_hooked_property_variance_error_ex(zend_ast_get_str(value_param_ast->child[1]), ce->name, prop_info->name);
8757
7
        }
8758
1.59k
      } else {
8759
1.59k
        zend_ast *param_name_ast = zend_ast_create_zval_from_str(ZSTR_KNOWN(ZEND_STR_VALUE));
8760
1.59k
        zend_ast *param = zend_ast_create(
8761
1.59k
          ZEND_AST_PARAM, prop_type_ast, param_name_ast,
8762
1.59k
          /* expr */ NULL, /* doc_comment */ NULL, /* attributes */ NULL,
8763
1.59k
          /* hooks */ NULL);
8764
1.59k
        value_type_ast_ptr = &param->child[0];
8765
1.59k
        hook->child[0] = zend_ast_create_list(1, ZEND_AST_PARAM_LIST, param);
8766
1.59k
      }
8767
1.71k
      zend_ast *return_type = zend_ast_create_zval_from_str(ZSTR_KNOWN(ZEND_STR_VOID));
8768
1.71k
      return_type->attr = ZEND_NAME_NOT_FQ;
8769
1.71k
      hook->child[3] = return_type;
8770
1.71k
    } else {
8771
0
      ZEND_UNREACHABLE();
8772
0
    }
8773
8774
4.71k
    hook->name = zend_strpprintf(0, "$%s::%s", ZSTR_VAL(prop_name), ZSTR_VAL(name));
8775
8776
4.71k
    zend_function *func = (zend_function *) zend_compile_func_decl_ex(
8777
4.71k
      NULL, (zend_ast *) hook, FUNC_DECL_LEVEL_NESTED, prop_info->name, hook_kind);
8778
8779
4.71k
    func->common.prop_info = prop_info;
8780
8781
4.71k
    if (!prop_info->hooks) {
8782
3.72k
      prop_info->hooks = zend_arena_alloc(&CG(arena), ZEND_PROPERTY_HOOK_STRUCT_SIZE);
8783
3.72k
      memset(prop_info->hooks, 0, ZEND_PROPERTY_HOOK_STRUCT_SIZE);
8784
3.72k
    }
8785
8786
4.71k
    if (prop_info->hooks[hook_kind]) {
8787
33
      zend_error_noreturn(E_COMPILE_ERROR,
8788
33
        "Cannot redeclare property hook \"%s\"", ZSTR_VAL(name));
8789
33
    }
8790
4.68k
    prop_info->hooks[hook_kind] = func;
8791
8792
4.68k
    if (hook_kind == ZEND_PROPERTY_HOOK_SET) {
8793
1.68k
      switch (zend_verify_property_hook_variance(prop_info, func)) {
8794
1.63k
        case INHERITANCE_SUCCESS:
8795
1.63k
          break;
8796
36
        case INHERITANCE_UNRESOLVED:
8797
36
          ce->num_hooked_prop_variance_checks++;
8798
36
          break;
8799
8
        case INHERITANCE_ERROR:
8800
8
          zend_hooked_property_variance_error(prop_info);
8801
0
        case INHERITANCE_WARNING:
8802
0
          ZEND_UNREACHABLE();
8803
1.68k
      }
8804
1.68k
    }
8805
8806
4.67k
    zend_string_release(name);
8807
    /* Un-share type ASTs to avoid double-frees of zval nodes. */
8808
4.67k
    if (return_type_ast_ptr) {
8809
2.93k
      *return_type_ast_ptr = NULL;
8810
2.93k
    }
8811
4.67k
    if (value_type_ast_ptr) {
8812
1.55k
      *value_type_ast_ptr = NULL;
8813
1.55k
    }
8814
4.67k
  }
8815
8816
3.71k
  ce->num_hooked_props++;
8817
8818
  /* See zend_link_hooked_object_iter(). */
8819
3.71k
#ifndef ZEND_OPCACHE_SHM_REATTACHMENT
8820
3.71k
  if (!ce->get_iterator) {
8821
    /* Will be removed again, in case of Iterator or IteratorAggregate. */
8822
2.83k
    ce->get_iterator = zend_hooked_object_get_iterator;
8823
2.83k
  }
8824
3.71k
#endif
8825
8826
3.71k
  if (!prop_info->ce->parent_name) {
8827
2.36k
    zend_verify_hooked_property(ce, prop_info, prop_name);
8828
2.36k
  }
8829
3.71k
}
8830
8831
static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags, zend_ast *attr_ast) /* {{{ */
8832
47.7k
{
8833
47.7k
  zend_ast_list *list = zend_ast_get_list(ast);
8834
47.7k
  zend_class_entry *ce = CG(active_class_entry);
8835
47.7k
  uint32_t i, children = list->children;
8836
8837
47.7k
  if (ce->ce_flags & ZEND_ACC_ENUM) {
8838
17
    zend_error_noreturn(E_COMPILE_ERROR, "Enum %s cannot include properties", ZSTR_VAL(ce->name));
8839
17
  }
8840
8841
47.7k
  if ((flags & ZEND_ACC_FINAL) && (flags & ZEND_ACC_PRIVATE)) {
8842
7
    zend_error_noreturn(E_COMPILE_ERROR, "Property cannot be both final and private");
8843
7
  }
8844
8845
47.7k
  if (ce->ce_flags & ZEND_ACC_INTERFACE) {
8846
297
    if (flags & ZEND_ACC_FINAL) {
8847
7
      zend_error_noreturn(E_COMPILE_ERROR, "Property in interface cannot be final");
8848
7
    }
8849
290
    if (flags & (ZEND_ACC_PROTECTED|ZEND_ACC_PRIVATE)) {
8850
7
      zend_error_noreturn(E_COMPILE_ERROR, "Property in interface cannot be protected or private");
8851
7
    }
8852
283
    if (flags & ZEND_ACC_ABSTRACT) {
8853
7
      zend_error_noreturn(E_COMPILE_ERROR,
8854
7
        "Property in interface cannot be explicitly abstract. "
8855
7
        "All interface members are implicitly abstract");
8856
7
    }
8857
276
    flags |= ZEND_ACC_ABSTRACT;
8858
276
  }
8859
8860
95.6k
  for (i = 0; i < children; ++i) {
8861
48.2k
    zend_property_info *info;
8862
48.2k
    zend_ast *prop_ast = list->child[i];
8863
48.2k
    zend_ast *name_ast = prop_ast->child[0];
8864
48.2k
    zend_ast **value_ast_ptr = &prop_ast->child[1];
8865
48.2k
    zend_ast *doc_comment_ast = prop_ast->child[2];
8866
48.2k
    zend_ast *hooks_ast = prop_ast->child[3];
8867
48.2k
    zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast));
8868
48.2k
    zend_string *doc_comment = NULL;
8869
48.2k
    zval value_zv;
8870
48.2k
    zend_type type = ZEND_TYPE_INIT_NONE(0);
8871
48.2k
    flags |= zend_property_is_virtual(ce, name, hooks_ast, flags) ? ZEND_ACC_VIRTUAL : 0;
8872
8873
48.2k
    zend_string *old_active_property_info_name = CG(context).active_property_info_name;
8874
48.2k
    CG(context).active_property_info_name = name;
8875
8876
48.2k
    if (!hooks_ast) {
8877
44.2k
      if (ce->ce_flags & ZEND_ACC_INTERFACE) {
8878
1
        zend_error_noreturn(E_COMPILE_ERROR,
8879
1
          "Interfaces may only include hooked properties");
8880
1
      }
8881
44.2k
      if (flags & ZEND_ACC_ABSTRACT) {
8882
8
        zend_error_noreturn(E_COMPILE_ERROR,
8883
8
          "Only hooked properties may be declared abstract");
8884
8
      }
8885
44.2k
    }
8886
48.1k
    if ((flags & ZEND_ACC_ABSTRACT)) {
8887
822
      ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
8888
822
    }
8889
8890
48.1k
    if (type_ast) {
8891
35.6k
      type = zend_compile_typename(type_ast);
8892
8893
35.6k
      if (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_VOID|MAY_BE_NEVER|MAY_BE_CALLABLE)) {
8894
7
        zend_string *str = zend_type_to_string(type);
8895
7
        zend_error_noreturn(E_COMPILE_ERROR,
8896
7
          "Property %s::$%s cannot have type %s",
8897
7
          ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(str));
8898
7
      }
8899
35.6k
    }
8900
8901
    /* Doc comment has been appended as last element in ZEND_AST_PROP_ELEM ast */
8902
48.1k
    if (doc_comment_ast) {
8903
384
      doc_comment = zend_string_copy(zend_ast_get_str(doc_comment_ast));
8904
384
    }
8905
8906
48.1k
    if (zend_hash_exists(&ce->properties_info, name)) {
8907
55
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s",
8908
55
        ZSTR_VAL(ce->name), ZSTR_VAL(name));
8909
55
    }
8910
8911
48.1k
    if (*value_ast_ptr) {
8912
7.60k
      zend_const_expr_to_zval(&value_zv, value_ast_ptr, /* allow_dynamic */ false);
8913
8914
7.60k
      if (ZEND_TYPE_IS_SET(type) && !Z_CONSTANT(value_zv)
8915
1.36k
          && !zend_is_valid_default_value(type, &value_zv)) {
8916
92
        zend_string *str = zend_type_to_string(type);
8917
92
        if (Z_TYPE(value_zv) == IS_NULL && !ZEND_TYPE_IS_INTERSECTION(type)) {
8918
27
          ZEND_TYPE_FULL_MASK(type) |= MAY_BE_NULL;
8919
27
          zend_string *nullable_str = zend_type_to_string(type);
8920
8921
27
          zend_error_noreturn(E_COMPILE_ERROR,
8922
27
            "Default value for property of type %s may not be null. "
8923
27
            "Use the nullable type %s to allow null default value",
8924
27
            ZSTR_VAL(str), ZSTR_VAL(nullable_str));
8925
65
        } else {
8926
65
          zend_error_noreturn(E_COMPILE_ERROR,
8927
65
            "Cannot use %s as default value for property %s::$%s of type %s",
8928
65
            zend_zval_value_name(&value_zv),
8929
65
            ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(str));
8930
65
        }
8931
92
      }
8932
40.5k
    } else if (!ZEND_TYPE_IS_SET(type) && !hooks_ast) {
8933
4.31k
      ZVAL_NULL(&value_zv);
8934
36.2k
    } else {
8935
36.2k
      ZVAL_UNDEF(&value_zv);
8936
36.2k
    }
8937
8938
48.0k
    if ((ce->ce_flags & ZEND_ACC_READONLY_CLASS)) {
8939
169
      flags |= ZEND_ACC_READONLY;
8940
169
    }
8941
8942
48.0k
    if (flags & ZEND_ACC_READONLY) {
8943
640
      if (!ZEND_TYPE_IS_SET(type)) {
8944
17
        zend_error_noreturn(E_COMPILE_ERROR, "Readonly property %s::$%s must have type",
8945
17
          ZSTR_VAL(ce->name), ZSTR_VAL(name));
8946
17
      }
8947
623
      if (!Z_ISUNDEF(value_zv)) {
8948
7
        zend_error_noreturn(E_COMPILE_ERROR,
8949
7
          "Readonly property %s::$%s cannot have default value",
8950
7
          ZSTR_VAL(ce->name), ZSTR_VAL(name));
8951
7
      }
8952
616
      if (flags & ZEND_ACC_STATIC) {
8953
13
        zend_error_noreturn(E_COMPILE_ERROR,
8954
13
          "Static property %s::$%s cannot be readonly",
8955
13
          ZSTR_VAL(ce->name), ZSTR_VAL(name));
8956
13
      }
8957
616
    }
8958
8959
48.0k
    info = zend_declare_typed_property(ce, name, &value_zv, flags, doc_comment, type);
8960
8961
48.0k
    if (hooks_ast) {
8962
3.94k
      zend_compile_property_hooks(info, name, type_ast, zend_ast_get_list(hooks_ast));
8963
3.94k
    }
8964
8965
48.0k
    if (attr_ast) {
8966
1.00k
      zend_compile_attributes(&info->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_PROPERTY, 0);
8967
8968
1.00k
      zend_attribute *override_attribute = zend_get_attribute_str(info->attributes, "override", sizeof("override")-1);
8969
1.00k
      if (override_attribute) {
8970
89
        info->flags |= ZEND_ACC_OVERRIDE;
8971
89
      }
8972
1.00k
    }
8973
8974
48.0k
    CG(context).active_property_info_name = old_active_property_info_name;
8975
48.0k
  }
8976
47.6k
}
8977
/* }}} */
8978
8979
static void zend_compile_prop_group(zend_ast *ast) /* {{{ */
8980
47.7k
{
8981
47.7k
  zend_ast *type_ast = ast->child[0];
8982
47.7k
  zend_ast *prop_ast = ast->child[1];
8983
47.7k
  zend_ast *attr_ast = ast->child[2];
8984
8985
47.7k
  zend_compile_prop_decl(prop_ast, type_ast, ast->attr, attr_ast);
8986
47.7k
}
8987
/* }}} */
8988
8989
static void zend_check_trait_alias_modifiers(uint32_t attr) /* {{{ */
8990
3.72k
{
8991
3.72k
  if (attr & ZEND_ACC_STATIC) {
8992
7
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"static\" as method modifier in trait alias");
8993
3.72k
  } else if (attr & ZEND_ACC_ABSTRACT) {
8994
7
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"abstract\" as method modifier in trait alias");
8995
7
  }
8996
3.72k
}
8997
/* }}} */
8998
8999
static void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_ast *attr_ast, zend_ast *type_ast)
9000
5.72k
{
9001
5.72k
  zend_ast_list *list = zend_ast_get_list(ast);
9002
5.72k
  zend_class_entry *ce = CG(active_class_entry);
9003
5.72k
  uint32_t i, children = list->children;
9004
9005
11.4k
  for (i = 0; i < children; ++i) {
9006
5.79k
    zend_class_constant *c;
9007
5.79k
    zend_ast *const_ast = list->child[i];
9008
5.79k
    zend_ast *name_ast = const_ast->child[0];
9009
5.79k
    zend_ast **value_ast_ptr = &const_ast->child[1];
9010
5.79k
    zend_ast *doc_comment_ast = const_ast->child[2];
9011
5.79k
    zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast));
9012
5.79k
    zend_string *doc_comment = doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL;
9013
5.79k
    zval value_zv;
9014
5.79k
    zend_type type = ZEND_TYPE_INIT_NONE(0);
9015
9016
5.79k
    if (type_ast) {
9017
1.64k
      type = zend_compile_typename(type_ast);
9018
9019
1.64k
      uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
9020
9021
1.64k
      if (type_mask != MAY_BE_ANY && (type_mask & (MAY_BE_CALLABLE|MAY_BE_VOID|MAY_BE_NEVER))) {
9022
7
        zend_string *type_str = zend_type_to_string(type);
9023
9024
7
        zend_error_noreturn(E_COMPILE_ERROR, "Class constant %s::%s cannot have type %s",
9025
7
          ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(type_str));
9026
7
      }
9027
1.64k
    }
9028
9029
5.78k
    if (UNEXPECTED((flags & ZEND_ACC_PRIVATE) && (flags & ZEND_ACC_FINAL))) {
9030
7
      zend_error_noreturn(
9031
7
        E_COMPILE_ERROR, "Private constant %s::%s cannot be final as it is not visible to other classes",
9032
7
        ZSTR_VAL(ce->name), ZSTR_VAL(name)
9033
7
      );
9034
7
    }
9035
9036
5.78k
    zend_const_expr_to_zval(&value_zv, value_ast_ptr, /* allow_dynamic */ false);
9037
9038
5.78k
    if (!Z_CONSTANT(value_zv) && ZEND_TYPE_IS_SET(type) && !zend_is_valid_default_value(type, &value_zv)) {
9039
43
      zend_string *type_str = zend_type_to_string(type);
9040
9041
43
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as value for class constant %s::%s of type %s",
9042
43
        zend_zval_type_name(&value_zv), ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(type_str));
9043
43
    }
9044
9045
5.73k
    c = zend_declare_typed_class_constant(ce, name, &value_zv, flags, doc_comment, type);
9046
9047
5.73k
    if (attr_ast) {
9048
175
      zend_compile_attributes(&c->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_CLASS_CONST, 0);
9049
9050
175
      zend_attribute *deprecated = zend_get_attribute_str(c->attributes, "deprecated", sizeof("deprecated")-1);
9051
9052
175
      if (deprecated) {
9053
80
        ZEND_CLASS_CONST_FLAGS(c) |= ZEND_ACC_DEPRECATED;
9054
        /* For deprecated constants, we need to flag the zval for recursion
9055
         * detection. Make sure the zval is separated out of shm. */
9056
80
        ce->ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS;
9057
80
        ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
9058
80
      }
9059
175
    }
9060
5.73k
  }
9061
5.72k
}
9062
9063
static void zend_compile_class_const_group(zend_ast *ast) /* {{{ */
9064
5.72k
{
9065
5.72k
  zend_ast *const_ast = ast->child[0];
9066
5.72k
  zend_ast *attr_ast = ast->child[1];
9067
5.72k
  zend_ast *type_ast = ast->child[2];
9068
9069
5.72k
  zend_compile_class_const_decl(const_ast, ast->attr, attr_ast, type_ast);
9070
5.72k
}
9071
/* }}} */
9072
9073
static void zend_compile_method_ref(zend_ast *ast, zend_trait_method_reference *method_ref) /* {{{ */
9074
4.89k
{
9075
4.89k
  zend_ast *class_ast = ast->child[0];
9076
4.89k
  zend_ast *method_ast = ast->child[1];
9077
9078
4.89k
  method_ref->method_name = zend_string_copy(zend_ast_get_str(method_ast));
9079
9080
4.89k
  if (class_ast) {
9081
2.25k
    method_ref->class_name = zend_resolve_const_class_name_reference(class_ast, "trait name");
9082
2.63k
  } else {
9083
2.63k
    method_ref->class_name = NULL;
9084
2.63k
  }
9085
4.89k
}
9086
/* }}} */
9087
9088
static void zend_compile_trait_precedence(zend_ast *ast) /* {{{ */
9089
1.18k
{
9090
1.18k
  zend_ast *method_ref_ast = ast->child[0];
9091
1.18k
  zend_ast *insteadof_ast = ast->child[1];
9092
1.18k
  zend_ast_list *insteadof_list = zend_ast_get_list(insteadof_ast);
9093
1.18k
  uint32_t i;
9094
9095
1.18k
  zend_trait_precedence *precedence = emalloc(sizeof(zend_trait_precedence) + (insteadof_list->children - 1) * sizeof(zend_string*));
9096
1.18k
  zend_compile_method_ref(method_ref_ast, &precedence->trait_method);
9097
1.18k
  precedence->num_excludes = insteadof_list->children;
9098
9099
3.62k
  for (i = 0; i < insteadof_list->children; ++i) {
9100
2.43k
    zend_ast *name_ast = insteadof_list->child[i];
9101
2.43k
    precedence->exclude_class_names[i] =
9102
2.43k
      zend_resolve_const_class_name_reference(name_ast, "trait name");
9103
2.43k
  }
9104
9105
1.18k
  zend_add_to_list(&CG(active_class_entry)->trait_precedences, precedence);
9106
1.18k
}
9107
/* }}} */
9108
9109
static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */
9110
3.72k
{
9111
3.72k
  zend_ast *method_ref_ast = ast->child[0];
9112
3.72k
  zend_ast *alias_ast = ast->child[1];
9113
3.72k
  uint32_t modifiers = ast->attr;
9114
9115
3.72k
  zend_trait_alias *alias;
9116
9117
3.72k
  zend_check_trait_alias_modifiers(modifiers);
9118
9119
3.72k
  alias = emalloc(sizeof(zend_trait_alias));
9120
3.72k
  zend_compile_method_ref(method_ref_ast, &alias->trait_method);
9121
3.72k
  alias->modifiers = modifiers;
9122
9123
3.72k
  if (alias_ast) {
9124
3.08k
    alias->alias = zend_string_copy(zend_ast_get_str(alias_ast));
9125
3.08k
  } else {
9126
644
    alias->alias = NULL;
9127
644
  }
9128
9129
3.72k
  zend_add_to_list(&CG(active_class_entry)->trait_aliases, alias);
9130
3.72k
}
9131
/* }}} */
9132
9133
static void zend_compile_use_trait(zend_ast *ast) /* {{{ */
9134
3.67k
{
9135
3.67k
  zend_ast_list *traits = zend_ast_get_list(ast->child[0]);
9136
3.67k
  zend_ast_list *adaptations = ast->child[1] ? zend_ast_get_list(ast->child[1]) : NULL;
9137
3.67k
  zend_class_entry *ce = CG(active_class_entry);
9138
3.67k
  uint32_t i;
9139
9140
3.67k
  ce->trait_names = erealloc(ce->trait_names, sizeof(zend_class_name) * (ce->num_traits + traits->children));
9141
9142
10.1k
  for (i = 0; i < traits->children; ++i) {
9143
6.45k
    zend_ast *trait_ast = traits->child[i];
9144
9145
6.45k
    if (ce->ce_flags & ZEND_ACC_INTERFACE) {
9146
7
      zend_string *name = zend_ast_get_str(trait_ast);
9147
7
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use traits inside of interfaces. "
9148
7
        "%s is used in %s", ZSTR_VAL(name), ZSTR_VAL(ce->name));
9149
7
    }
9150
9151
6.44k
    ce->trait_names[ce->num_traits].name =
9152
6.44k
      zend_resolve_const_class_name_reference(trait_ast, "trait name");
9153
6.44k
    ce->trait_names[ce->num_traits].lc_name = zend_string_tolower(ce->trait_names[ce->num_traits].name);
9154
6.44k
    ce->num_traits++;
9155
6.44k
  }
9156
9157
3.66k
  if (!adaptations) {
9158
2.61k
    return;
9159
2.61k
  }
9160
9161
5.94k
  for (i = 0; i < adaptations->children; ++i) {
9162
4.90k
    zend_ast *adaptation_ast = adaptations->child[i];
9163
4.90k
    switch (adaptation_ast->kind) {
9164
1.18k
      case ZEND_AST_TRAIT_PRECEDENCE:
9165
1.18k
        zend_compile_trait_precedence(adaptation_ast);
9166
1.18k
        break;
9167
3.72k
      case ZEND_AST_TRAIT_ALIAS:
9168
3.72k
        zend_compile_trait_alias(adaptation_ast);
9169
3.72k
        break;
9170
4.90k
      EMPTY_SWITCH_DEFAULT_CASE()
9171
4.90k
    }
9172
4.90k
  }
9173
1.04k
}
9174
/* }}} */
9175
9176
static void zend_compile_implements(zend_ast *ast) /* {{{ */
9177
2.92k
{
9178
2.92k
  zend_ast_list *list = zend_ast_get_list(ast);
9179
2.92k
  zend_class_entry *ce = CG(active_class_entry);
9180
2.92k
  zend_class_name *interface_names;
9181
2.92k
  uint32_t i;
9182
9183
2.92k
  interface_names = emalloc(sizeof(zend_class_name) * list->children);
9184
9185
7.43k
  for (i = 0; i < list->children; ++i) {
9186
4.51k
    zend_ast *class_ast = list->child[i];
9187
4.51k
    interface_names[i].name =
9188
4.51k
      zend_resolve_const_class_name_reference(class_ast, "interface name");
9189
4.51k
    interface_names[i].lc_name = zend_string_tolower(interface_names[i].name);
9190
4.51k
  }
9191
9192
2.92k
  ce->num_interfaces = list->children;
9193
2.92k
  ce->interface_names = interface_names;
9194
2.92k
}
9195
/* }}} */
9196
9197
static zend_string *zend_generate_anon_class_name(zend_ast_decl *decl)
9198
2.17k
{
9199
2.17k
  zend_string *filename = CG(active_op_array)->filename;
9200
2.17k
  uint32_t start_lineno = decl->start_lineno;
9201
9202
  /* Use parent or first interface as prefix. */
9203
2.17k
  zend_string *prefix = ZSTR_KNOWN(ZEND_STR_CLASS);
9204
2.17k
  if (decl->child[0]) {
9205
195
    prefix = zend_resolve_const_class_name_reference(decl->child[0], "class name");
9206
1.98k
  } else if (decl->child[1]) {
9207
557
    zend_ast_list *list = zend_ast_get_list(decl->child[1]);
9208
557
    prefix = zend_resolve_const_class_name_reference(list->child[0], "interface name");
9209
557
  }
9210
9211
2.17k
  zend_string *result = zend_strpprintf(0, "%s@anonymous%c%s:%" PRIu32 "$%" PRIx32,
9212
2.17k
    ZSTR_VAL(prefix), '\0', ZSTR_VAL(filename), start_lineno, CG(rtd_key_counter)++);
9213
2.17k
  zend_string_release(prefix);
9214
2.17k
  return zend_new_interned_string(result);
9215
2.17k
}
9216
9217
static void zend_compile_enum_backing_type(zend_class_entry *ce, zend_ast *enum_backing_type_ast)
9218
796
{
9219
796
  ZEND_ASSERT(ce->ce_flags & ZEND_ACC_ENUM);
9220
796
  zend_type type = zend_compile_typename(enum_backing_type_ast);
9221
796
  uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
9222
796
  if (ZEND_TYPE_IS_COMPLEX(type) || (type_mask != MAY_BE_LONG && type_mask != MAY_BE_STRING)) {
9223
63
    zend_string *type_string = zend_type_to_string(type);
9224
63
    zend_error_noreturn(E_COMPILE_ERROR,
9225
63
      "Enum backing type must be int or string, %s given",
9226
63
      ZSTR_VAL(type_string));
9227
63
  }
9228
733
  if (type_mask == MAY_BE_LONG) {
9229
504
    ce->enum_backing_type = IS_LONG;
9230
504
  } else {
9231
229
    ZEND_ASSERT(type_mask == MAY_BE_STRING);
9232
229
    ce->enum_backing_type = IS_STRING;
9233
228
  }
9234
733
  zend_type_release(type, 0);
9235
732
}
9236
9237
static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) /* {{{ */
9238
113k
{
9239
113k
  zend_ast_decl *decl = (zend_ast_decl *) ast;
9240
113k
  zend_ast *extends_ast = decl->child[0];
9241
113k
  zend_ast *implements_ast = decl->child[1];
9242
113k
  zend_ast *stmt_ast = decl->child[2];
9243
113k
  zend_ast *enum_backing_type_ast = decl->child[4];
9244
113k
  zend_string *name, *lcname;
9245
113k
  zend_class_entry *ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry));
9246
113k
  zend_op *opline;
9247
9248
113k
  zend_class_entry *original_ce = CG(active_class_entry);
9249
9250
113k
  if (EXPECTED((decl->flags & ZEND_ACC_ANON_CLASS) == 0)) {
9251
110k
    zend_string *unqualified_name = decl->name;
9252
9253
110k
    if (CG(active_class_entry)) {
9254
10
      zend_error_noreturn(E_COMPILE_ERROR, "Class declarations may not be nested");
9255
10
    }
9256
9257
110k
    const char *type = "a class name";
9258
110k
    if (decl->flags & ZEND_ACC_ENUM) {
9259
5.94k
      type = "an enum name";
9260
104k
    } else if (decl->flags & ZEND_ACC_INTERFACE) {
9261
9.93k
      type = "an interface name";
9262
95.0k
    } else if (decl->flags & ZEND_ACC_TRAIT) {
9263
3.31k
      type = "a trait name";
9264
3.31k
    }
9265
110k
    zend_assert_valid_class_name(unqualified_name, type);
9266
110k
    name = zend_prefix_with_ns(unqualified_name);
9267
110k
    name = zend_new_interned_string(name);
9268
110k
    lcname = zend_string_tolower(name);
9269
9270
110k
    if (FC(imports)) {
9271
879
      zend_string *import_name =
9272
879
        zend_hash_find_ptr_lc(FC(imports), unqualified_name);
9273
879
      if (import_name && !zend_string_equals_ci(lcname, import_name)) {
9274
14
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare class %s "
9275
14
            "(previously declared as local import)", ZSTR_VAL(name));
9276
14
      }
9277
879
    }
9278
9279
110k
    zend_register_seen_symbol(lcname, ZEND_SYMBOL_CLASS);
9280
110k
  } else {
9281
    /* Find an anon class name that is not in use yet. */
9282
2.17k
    name = NULL;
9283
2.17k
    lcname = NULL;
9284
2.17k
    do {
9285
2.17k
      zend_tmp_string_release(name);
9286
2.17k
      zend_tmp_string_release(lcname);
9287
2.17k
      name = zend_generate_anon_class_name(decl);
9288
2.17k
      lcname = zend_string_tolower(name);
9289
2.17k
    } while (zend_hash_exists(CG(class_table), lcname));
9290
2.17k
  }
9291
113k
  lcname = zend_new_interned_string(lcname);
9292
9293
113k
  ce->type = ZEND_USER_CLASS;
9294
113k
  ce->name = name;
9295
113k
  zend_initialize_class_data(ce, true);
9296
113k
  if (!(decl->flags & ZEND_ACC_ANON_CLASS)) {
9297
110k
    zend_alloc_ce_cache(ce->name);
9298
110k
  }
9299
9300
113k
  if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
9301
0
    ce->ce_flags |= ZEND_ACC_PRELOADED;
9302
0
    ZEND_MAP_PTR_NEW(ce->static_members_table);
9303
0
    ZEND_MAP_PTR_NEW(ce->mutable_data);
9304
0
  }
9305
9306
113k
  ce->ce_flags |= decl->flags;
9307
113k
  ce->info.user.filename = zend_string_copy(zend_get_compiled_filename());
9308
113k
  ce->info.user.line_start = decl->start_lineno;
9309
113k
  ce->info.user.line_end = decl->end_lineno;
9310
9311
113k
  if (decl->doc_comment) {
9312
105
    ce->doc_comment = zend_string_copy(decl->doc_comment);
9313
105
  }
9314
9315
113k
  if (UNEXPECTED((decl->flags & ZEND_ACC_ANON_CLASS))) {
9316
    /* Serialization is not supported for anonymous classes */
9317
2.17k
    ce->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE;
9318
2.17k
  }
9319
9320
113k
  if (extends_ast) {
9321
36.5k
    ce->parent_name =
9322
36.5k
      zend_resolve_const_class_name_reference(extends_ast, "class name");
9323
36.5k
  }
9324
9325
113k
  CG(active_class_entry) = ce;
9326
9327
113k
  if (decl->child[3]) {
9328
2.39k
    zend_compile_attributes(&ce->attributes, decl->child[3], 0, ZEND_ATTRIBUTE_TARGET_CLASS, 0);
9329
2.39k
  }
9330
9331
113k
  if (implements_ast) {
9332
2.92k
    zend_compile_implements(implements_ast);
9333
2.92k
  }
9334
9335
113k
  if (ce->ce_flags & ZEND_ACC_ENUM) {
9336
5.91k
    if (enum_backing_type_ast != NULL) {
9337
796
      zend_compile_enum_backing_type(ce, enum_backing_type_ast);
9338
796
    }
9339
5.91k
    zend_enum_add_interfaces(ce);
9340
5.91k
    zend_enum_register_props(ce);
9341
5.91k
  }
9342
9343
113k
  zend_compile_stmt(stmt_ast);
9344
9345
  /* Reset lineno for final opcodes and errors */
9346
113k
  CG(zend_lineno) = ast->lineno;
9347
9348
113k
  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) {
9349
99
    zend_verify_abstract_class(ce);
9350
99
  }
9351
9352
113k
  CG(active_class_entry) = original_ce;
9353
9354
113k
  if (toplevel) {
9355
44.4k
    ce->ce_flags |= ZEND_ACC_TOP_LEVEL;
9356
44.4k
  }
9357
9358
113k
  if (ce->__serialize == NULL && zend_hash_exists(&ce->function_table, ZSTR_KNOWN(ZEND_STR_SLEEP))) {
9359
458
    zend_error(E_DEPRECATED, "The __sleep() serialization magic method has been deprecated."
9360
458
      " Implement __serialize() instead (or in addition, if support for old PHP versions is necessary)");
9361
458
  }
9362
113k
  if (ce->__unserialize == NULL && zend_hash_exists(&ce->function_table, ZSTR_KNOWN(ZEND_STR_WAKEUP))) {
9363
48
    zend_error(E_DEPRECATED, "The __wakeup() serialization magic method has been deprecated."
9364
48
      " Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary)");
9365
48
  }
9366
9367
  /* We currently don't early-bind classes that implement interfaces or use traits */
9368
113k
  if (!ce->num_interfaces && !ce->num_traits && !ce->num_hooked_prop_variance_checks
9369
#ifdef ZEND_OPCACHE_SHM_REATTACHMENT
9370
   /* See zend_link_hooked_object_iter(). */
9371
   && !ce->num_hooked_props
9372
#endif
9373
98.8k
   && !(CG(compiler_options) & ZEND_COMPILE_WITHOUT_EXECUTION)) {
9374
98.8k
    if (toplevel) {
9375
35.6k
      if (extends_ast) {
9376
10.3k
        zend_class_entry *parent_ce = zend_lookup_class_ex(
9377
10.3k
          ce->parent_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
9378
9379
10.3k
        if (parent_ce
9380
9.24k
         && !zend_compile_ignore_class(parent_ce, ce->info.user.filename)) {
9381
9.24k
          if (zend_try_early_bind(ce, parent_ce, lcname, NULL)) {
9382
4.92k
            zend_string_release(lcname);
9383
4.92k
            return;
9384
4.92k
          }
9385
9.24k
        }
9386
25.3k
      } else if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) {
9387
20.7k
        zend_string_release(lcname);
9388
20.7k
        zend_build_properties_info_table(ce);
9389
20.7k
        zend_inheritance_check_override(ce);
9390
20.7k
        ce->ce_flags |= ZEND_ACC_LINKED;
9391
20.7k
        zend_observer_class_linked_notify(ce, lcname);
9392
20.7k
        return;
9393
20.7k
      } else {
9394
4.57k
        goto link_unbound;
9395
4.57k
      }
9396
63.2k
    } else if (!extends_ast) {
9397
42.2k
link_unbound:
9398
      /* Link unbound simple class */
9399
42.2k
      zend_build_properties_info_table(ce);
9400
42.2k
      zend_inheritance_check_override(ce);
9401
42.2k
      ce->ce_flags |= ZEND_ACC_LINKED;
9402
42.2k
    }
9403
98.8k
  }
9404
9405
87.4k
  opline = get_next_op();
9406
9407
87.4k
  if (ce->parent_name) {
9408
    /* Lowercased parent name */
9409
30.5k
    zend_string *lc_parent_name = zend_string_tolower(ce->parent_name);
9410
30.5k
    opline->op2_type = IS_CONST;
9411
30.5k
    LITERAL_STR(opline->op2, lc_parent_name);
9412
30.5k
  }
9413
9414
87.4k
  opline->op1_type = IS_CONST;
9415
  /* It's possible that `lcname` is not an interned string because it was not yet in the interned string table.
9416
   * However, by this point another thread may have caused `lcname` to be added in the interned string table.
9417
   * This will cause `lcname` to get freed once it is found in the interned string table. If we were to use
9418
   * LITERAL_STR() here we would not change the `lcname` pointer to the new value, and it would point to the
9419
   * now-freed string. This will cause issues when we use `lcname` in the code below. We solve this by using
9420
   * zend_add_literal_string() which gives us the new value. */
9421
87.4k
  opline->op1.constant = zend_add_literal_string(&lcname);
9422
9423
87.4k
  if (decl->flags & ZEND_ACC_ANON_CLASS) {
9424
2.14k
    opline->opcode = ZEND_DECLARE_ANON_CLASS;
9425
2.14k
    opline->extended_value = zend_alloc_cache_slot();
9426
2.14k
    zend_make_var_result(result, opline);
9427
2.14k
    if (!zend_hash_add_ptr(CG(class_table), lcname, ce)) {
9428
      /* We checked above that the class name is not used. This really shouldn't happen. */
9429
0
      zend_error_noreturn(E_ERROR,
9430
0
        "Runtime definition key collision for %s. This is a bug", ZSTR_VAL(name));
9431
0
    }
9432
85.3k
  } else {
9433
    /* Generate RTD keys until we find one that isn't in use yet. */
9434
85.3k
    zend_string *key = NULL;
9435
85.3k
    do {
9436
85.3k
      zend_tmp_string_release(key);
9437
85.3k
      key = zend_build_runtime_definition_key(lcname, decl->start_lineno);
9438
85.3k
    } while (!zend_hash_add_ptr(CG(class_table), key, ce));
9439
9440
    /* RTD key is placed after lcname literal in op1 */
9441
85.3k
    zend_add_literal_string(&key);
9442
9443
85.3k
    opline->opcode = ZEND_DECLARE_CLASS;
9444
85.3k
    if (toplevel
9445
17.7k
       && (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING)
9446
        /* We currently don't early-bind classes that implement interfaces or use traits */
9447
5.82k
       && !ce->num_interfaces && !ce->num_traits && !ce->num_hooked_prop_variance_checks
9448
85.3k
    ) {
9449
1.39k
      if (!extends_ast) {
9450
        /* Use empty string for classes without parents to avoid new handler, and special
9451
         * handling of zend_early_binding. */
9452
836
        opline->op2_type = IS_CONST;
9453
836
        LITERAL_STR(opline->op2, ZSTR_EMPTY_ALLOC());
9454
836
      }
9455
1.39k
      CG(active_op_array)->fn_flags |= ZEND_ACC_EARLY_BINDING;
9456
1.39k
      opline->opcode = ZEND_DECLARE_CLASS_DELAYED;
9457
1.39k
      opline->extended_value = zend_alloc_cache_slot();
9458
1.39k
      opline->result_type = IS_UNUSED;
9459
1.39k
      opline->result.opline_num = -1;
9460
1.39k
    }
9461
85.3k
  }
9462
87.4k
}
9463
/* }}} */
9464
9465
static void zend_compile_enum_case(zend_ast *ast)
9466
3.16k
{
9467
3.16k
  zend_class_entry *enum_class = CG(active_class_entry);
9468
3.16k
  if (!(enum_class->ce_flags & ZEND_ACC_ENUM)) {
9469
7
    zend_error_noreturn(E_COMPILE_ERROR, "Case can only be used in enums");
9470
7
  }
9471
9472
3.15k
  zend_string *enum_case_name = zval_make_interned_string(zend_ast_get_zval(ast->child[0]));
9473
3.15k
  zend_string *enum_class_name = enum_class->name;
9474
9475
3.15k
  zval class_name_zval;
9476
3.15k
  ZVAL_STR_COPY(&class_name_zval, enum_class_name);
9477
3.15k
  zend_ast *class_name_ast = zend_ast_create_zval(&class_name_zval);
9478
9479
3.15k
  zval case_name_zval;
9480
3.15k
  ZVAL_STR_COPY(&case_name_zval, enum_case_name);
9481
3.15k
  zend_ast *case_name_ast = zend_ast_create_zval(&case_name_zval);
9482
9483
3.15k
  zend_ast *case_value_ast = ast->child[1];
9484
  // Remove case_value_ast from the original AST to avoid freeing it, as it will be freed by zend_const_expr_to_zval
9485
3.15k
  ast->child[1] = NULL;
9486
3.15k
  if (enum_class->enum_backing_type != IS_UNDEF && case_value_ast == NULL) {
9487
8
    zend_error_noreturn(E_COMPILE_ERROR, "Case %s of backed enum %s must have a value",
9488
8
      ZSTR_VAL(enum_case_name),
9489
8
      ZSTR_VAL(enum_class_name));
9490
3.14k
  } else if (enum_class->enum_backing_type == IS_UNDEF && case_value_ast != NULL) {
9491
15
    zend_error_noreturn(E_COMPILE_ERROR, "Case %s of non-backed enum %s must not have a value",
9492
15
      ZSTR_VAL(enum_case_name),
9493
15
      ZSTR_VAL(enum_class_name));
9494
15
  }
9495
9496
3.13k
  zend_ast *const_enum_init_ast = zend_ast_create(ZEND_AST_CONST_ENUM_INIT, class_name_ast, case_name_ast, case_value_ast);
9497
9498
3.13k
  zval value_zv;
9499
3.13k
  zend_const_expr_to_zval(&value_zv, &const_enum_init_ast, /* allow_dynamic */ false);
9500
9501
  /* Doc comment has been appended as second last element in ZEND_AST_ENUM ast - attributes are conventionally last */
9502
3.13k
  zend_ast *doc_comment_ast = ast->child[2];
9503
3.13k
  zend_string *doc_comment = NULL;
9504
3.13k
  if (doc_comment_ast) {
9505
238
    doc_comment = zend_string_copy(zend_ast_get_str(doc_comment_ast));
9506
238
  }
9507
9508
3.13k
  zend_class_constant *c = zend_declare_class_constant_ex(enum_class, enum_case_name, &value_zv, ZEND_ACC_PUBLIC, doc_comment);
9509
3.13k
  ZEND_CLASS_CONST_FLAGS(c) |= ZEND_CLASS_CONST_IS_CASE;
9510
3.13k
  zend_ast_destroy(const_enum_init_ast);
9511
9512
3.13k
  zend_ast *attr_ast = ast->child[3];
9513
3.13k
  if (attr_ast) {
9514
141
    zend_compile_attributes(&c->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_CLASS_CONST, 0);
9515
9516
141
    zend_attribute *deprecated = zend_get_attribute_str(c->attributes, "deprecated", sizeof("deprecated")-1);
9517
9518
141
    if (deprecated) {
9519
46
      ZEND_CLASS_CONST_FLAGS(c) |= ZEND_ACC_DEPRECATED;
9520
46
    }
9521
141
  }
9522
3.13k
}
9523
9524
static HashTable *zend_get_import_ht(uint32_t type) /* {{{ */
9525
1.89k
{
9526
1.89k
  switch (type) {
9527
1.14k
    case ZEND_SYMBOL_CLASS:
9528
1.14k
      if (!FC(imports)) {
9529
839
        FC(imports) = emalloc(sizeof(HashTable));
9530
839
        zend_hash_init(FC(imports), 8, NULL, str_dtor, 0);
9531
839
      }
9532
1.14k
      return FC(imports);
9533
513
    case ZEND_SYMBOL_FUNCTION:
9534
513
      if (!FC(imports_function)) {
9535
435
        FC(imports_function) = emalloc(sizeof(HashTable));
9536
435
        zend_hash_init(FC(imports_function), 8, NULL, str_dtor, 0);
9537
435
      }
9538
513
      return FC(imports_function);
9539
237
    case ZEND_SYMBOL_CONST:
9540
237
      if (!FC(imports_const)) {
9541
173
        FC(imports_const) = emalloc(sizeof(HashTable));
9542
173
        zend_hash_init(FC(imports_const), 8, NULL, str_dtor, 0);
9543
173
      }
9544
237
      return FC(imports_const);
9545
1.89k
    EMPTY_SWITCH_DEFAULT_CASE()
9546
1.89k
  }
9547
9548
0
  return NULL;
9549
1.89k
}
9550
/* }}} */
9551
9552
static char *zend_get_use_type_str(uint32_t type) /* {{{ */
9553
85
{
9554
85
  switch (type) {
9555
50
    case ZEND_SYMBOL_CLASS:
9556
50
      return "";
9557
21
    case ZEND_SYMBOL_FUNCTION:
9558
21
      return " function";
9559
14
    case ZEND_SYMBOL_CONST:
9560
14
      return " const";
9561
85
    EMPTY_SWITCH_DEFAULT_CASE()
9562
85
  }
9563
9564
0
  return " unknown";
9565
85
}
9566
/* }}} */
9567
9568
static void zend_check_already_in_use(uint32_t type, zend_string *old_name, zend_string *new_name, zend_string *check_name) /* {{{ */
9569
64
{
9570
64
  if (zend_string_equals_ci(old_name, check_name)) {
9571
28
    return;
9572
28
  }
9573
9574
36
  zend_error_noreturn(E_COMPILE_ERROR, "Cannot use%s %s as %s because the name "
9575
36
    "is already in use", zend_get_use_type_str(type), ZSTR_VAL(old_name), ZSTR_VAL(new_name));
9576
64
}
9577
/* }}} */
9578
9579
static void zend_compile_use(zend_ast *ast) /* {{{ */
9580
1.89k
{
9581
1.89k
  zend_ast_list *list = zend_ast_get_list(ast);
9582
1.89k
  uint32_t i;
9583
1.89k
  zend_string *current_ns = FC(current_namespace);
9584
1.89k
  uint32_t type = ast->attr;
9585
1.89k
  HashTable *current_import = zend_get_import_ht(type);
9586
1.89k
  bool case_sensitive = type == ZEND_SYMBOL_CONST;
9587
9588
3.90k
  for (i = 0; i < list->children; ++i) {
9589
2.10k
    zend_ast *use_ast = list->child[i];
9590
2.10k
    zend_ast *old_name_ast = use_ast->child[0];
9591
2.10k
    zend_ast *new_name_ast = use_ast->child[1];
9592
2.10k
    zend_string *old_name = zend_ast_get_str(old_name_ast);
9593
2.10k
    zend_string *new_name, *lookup_name;
9594
9595
2.10k
    if (new_name_ast) {
9596
416
      new_name = zend_string_copy(zend_ast_get_str(new_name_ast));
9597
1.68k
    } else {
9598
1.68k
      const char *unqualified_name;
9599
1.68k
      size_t unqualified_name_len;
9600
1.68k
      if (zend_get_unqualified_name(old_name, &unqualified_name, &unqualified_name_len)) {
9601
        /* The form "use A\B" is equivalent to "use A\B as B" */
9602
767
        new_name = zend_string_init(unqualified_name, unqualified_name_len, 0);
9603
917
      } else {
9604
917
        new_name = zend_string_copy(old_name);
9605
9606
917
        if (!current_ns) {
9607
641
          zend_error(E_WARNING, "The use statement with non-compound name '%s' "
9608
641
            "has no effect", ZSTR_VAL(new_name));
9609
641
        }
9610
917
      }
9611
1.68k
    }
9612
9613
2.10k
    if (case_sensitive) {
9614
261
      lookup_name = zend_string_copy(new_name);
9615
1.83k
    } else {
9616
1.83k
      lookup_name = zend_string_tolower(new_name);
9617
1.83k
    }
9618
9619
2.10k
    if (type == ZEND_SYMBOL_CLASS && zend_is_reserved_class_name(new_name)) {
9620
32
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' "
9621
32
        "is a special class name", ZSTR_VAL(old_name), ZSTR_VAL(new_name), ZSTR_VAL(new_name));
9622
32
    }
9623
9624
2.06k
    if (current_ns) {
9625
836
      zend_string *ns_name = zend_string_alloc(ZSTR_LEN(current_ns) + 1 + ZSTR_LEN(new_name), 0);
9626
836
      zend_str_tolower_copy(ZSTR_VAL(ns_name), ZSTR_VAL(current_ns), ZSTR_LEN(current_ns));
9627
836
      ZSTR_VAL(ns_name)[ZSTR_LEN(current_ns)] = '\\';
9628
836
      memcpy(ZSTR_VAL(ns_name) + ZSTR_LEN(current_ns) + 1, ZSTR_VAL(lookup_name), ZSTR_LEN(lookup_name) + 1);
9629
9630
836
      if (zend_have_seen_symbol(ns_name, type)) {
9631
35
        zend_check_already_in_use(type, old_name, new_name, ns_name);
9632
35
      }
9633
9634
836
      zend_string_efree(ns_name);
9635
1.23k
    } else if (zend_have_seen_symbol(lookup_name, type)) {
9636
29
      zend_check_already_in_use(type, old_name, new_name, lookup_name);
9637
29
    }
9638
9639
2.06k
    zend_string_addref(old_name);
9640
2.06k
    old_name = zend_new_interned_string(old_name);
9641
2.06k
    if (!zend_hash_add_ptr(current_import, lookup_name, old_name)) {
9642
49
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use%s %s as %s because the name "
9643
49
        "is already in use", zend_get_use_type_str(type), ZSTR_VAL(old_name), ZSTR_VAL(new_name));
9644
49
    }
9645
9646
2.01k
    zend_string_release_ex(lookup_name, 0);
9647
2.01k
    zend_string_release_ex(new_name, 0);
9648
2.01k
  }
9649
1.89k
}
9650
/* }}} */
9651
9652
static void zend_compile_group_use(zend_ast *ast) /* {{{ */
9653
189
{
9654
189
  uint32_t i;
9655
189
  zend_string *ns = zend_ast_get_str(ast->child[0]);
9656
189
  zend_ast_list *list = zend_ast_get_list(ast->child[1]);
9657
9658
661
  for (i = 0; i < list->children; i++) {
9659
472
    zend_ast *inline_use, *use = list->child[i];
9660
472
    zval *name_zval = zend_ast_get_zval(use->child[0]);
9661
472
    zend_string *name = Z_STR_P(name_zval);
9662
472
    zend_string *compound_ns = zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
9663
472
    zend_string_release_ex(name, 0);
9664
472
    ZVAL_STR(name_zval, compound_ns);
9665
472
    inline_use = zend_ast_create_list(1, ZEND_AST_USE, use);
9666
472
    inline_use->attr = ast->attr ? ast->attr : use->attr;
9667
472
    zend_compile_use(inline_use);
9668
472
  }
9669
189
}
9670
/* }}} */
9671
9672
static void zend_compile_const_decl(zend_ast *ast) /* {{{ */
9673
5.53k
{
9674
5.53k
  zend_ast_list *list = zend_ast_get_list(ast);
9675
5.53k
  uint32_t i;
9676
5.53k
  zend_ast *attributes_ast = NULL;
9677
5.53k
  zend_op *last_op = NULL;
9678
13.1k
  for (i = 0; i < list->children; ++i) {
9679
7.58k
    zend_ast *const_ast = list->child[i];
9680
7.58k
    if (const_ast->kind == ZEND_AST_ATTRIBUTE_LIST) {
9681
1.36k
      ZEND_ASSERT(i == list->children - 1);
9682
1.36k
      attributes_ast = const_ast;
9683
1.36k
      continue;
9684
1.36k
    }
9685
6.21k
    ZEND_ASSERT(const_ast->kind == ZEND_AST_CONST_ELEM);
9686
6.21k
    zend_ast *name_ast = const_ast->child[0];
9687
6.21k
    zend_ast **value_ast_ptr = &const_ast->child[1];
9688
6.21k
    zend_string *unqualified_name = zend_ast_get_str(name_ast);
9689
9690
6.21k
    zend_string *name;
9691
6.21k
    znode name_node, value_node;
9692
6.21k
    zval *value_zv = &value_node.u.constant;
9693
9694
6.21k
    value_node.op_type = IS_CONST;
9695
6.21k
    zend_const_expr_to_zval(value_zv, value_ast_ptr, /* allow_dynamic */ true);
9696
9697
6.21k
    if (zend_get_special_const(ZSTR_VAL(unqualified_name), ZSTR_LEN(unqualified_name))) {
9698
8
      zend_error_noreturn(E_COMPILE_ERROR,
9699
8
        "Cannot redeclare constant '%s'", ZSTR_VAL(unqualified_name));
9700
8
    }
9701
9702
6.20k
    name = zend_prefix_with_ns(unqualified_name);
9703
6.20k
    name = zend_new_interned_string(name);
9704
9705
6.20k
    if (FC(imports_const)) {
9706
54
      zend_string *import_name = zend_hash_find_ptr(FC(imports_const), unqualified_name);
9707
54
      if (import_name && !zend_string_equals(import_name, name)) {
9708
8
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare const %s because "
9709
8
          "the name is already in use", ZSTR_VAL(name));
9710
8
      }
9711
54
    }
9712
9713
6.19k
    name_node.op_type = IS_CONST;
9714
6.19k
    ZVAL_STR(&name_node.u.constant, name);
9715
9716
6.19k
    last_op = zend_emit_op(NULL, ZEND_DECLARE_CONST, &name_node, &value_node);
9717
9718
6.19k
    zend_register_seen_symbol(name, ZEND_SYMBOL_CONST);
9719
6.19k
  }
9720
5.52k
  if (attributes_ast == NULL) {
9721
4.05k
    return;
9722
4.05k
  }
9723
  /* Validate: attributes can only be applied to one constant at a time
9724
   * Since we store the AST for the attributes in the list of children,
9725
   * there should be exactly 2 children. */
9726
1.47k
  if (list->children > 2) {
9727
9
    zend_error_noreturn(
9728
9
      E_COMPILE_ERROR,
9729
9
      "Cannot apply attributes to multiple constants at once"
9730
9
    );
9731
9
  }
9732
9733
1.46k
  HashTable *attributes = NULL;
9734
1.46k
  zend_compile_attributes(&attributes, list->child[1], 0, ZEND_ATTRIBUTE_TARGET_CONST, 0);
9735
9736
1.46k
  ZEND_ASSERT(last_op != NULL);
9737
1.46k
  last_op->opcode = ZEND_DECLARE_ATTRIBUTED_CONST;
9738
1.34k
  znode attribs_node;
9739
1.34k
  attribs_node.op_type = IS_CONST;
9740
1.34k
  ZVAL_PTR(&attribs_node.u.constant, attributes);
9741
1.34k
  zend_emit_op_data(&attribs_node);
9742
1.34k
  CG(active_op_array)->fn_flags |= ZEND_ACC_PTR_OPS;
9743
1.34k
}
9744
/* }}}*/
9745
9746
static void zend_compile_namespace(zend_ast *ast) /* {{{ */
9747
5.44k
{
9748
5.44k
  zend_ast *name_ast = ast->child[0];
9749
5.44k
  zend_ast *stmt_ast = ast->child[1];
9750
5.44k
  zend_string *name;
9751
5.44k
  bool with_bracket = stmt_ast != NULL;
9752
9753
  /* handle mixed syntax declaration or nested namespaces */
9754
5.44k
  if (!FC(has_bracketed_namespaces)) {
9755
4.24k
    if (FC(current_namespace)) {
9756
      /* previous namespace declarations were unbracketed */
9757
962
      if (with_bracket) {
9758
6
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations "
9759
6
          "with unbracketed namespace declarations");
9760
6
      }
9761
962
    }
9762
4.24k
  } else {
9763
    /* previous namespace declarations were bracketed */
9764
1.20k
    if (!with_bracket) {
9765
6
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations "
9766
6
        "with unbracketed namespace declarations");
9767
1.19k
    } else if (FC(current_namespace) || FC(in_namespace)) {
9768
10
      zend_error_noreturn(E_COMPILE_ERROR, "Namespace declarations cannot be nested");
9769
10
    }
9770
1.20k
  }
9771
9772
5.44k
  bool is_first_namespace = (!with_bracket && !FC(current_namespace))
9773
2.68k
    || (with_bracket && !FC(has_bracketed_namespaces));
9774
5.42k
  if (is_first_namespace && FAILURE == zend_is_first_statement(ast, /* allow_nop */ true)) {
9775
38
    zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be "
9776
38
      "the very first statement or after any declare call in the script");
9777
38
  }
9778
9779
5.38k
  if (FC(current_namespace)) {
9780
956
    zend_string_release_ex(FC(current_namespace), 0);
9781
956
  }
9782
9783
5.38k
  if (name_ast) {
9784
4.69k
    name = zend_ast_get_str(name_ast);
9785
9786
4.69k
    if (zend_string_equals_literal_ci(name, "namespace")) {
9787
7
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", ZSTR_VAL(name));
9788
7
    }
9789
9790
4.68k
    FC(current_namespace) = zend_string_copy(name);
9791
4.68k
  } else {
9792
698
    FC(current_namespace) = NULL;
9793
698
  }
9794
9795
5.38k
  zend_reset_import_tables();
9796
9797
5.38k
  FC(in_namespace) = 1;
9798
5.38k
  if (with_bracket) {
9799
1.72k
    FC(has_bracketed_namespaces) = 1;
9800
1.72k
  }
9801
9802
5.38k
  if (stmt_ast) {
9803
1.72k
    zend_compile_top_stmt(stmt_ast);
9804
1.72k
    zend_end_namespace();
9805
1.72k
  }
9806
5.38k
}
9807
/* }}} */
9808
9809
static void zend_compile_halt_compiler(zend_ast *ast) /* {{{ */
9810
62
{
9811
62
  zend_ast *offset_ast = ast->child[0];
9812
62
  zend_long offset = Z_LVAL_P(zend_ast_get_zval(offset_ast));
9813
9814
62
  zend_string *filename, *name;
9815
62
  const char const_name[] = "__COMPILER_HALT_OFFSET__";
9816
9817
62
  if (FC(has_bracketed_namespaces) && FC(in_namespace)) {
9818
0
    zend_error_noreturn(E_COMPILE_ERROR,
9819
0
      "__HALT_COMPILER() can only be used from the outermost scope");
9820
0
  }
9821
9822
62
  filename = zend_get_compiled_filename();
9823
62
  name = zend_mangle_property_name(const_name, sizeof(const_name) - 1,
9824
62
    ZSTR_VAL(filename), ZSTR_LEN(filename), false);
9825
9826
  /* Avoid repeated declaration of the __COMPILER_HALT_OFFSET__ constant in
9827
   * case this file was already included. */
9828
62
  if (!zend_hash_find(EG(zend_constants), name)) {
9829
62
    zend_register_long_constant(ZSTR_VAL(name), ZSTR_LEN(name), offset, 0, 0);
9830
62
  }
9831
62
  zend_string_release_ex(name, 0);
9832
62
}
9833
/* }}} */
9834
9835
static bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */
9836
20.2k
{
9837
20.2k
  zend_op_array *op_array = CG(active_op_array);
9838
20.2k
  zend_class_entry *ce = CG(active_class_entry);
9839
9840
20.2k
  switch (ast->attr) {
9841
391
    case T_LINE:
9842
391
      ZVAL_LONG(zv, ast->lineno);
9843
391
      break;
9844
4.25k
    case T_FILE:
9845
4.25k
      ZVAL_STR_COPY(zv, CG(compiled_filename));
9846
4.25k
      break;
9847
1.74k
    case T_DIR:
9848
1.74k
    {
9849
1.74k
      zend_string *filename = CG(compiled_filename);
9850
1.74k
      zend_string *dirname = zend_string_init(ZSTR_VAL(filename), ZSTR_LEN(filename), 0);
9851
#ifdef ZEND_WIN32
9852
      ZSTR_LEN(dirname) = php_win32_ioutil_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname));
9853
#else
9854
1.74k
      ZSTR_LEN(dirname) = zend_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname));
9855
1.74k
#endif
9856
9857
1.74k
      if (zend_string_equals_literal(dirname, ".")) {
9858
1.18k
        dirname = zend_string_extend(dirname, MAXPATHLEN, 0);
9859
1.18k
#ifdef HAVE_GETCWD
9860
1.18k
        ZEND_IGNORE_VALUE(VCWD_GETCWD(ZSTR_VAL(dirname), MAXPATHLEN));
9861
#elif defined(HAVE_GETWD)
9862
        ZEND_IGNORE_VALUE(VCWD_GETWD(ZSTR_VAL(dirname)));
9863
#endif
9864
1.18k
        ZSTR_LEN(dirname) = strlen(ZSTR_VAL(dirname));
9865
1.18k
      }
9866
9867
1.74k
      ZVAL_STR(zv, dirname);
9868
1.74k
      break;
9869
0
    }
9870
1.54k
    case T_FUNC_C:
9871
1.54k
      if (op_array && op_array->function_name) {
9872
1.25k
        ZVAL_STR_COPY(zv, op_array->function_name);
9873
1.25k
      } else {
9874
291
        ZVAL_EMPTY_STRING(zv);
9875
291
      }
9876
1.54k
      break;
9877
714
    case T_PROPERTY_C: {
9878
714
      zend_string *prop_info_name = CG(context).active_property_info_name;
9879
714
      if (prop_info_name) {
9880
349
        ZVAL_STR(zv, zend_copy_unmangled_prop_name(prop_info_name));
9881
365
      } else {
9882
365
        ZVAL_EMPTY_STRING(zv);
9883
365
      }
9884
714
      break;
9885
0
    }
9886
6.00k
    case T_METHOD_C:
9887
      /* Detect whether we are directly inside a class (e.g. a class constant) and treat
9888
       * this as not being inside a function. */
9889
6.00k
      if (op_array && ce && !op_array->scope && !(op_array->fn_flags & ZEND_ACC_CLOSURE)) {
9890
210
        op_array = NULL;
9891
210
      }
9892
6.00k
      if (op_array && op_array->function_name) {
9893
5.66k
        if (op_array->scope) {
9894
5.29k
          ZVAL_NEW_STR(zv,
9895
5.29k
            zend_create_member_string(op_array->scope->name, op_array->function_name));
9896
5.29k
        } else {
9897
361
          ZVAL_STR_COPY(zv, op_array->function_name);
9898
361
        }
9899
5.66k
      } else {
9900
344
        ZVAL_EMPTY_STRING(zv);
9901
344
      }
9902
6.00k
      break;
9903
1.70k
    case T_CLASS_C:
9904
1.70k
      if (ce) {
9905
797
        if ((ce->ce_flags & ZEND_ACC_TRAIT) != 0) {
9906
359
          return 0;
9907
438
        } else {
9908
438
          ZVAL_STR_COPY(zv, ce->name);
9909
438
        }
9910
912
      } else {
9911
912
        ZVAL_EMPTY_STRING(zv);
9912
912
      }
9913
1.35k
      break;
9914
3.10k
    case T_TRAIT_C:
9915
3.10k
      if (ce && (ce->ce_flags & ZEND_ACC_TRAIT) != 0) {
9916
587
        ZVAL_STR_COPY(zv, ce->name);
9917
2.51k
      } else {
9918
2.51k
        ZVAL_EMPTY_STRING(zv);
9919
2.51k
      }
9920
3.10k
      break;
9921
816
    case T_NS_C:
9922
816
      if (FC(current_namespace)) {
9923
548
        ZVAL_STR_COPY(zv, FC(current_namespace));
9924
548
      } else {
9925
268
        ZVAL_EMPTY_STRING(zv);
9926
268
      }
9927
816
      break;
9928
20.2k
    EMPTY_SWITCH_DEFAULT_CASE()
9929
20.2k
  }
9930
9931
19.9k
  return 1;
9932
20.2k
}
9933
/* }}} */
9934
9935
ZEND_API bool zend_is_op_long_compatible(const zval *op)
9936
76.7k
{
9937
76.7k
  if (Z_TYPE_P(op) == IS_ARRAY) {
9938
447
    return false;
9939
447
  }
9940
9941
76.2k
  if (Z_TYPE_P(op) == IS_DOUBLE
9942
19.1k
    && !zend_is_long_compatible(Z_DVAL_P(op), zend_dval_to_lval_silent(Z_DVAL_P(op)))) {
9943
12.7k
    return false;
9944
12.7k
  }
9945
9946
63.5k
  if (Z_TYPE_P(op) == IS_STRING) {
9947
9.45k
    double dval = 0;
9948
9.45k
    uint8_t is_num = is_numeric_str_function(Z_STR_P(op), NULL, &dval);
9949
9.45k
    if (is_num == 0 || (is_num == IS_DOUBLE && !zend_is_long_compatible(dval, zend_dval_to_lval_silent(dval)))) {
9950
4.32k
      return false;
9951
4.32k
    }
9952
9.45k
  }
9953
9954
59.2k
  return true;
9955
63.5k
}
9956
9957
ZEND_API bool zend_binary_op_produces_error(uint32_t opcode, const zval *op1, const zval *op2) /* {{{ */
9958
247k
{
9959
247k
  if ((opcode == ZEND_CONCAT || opcode == ZEND_FAST_CONCAT)) {
9960
    /* Array to string warning. */
9961
33.1k
    return Z_TYPE_P(op1) == IS_ARRAY || Z_TYPE_P(op2) == IS_ARRAY;
9962
33.1k
  }
9963
9964
213k
  if (!(opcode == ZEND_ADD || opcode == ZEND_SUB || opcode == ZEND_MUL || opcode == ZEND_DIV
9965
110k
               || opcode == ZEND_POW || opcode == ZEND_MOD || opcode == ZEND_SL || opcode == ZEND_SR
9966
71.9k
               || opcode == ZEND_BW_OR || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR)) {
9967
    /* Only the numeric operations throw errors. */
9968
28.1k
    return 0;
9969
28.1k
  }
9970
9971
185k
  if (Z_TYPE_P(op1) == IS_ARRAY || Z_TYPE_P(op2) == IS_ARRAY) {
9972
8.67k
    if (opcode == ZEND_ADD && Z_TYPE_P(op1) == IS_ARRAY && Z_TYPE_P(op2) == IS_ARRAY) {
9973
      /* Adding two arrays is allowed. */
9974
5.26k
      return 0;
9975
5.26k
    }
9976
9977
    /* Numeric operators throw when one of the operands is an array. */
9978
3.41k
    return 1;
9979
8.67k
  }
9980
9981
  /* While basic arithmetic operators always produce numeric string errors,
9982
   * bitwise operators don't produce errors if both operands are strings */
9983
177k
  if ((opcode == ZEND_BW_OR || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR)
9984
43.7k
    && Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
9985
18.3k
    return 0;
9986
18.3k
  }
9987
9988
158k
  if (Z_TYPE_P(op1) == IS_STRING
9989
41.7k
    && !is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), NULL, NULL, 0)) {
9990
31.1k
    return 1;
9991
31.1k
  }
9992
9993
127k
  if (Z_TYPE_P(op2) == IS_STRING
9994
12.4k
    && !is_numeric_string(Z_STRVAL_P(op2), Z_STRLEN_P(op2), NULL, NULL, 0)) {
9995
7.11k
    return 1;
9996
7.11k
  }
9997
9998
  /* Operation which cast float/float-strings to integers might produce incompatible float to int errors */
9999
120k
  if (opcode == ZEND_SL || opcode == ZEND_SR || opcode == ZEND_BW_OR
10000
113k
      || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR) {
10001
27.8k
    return !zend_is_op_long_compatible(op1) || !zend_is_op_long_compatible(op2);
10002
27.8k
  }
10003
10004
92.5k
  if (opcode == ZEND_DIV && zval_get_double(op2) == 0.0) {
10005
    /* Division by zero throws an error. */
10006
715
    return 1;
10007
715
  }
10008
10009
  /* Mod is an operation that will cast float/float-strings to integers which might
10010
     produce float to int incompatible errors, and also cannot be divided by 0 */
10011
91.8k
  if (opcode == ZEND_MOD) {
10012
11.5k
    return  !zend_is_op_long_compatible(op1) || !zend_is_op_long_compatible(op2) || zval_get_long(op2) == 0;
10013
11.5k
  }
10014
10015
80.2k
  if ((opcode == ZEND_POW) && zval_get_double(op1) == 0 && zval_get_double(op2) < 0) {
10016
    /* 0 ** (<0) throws a division by zero error. */
10017
134
    return 1;
10018
134
  }
10019
80.0k
  if ((opcode == ZEND_SL || opcode == ZEND_SR) && zval_get_long(op2) < 0) {
10020
    /* Shift by negative number throws an error. */
10021
0
    return 1;
10022
0
  }
10023
10024
80.0k
  return 0;
10025
80.0k
}
10026
/* }}} */
10027
10028
static inline bool zend_try_ct_eval_binary_op(zval *result, uint32_t opcode, zval *op1, zval *op2) /* {{{ */
10029
196k
{
10030
196k
  if (zend_binary_op_produces_error(opcode, op1, op2)) {
10031
33.6k
    return 0;
10032
33.6k
  }
10033
10034
162k
  binary_op_type fn = get_binary_op(opcode);
10035
162k
  fn(result, op1, op2);
10036
162k
  return 1;
10037
196k
}
10038
/* }}} */
10039
10040
ZEND_API bool zend_unary_op_produces_error(uint32_t opcode, const zval *op)
10041
45.3k
{
10042
45.3k
  if (opcode == ZEND_BW_NOT) {
10043
    /* BW_NOT on string does not convert the string into an integer. */
10044
7.32k
    if (Z_TYPE_P(op) == IS_STRING) {
10045
1.49k
      return 0;
10046
1.49k
    }
10047
5.83k
    return Z_TYPE_P(op) <= IS_TRUE || !zend_is_op_long_compatible(op);
10048
7.32k
  }
10049
  /* Can happen when called from zend_optimizer_eval_unary_op() */
10050
38.0k
  if (opcode == ZEND_BOOL || opcode == ZEND_BOOL_NOT) {
10051
    /* ZEND_BOOL/ZEND_BOOL_NOT warns when casting NAN. */
10052
38.0k
    return Z_TYPE_P(op) == IS_DOUBLE;
10053
38.0k
  }
10054
10055
0
  return 0;
10056
38.0k
}
10057
10058
static inline bool zend_try_ct_eval_unary_op(zval *result, uint32_t opcode, zval *op) /* {{{ */
10059
44.3k
{
10060
44.3k
  if (zend_unary_op_produces_error(opcode, op)) {
10061
2.02k
    return 0;
10062
2.02k
  }
10063
10064
42.3k
  unary_op_type fn = get_unary_op(opcode);
10065
42.3k
  fn(result, op);
10066
42.3k
  return 1;
10067
44.3k
}
10068
/* }}} */
10069
10070
static inline bool zend_try_ct_eval_unary_pm(zval *result, zend_ast_kind kind, zval *op) /* {{{ */
10071
46.0k
{
10072
46.0k
  zval right;
10073
46.0k
  ZVAL_LONG(&right, (kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
10074
46.0k
  return zend_try_ct_eval_binary_op(result, ZEND_MUL, op, &right);
10075
46.0k
}
10076
/* }}} */
10077
10078
static inline void zend_ct_eval_greater(zval *result, zend_ast_kind kind, zval *op1, zval *op2) /* {{{ */
10079
10.2k
{
10080
10.2k
  binary_op_type fn = kind == ZEND_AST_GREATER
10081
10.2k
    ? is_smaller_function : is_smaller_or_equal_function;
10082
10.2k
  fn(result, op2, op1);
10083
10.2k
}
10084
/* }}} */
10085
10086
static bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */
10087
2.74M
{
10088
2.74M
  zend_ast_list *list = zend_ast_get_list(ast);
10089
2.74M
  zend_ast *last_elem_ast = NULL;
10090
2.74M
  uint32_t i;
10091
2.74M
  bool is_constant = true;
10092
10093
2.74M
  if (ast->attr == ZEND_ARRAY_SYNTAX_LIST) {
10094
7
    zend_error(E_COMPILE_ERROR, "Cannot use list() as standalone expression");
10095
7
  }
10096
10097
  /* First ensure that *all* child nodes are constant and by-val */
10098
5.92M
  for (i = 0; i < list->children; ++i) {
10099
3.17M
    zend_ast *elem_ast = list->child[i];
10100
10101
3.17M
    if (elem_ast == NULL) {
10102
      /* Report error at line of last non-empty element */
10103
148
      if (last_elem_ast) {
10104
85
        CG(zend_lineno) = zend_ast_get_lineno(last_elem_ast);
10105
85
      }
10106
148
      zend_error(E_COMPILE_ERROR, "Cannot use empty array elements in arrays");
10107
148
    }
10108
10109
3.17M
    if (elem_ast->kind != ZEND_AST_UNPACK) {
10110
3.08M
      zend_eval_const_expr(&elem_ast->child[0]);
10111
3.08M
      zend_eval_const_expr(&elem_ast->child[1]);
10112
10113
3.08M
      if (elem_ast->attr /* by_ref */ || elem_ast->child[0]->kind != ZEND_AST_ZVAL
10114
430k
        || (elem_ast->child[1] && elem_ast->child[1]->kind != ZEND_AST_ZVAL)
10115
3.08M
      ) {
10116
2.65M
        is_constant = false;
10117
2.65M
      }
10118
3.08M
    } else {
10119
91.4k
      zend_eval_const_expr(&elem_ast->child[0]);
10120
10121
91.4k
      if (elem_ast->child[0]->kind != ZEND_AST_ZVAL) {
10122
88.2k
        is_constant = false;
10123
88.2k
      }
10124
91.4k
    }
10125
10126
3.17M
    last_elem_ast = elem_ast;
10127
3.17M
  }
10128
10129
2.74M
  if (!is_constant) {
10130
2.64M
    return 0;
10131
2.64M
  }
10132
10133
103k
  if (!list->children) {
10134
19.2k
    ZVAL_EMPTY_ARRAY(result);
10135
19.2k
    return 1;
10136
19.2k
  }
10137
10138
84.1k
  array_init_size(result, list->children);
10139
420k
  for (i = 0; i < list->children; ++i) {
10140
341k
    zend_ast *elem_ast = list->child[i];
10141
341k
    zend_ast *value_ast = elem_ast->child[0];
10142
341k
    zend_ast *key_ast;
10143
10144
341k
    zval *value = zend_ast_get_zval(value_ast);
10145
341k
    if (elem_ast->kind == ZEND_AST_UNPACK) {
10146
1.65k
      if (Z_TYPE_P(value) == IS_ARRAY) {
10147
1.64k
        HashTable *ht = Z_ARRVAL_P(value);
10148
1.64k
        zval *val;
10149
1.64k
        zend_string *key;
10150
10151
5.75k
        ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
10152
5.75k
          if (key) {
10153
348
            zend_hash_update(Z_ARRVAL_P(result), key, val);
10154
977
          } else if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), val)) {
10155
12
            zval_ptr_dtor(result);
10156
12
            return 0;
10157
12
          }
10158
1.31k
          Z_TRY_ADDREF_P(val);
10159
1.31k
        } ZEND_HASH_FOREACH_END();
10160
10161
1.63k
        continue;
10162
1.64k
      } else {
10163
11
        zend_error_noreturn(E_COMPILE_ERROR, "Only arrays and Traversables can be unpacked, %s given", zend_zval_value_name(value));
10164
11
      }
10165
1.65k
    }
10166
10167
340k
    Z_TRY_ADDREF_P(value);
10168
10169
340k
    key_ast = elem_ast->child[1];
10170
340k
    if (key_ast) {
10171
22.1k
      zval *key = zend_ast_get_zval(key_ast);
10172
22.1k
      switch (Z_TYPE_P(key)) {
10173
6.05k
        case IS_LONG:
10174
6.05k
          zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(key), value);
10175
6.05k
          break;
10176
10.2k
        case IS_STRING:
10177
10.2k
          zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(key), value);
10178
10.2k
          break;
10179
5.50k
        case IS_DOUBLE: {
10180
5.50k
          zend_long lval = zend_dval_to_lval_silent(Z_DVAL_P(key));
10181
          /* Incompatible float will generate an error, leave this to run-time */
10182
5.50k
          if (!zend_is_long_compatible(Z_DVAL_P(key), lval)) {
10183
4.96k
            zval_ptr_dtor_nogc(value);
10184
4.96k
            zval_ptr_dtor(result);
10185
4.96k
            return 0;
10186
4.96k
          }
10187
543
          zend_hash_index_update(Z_ARRVAL_P(result), lval, value);
10188
543
          break;
10189
5.50k
        }
10190
220
        case IS_FALSE:
10191
220
          zend_hash_index_update(Z_ARRVAL_P(result), 0, value);
10192
220
          break;
10193
113
        case IS_TRUE:
10194
113
          zend_hash_index_update(Z_ARRVAL_P(result), 1, value);
10195
113
          break;
10196
19
        case IS_NULL:
10197
19
          zend_hash_update(Z_ARRVAL_P(result), ZSTR_EMPTY_ALLOC(), value);
10198
19
          break;
10199
3
        default:
10200
3
          zend_error_noreturn(E_COMPILE_ERROR, "Illegal offset type");
10201
0
          break;
10202
22.1k
      }
10203
317k
    } else if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), value)) {
10204
186
      zval_ptr_dtor_nogc(value);
10205
186
      zval_ptr_dtor(result);
10206
186
      return 0;
10207
186
    }
10208
340k
  }
10209
10210
78.9k
  return 1;
10211
84.1k
}
10212
/* }}} */
10213
10214
static void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */
10215
1.22M
{
10216
1.22M
  zend_ast *left_ast = ast->child[0];
10217
1.22M
  zend_ast *right_ast = ast->child[1];
10218
1.22M
  uint32_t opcode = ast->attr;
10219
10220
1.22M
  znode left_node, right_node;
10221
10222
1.22M
  zend_compile_expr(&left_node, left_ast);
10223
1.22M
  zend_compile_expr(&right_node, right_ast);
10224
10225
1.22M
  if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
10226
118k
    if (zend_try_ct_eval_binary_op(&result->u.constant, opcode,
10227
118k
        &left_node.u.constant, &right_node.u.constant)
10228
118k
    ) {
10229
104k
      result->op_type = IS_CONST;
10230
104k
      zval_ptr_dtor(&left_node.u.constant);
10231
104k
      zval_ptr_dtor(&right_node.u.constant);
10232
104k
      return;
10233
104k
    }
10234
118k
  }
10235
10236
1.11M
  do {
10237
1.11M
    if (opcode == ZEND_IS_IDENTICAL || opcode == ZEND_IS_NOT_IDENTICAL) {
10238
      /* 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) */
10239
5.21k
      if (left_node.op_type == IS_CONST) {
10240
1.09k
        if (Z_TYPE(left_node.u.constant) <= IS_TRUE && Z_TYPE(left_node.u.constant) >= IS_NULL) {
10241
410
          zend_op *opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &right_node, NULL);
10242
410
          opline->extended_value =
10243
410
            (opcode == ZEND_IS_IDENTICAL) ?
10244
320
              (1 << Z_TYPE(left_node.u.constant)) :
10245
410
              (MAY_BE_ANY - (1 << Z_TYPE(left_node.u.constant)));
10246
410
          return;
10247
410
        }
10248
4.11k
      } else if (right_node.op_type == IS_CONST) {
10249
2.02k
        if (Z_TYPE(right_node.u.constant) <= IS_TRUE && Z_TYPE(right_node.u.constant) >= IS_NULL) {
10250
609
          zend_op *opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &left_node, NULL);
10251
609
          opline->extended_value =
10252
609
            (opcode == ZEND_IS_IDENTICAL) ?
10253
404
              (1 << Z_TYPE(right_node.u.constant)) :
10254
609
              (MAY_BE_ANY - (1 << Z_TYPE(right_node.u.constant)));
10255
609
          return;
10256
609
        }
10257
2.02k
      }
10258
1.11M
    } else if (opcode == ZEND_CONCAT) {
10259
      /* convert constant operands to strings at compile-time */
10260
72.2k
      if (left_node.op_type == IS_CONST) {
10261
14.5k
        if (Z_TYPE(left_node.u.constant) == IS_ARRAY) {
10262
215
          zend_emit_op_tmp(&left_node, ZEND_CAST, &left_node, NULL)->extended_value = IS_STRING;
10263
14.3k
        } else {
10264
14.3k
          convert_to_string(&left_node.u.constant);
10265
14.3k
        }
10266
14.5k
      }
10267
72.2k
      if (right_node.op_type == IS_CONST) {
10268
24.4k
        if (Z_TYPE(right_node.u.constant) == IS_ARRAY) {
10269
449
          zend_emit_op_tmp(&right_node, ZEND_CAST, &right_node, NULL)->extended_value = IS_STRING;
10270
23.9k
        } else {
10271
23.9k
          convert_to_string(&right_node.u.constant);
10272
23.9k
        }
10273
24.4k
      }
10274
72.2k
      if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
10275
0
        opcode = ZEND_FAST_CONCAT;
10276
0
      }
10277
72.2k
    }
10278
1.11M
    zend_emit_op_tmp(result, opcode, &left_node, &right_node);
10279
1.11M
  } while (0);
10280
1.11M
}
10281
/* }}} */
10282
10283
/* We do not use zend_compile_binary_op for this because we want to retain the left-to-right
10284
 * evaluation order. */
10285
static void zend_compile_greater(znode *result, zend_ast *ast) /* {{{ */
10286
303k
{
10287
303k
  zend_ast *left_ast = ast->child[0];
10288
303k
  zend_ast *right_ast = ast->child[1];
10289
303k
  znode left_node, right_node;
10290
10291
303k
  ZEND_ASSERT(ast->kind == ZEND_AST_GREATER || ast->kind == ZEND_AST_GREATER_EQUAL);
10292
10293
303k
  zend_compile_expr(&left_node, left_ast);
10294
303k
  zend_compile_expr(&right_node, right_ast);
10295
10296
303k
  if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
10297
8.74k
    result->op_type = IS_CONST;
10298
8.74k
    zend_ct_eval_greater(&result->u.constant, ast->kind,
10299
8.74k
      &left_node.u.constant, &right_node.u.constant);
10300
8.74k
    zval_ptr_dtor(&left_node.u.constant);
10301
8.74k
    zval_ptr_dtor(&right_node.u.constant);
10302
8.74k
    return;
10303
8.74k
  }
10304
10305
294k
  zend_emit_op_tmp(result,
10306
294k
    ast->kind == ZEND_AST_GREATER ? ZEND_IS_SMALLER : ZEND_IS_SMALLER_OR_EQUAL,
10307
294k
    &right_node, &left_node);
10308
294k
}
10309
/* }}} */
10310
10311
static void zend_compile_unary_op(znode *result, zend_ast *ast) /* {{{ */
10312
646k
{
10313
646k
  zend_ast *expr_ast = ast->child[0];
10314
646k
  uint32_t opcode = ast->attr;
10315
10316
646k
  znode expr_node;
10317
646k
  zend_compile_expr(&expr_node, expr_ast);
10318
10319
646k
  if (expr_node.op_type == IS_CONST
10320
39.7k
      && zend_try_ct_eval_unary_op(&result->u.constant, opcode, &expr_node.u.constant)) {
10321
38.4k
    result->op_type = IS_CONST;
10322
38.4k
    zval_ptr_dtor(&expr_node.u.constant);
10323
38.4k
    return;
10324
38.4k
  }
10325
10326
607k
  zend_emit_op_tmp(result, opcode, &expr_node, NULL);
10327
607k
}
10328
/* }}} */
10329
10330
static void zend_compile_unary_pm(znode *result, zend_ast *ast) /* {{{ */
10331
52.5k
{
10332
52.5k
  zend_ast *expr_ast = ast->child[0];
10333
52.5k
  znode expr_node, right_node;
10334
10335
52.5k
  ZEND_ASSERT(ast->kind == ZEND_AST_UNARY_PLUS || ast->kind == ZEND_AST_UNARY_MINUS);
10336
10337
52.5k
  zend_compile_expr(&expr_node, expr_ast);
10338
10339
52.5k
  if (expr_node.op_type == IS_CONST
10340
28.3k
    && zend_try_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant)) {
10341
26.6k
    result->op_type = IS_CONST;
10342
26.6k
    zval_ptr_dtor(&expr_node.u.constant);
10343
26.6k
    return;
10344
26.6k
  }
10345
10346
25.8k
  right_node.op_type = IS_CONST;
10347
25.8k
  ZVAL_LONG(&right_node.u.constant, (ast->kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
10348
25.8k
  zend_emit_op_tmp(result, ZEND_MUL, &expr_node, &right_node);
10349
25.8k
}
10350
/* }}} */
10351
10352
static void zend_compile_short_circuiting(znode *result, zend_ast *ast) /* {{{ */
10353
20.3k
{
10354
20.3k
  zend_ast *left_ast = ast->child[0];
10355
20.3k
  zend_ast *right_ast = ast->child[1];
10356
10357
20.3k
  znode left_node, right_node;
10358
20.3k
  zend_op *opline_jmpz, *opline_bool;
10359
20.3k
  uint32_t opnum_jmpz;
10360
10361
20.3k
  ZEND_ASSERT(ast->kind == ZEND_AST_AND || ast->kind == ZEND_AST_OR);
10362
10363
20.3k
  zend_compile_expr(&left_node, left_ast);
10364
10365
20.3k
  if (left_node.op_type == IS_CONST) {
10366
3.30k
    if ((ast->kind == ZEND_AST_AND && !zend_is_true(&left_node.u.constant))
10367
2.02k
     || (ast->kind == ZEND_AST_OR && zend_is_true(&left_node.u.constant))) {
10368
1.99k
      result->op_type = IS_CONST;
10369
1.99k
      ZVAL_BOOL(&result->u.constant, zend_is_true(&left_node.u.constant));
10370
1.99k
    } else {
10371
1.31k
      zend_compile_expr(&right_node, right_ast);
10372
10373
1.31k
      if (right_node.op_type == IS_CONST) {
10374
682
        result->op_type = IS_CONST;
10375
682
        ZVAL_BOOL(&result->u.constant, zend_is_true(&right_node.u.constant));
10376
10377
682
        zval_ptr_dtor(&right_node.u.constant);
10378
682
      } else {
10379
631
        zend_emit_op_tmp(result, ZEND_BOOL, &right_node, NULL);
10380
631
      }
10381
1.31k
    }
10382
10383
3.30k
    zval_ptr_dtor(&left_node.u.constant);
10384
3.30k
    return;
10385
3.30k
  }
10386
10387
17.0k
  opnum_jmpz = get_next_op_number();
10388
17.0k
  opline_jmpz = zend_emit_op(NULL, ast->kind == ZEND_AST_AND ? ZEND_JMPZ_EX : ZEND_JMPNZ_EX,
10389
17.0k
    &left_node, NULL);
10390
10391
17.0k
  if (left_node.op_type == IS_TMP_VAR) {
10392
13.9k
    SET_NODE(opline_jmpz->result, &left_node);
10393
13.9k
    GET_NODE(result, opline_jmpz->result);
10394
13.9k
  } else {
10395
3.14k
    zend_make_tmp_result(result, opline_jmpz);
10396
3.14k
  }
10397
10398
17.0k
  zend_compile_expr(&right_node, right_ast);
10399
10400
17.0k
  opline_bool = zend_emit_op(NULL, ZEND_BOOL, &right_node, NULL);
10401
17.0k
  SET_NODE(opline_bool->result, result);
10402
10403
17.0k
  zend_update_jump_target_to_next(opnum_jmpz);
10404
17.0k
}
10405
/* }}} */
10406
10407
static void zend_compile_post_incdec(znode *result, zend_ast *ast) /* {{{ */
10408
9.79k
{
10409
9.79k
  zend_ast *var_ast = ast->child[0];
10410
9.79k
  ZEND_ASSERT(ast->kind == ZEND_AST_POST_INC || ast->kind == ZEND_AST_POST_DEC);
10411
10412
9.79k
  zend_ensure_writable_variable(var_ast);
10413
10414
9.79k
  if (var_ast->kind == ZEND_AST_PROP || var_ast->kind == ZEND_AST_NULLSAFE_PROP) {
10415
862
    zend_op *opline = zend_compile_prop(NULL, var_ast, BP_VAR_RW, false);
10416
862
    opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ;
10417
862
    zend_make_tmp_result(result, opline);
10418
8.93k
  } else if (var_ast->kind == ZEND_AST_STATIC_PROP) {
10419
751
    zend_op *opline = zend_compile_static_prop(NULL, var_ast, BP_VAR_RW, false, false);
10420
751
    opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_STATIC_PROP : ZEND_POST_DEC_STATIC_PROP;
10421
751
    zend_make_tmp_result(result, opline);
10422
8.18k
  } else {
10423
8.18k
    znode var_node;
10424
8.18k
    zend_op *opline = zend_compile_var(&var_node, var_ast, BP_VAR_RW, false);
10425
8.18k
    if (opline && opline->opcode == ZEND_FETCH_DIM_RW) {
10426
247
      opline->extended_value = ZEND_FETCH_DIM_INCDEC;
10427
247
    }
10428
8.18k
    zend_emit_op_tmp(result, ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC : ZEND_POST_DEC,
10429
8.18k
      &var_node, NULL);
10430
8.18k
  }
10431
9.79k
}
10432
/* }}} */
10433
10434
static void zend_compile_pre_incdec(znode *result, zend_ast *ast) /* {{{ */
10435
4.73k
{
10436
4.73k
  zend_ast *var_ast = ast->child[0];
10437
4.73k
  ZEND_ASSERT(ast->kind == ZEND_AST_PRE_INC || ast->kind == ZEND_AST_PRE_DEC);
10438
10439
4.73k
  zend_ensure_writable_variable(var_ast);
10440
10441
4.73k
  if (var_ast->kind == ZEND_AST_PROP || var_ast->kind == ZEND_AST_NULLSAFE_PROP) {
10442
1.04k
    zend_op *opline = zend_compile_prop(result, var_ast, BP_VAR_RW, false);
10443
1.04k
    opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ;
10444
1.04k
    opline->result_type = IS_TMP_VAR;
10445
1.04k
    result->op_type = IS_TMP_VAR;
10446
3.69k
  } else if (var_ast->kind == ZEND_AST_STATIC_PROP) {
10447
260
    zend_op *opline = zend_compile_static_prop(result, var_ast, BP_VAR_RW, false, false);
10448
260
    opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_STATIC_PROP : ZEND_PRE_DEC_STATIC_PROP;
10449
260
    opline->result_type = IS_TMP_VAR;
10450
260
    result->op_type = IS_TMP_VAR;
10451
3.43k
  } else {
10452
3.43k
    znode var_node;
10453
3.43k
    zend_op *opline = zend_compile_var(&var_node, var_ast, BP_VAR_RW, false);
10454
3.43k
    if (opline && opline->opcode == ZEND_FETCH_DIM_RW) {
10455
285
      opline->extended_value = ZEND_FETCH_DIM_INCDEC;
10456
285
    }
10457
3.43k
    zend_emit_op_tmp(result, ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC : ZEND_PRE_DEC,
10458
3.43k
      &var_node, NULL);
10459
3.43k
  }
10460
4.73k
}
10461
/* }}} */
10462
10463
static void zend_compile_cast(znode *result, zend_ast *ast) /* {{{ */
10464
4.53k
{
10465
4.53k
  zend_ast *expr_ast = ast->child[0];
10466
4.53k
  znode expr_node;
10467
4.53k
  zend_op *opline;
10468
10469
4.53k
  zend_compile_expr(&expr_node, expr_ast);
10470
10471
4.53k
  if (ast->attr == _IS_BOOL) {
10472
271
    opline = zend_emit_op_tmp(result, ZEND_BOOL, &expr_node, NULL);
10473
4.26k
  } else if (ast->attr == IS_NULL) {
10474
13
    zend_error(E_COMPILE_ERROR, "The (unset) cast is no longer supported");
10475
4.25k
  } else {
10476
4.25k
    opline = zend_emit_op_tmp(result, ZEND_CAST, &expr_node, NULL);
10477
4.25k
    opline->extended_value = ast->attr;
10478
4.25k
  }
10479
4.53k
}
10480
/* }}} */
10481
10482
static void zend_compile_shorthand_conditional(znode *result, zend_ast *ast) /* {{{ */
10483
5.35k
{
10484
5.35k
  zend_ast *cond_ast = ast->child[0];
10485
5.35k
  zend_ast *false_ast = ast->child[2];
10486
10487
5.35k
  znode cond_node, false_node;
10488
5.35k
  zend_op *opline_qm_assign;
10489
5.35k
  uint32_t opnum_jmp_set;
10490
10491
5.35k
  ZEND_ASSERT(ast->child[1] == NULL);
10492
10493
5.35k
  zend_compile_expr(&cond_node, cond_ast);
10494
10495
5.35k
  opnum_jmp_set = get_next_op_number();
10496
5.35k
  zend_emit_op_tmp(result, ZEND_JMP_SET, &cond_node, NULL);
10497
10498
5.35k
  zend_compile_expr(&false_node, false_ast);
10499
10500
5.35k
  opline_qm_assign = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &false_node, NULL);
10501
5.35k
  SET_NODE(opline_qm_assign->result, result);
10502
10503
5.35k
  zend_update_jump_target_to_next(opnum_jmp_set);
10504
5.35k
}
10505
/* }}} */
10506
10507
static void zend_compile_conditional(znode *result, zend_ast *ast) /* {{{ */
10508
12.3k
{
10509
12.3k
  zend_ast *cond_ast = ast->child[0];
10510
12.3k
  zend_ast *true_ast = ast->child[1];
10511
12.3k
  zend_ast *false_ast = ast->child[2];
10512
10513
12.3k
  znode cond_node, true_node, false_node;
10514
12.3k
  zend_op *opline_qm_assign2;
10515
12.3k
  uint32_t opnum_jmpz, opnum_jmp;
10516
10517
12.3k
  if (cond_ast->kind == ZEND_AST_CONDITIONAL
10518
2.25k
      && cond_ast->attr != ZEND_PARENTHESIZED_CONDITIONAL) {
10519
1.32k
    if (cond_ast->child[1]) {
10520
35
      if (true_ast) {
10521
18
        zend_error(E_COMPILE_ERROR,
10522
18
          "Unparenthesized `a ? b : c ? d : e` is not supported. "
10523
18
          "Use either `(a ? b : c) ? d : e` or `a ? b : (c ? d : e)`");
10524
18
      } else {
10525
17
        zend_error(E_COMPILE_ERROR,
10526
17
          "Unparenthesized `a ? b : c ?: d` is not supported. "
10527
17
          "Use either `(a ? b : c) ?: d` or `a ? b : (c ?: d)`");
10528
17
      }
10529
1.29k
    } else {
10530
1.29k
      if (true_ast) {
10531
11
        zend_error(E_COMPILE_ERROR,
10532
11
          "Unparenthesized `a ?: b ? c : d` is not supported. "
10533
11
          "Use either `(a ?: b) ? c : d` or `a ?: (b ? c : d)`");
10534
1.28k
      } else {
10535
        /* This case is harmless:  (a ?: b) ?: c always produces the same result
10536
         * as a ?: (b ?: c). */
10537
1.28k
      }
10538
1.29k
    }
10539
1.32k
  }
10540
10541
12.3k
  if (!true_ast) {
10542
5.35k
    zend_compile_shorthand_conditional(result, ast);
10543
5.35k
    return;
10544
5.35k
  }
10545
10546
7.00k
  zend_compile_expr(&cond_node, cond_ast);
10547
10548
7.00k
  opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
10549
10550
7.00k
  zend_compile_expr(&true_node, true_ast);
10551
10552
7.00k
  zend_emit_op_tmp(result, ZEND_QM_ASSIGN, &true_node, NULL);
10553
10554
7.00k
  opnum_jmp = zend_emit_jump(0);
10555
10556
7.00k
  zend_update_jump_target_to_next(opnum_jmpz);
10557
10558
7.00k
  zend_compile_expr(&false_node, false_ast);
10559
10560
7.00k
  opline_qm_assign2 = zend_emit_op(NULL, ZEND_QM_ASSIGN, &false_node, NULL);
10561
7.00k
  SET_NODE(opline_qm_assign2->result, result);
10562
10563
7.00k
  zend_update_jump_target_to_next(opnum_jmp);
10564
7.00k
}
10565
/* }}} */
10566
10567
static void zend_compile_coalesce(znode *result, zend_ast *ast) /* {{{ */
10568
838k
{
10569
838k
  zend_ast *expr_ast = ast->child[0];
10570
838k
  zend_ast *default_ast = ast->child[1];
10571
10572
838k
  znode expr_node, default_node;
10573
838k
  zend_op *opline;
10574
838k
  uint32_t opnum;
10575
10576
838k
  zend_compile_var(&expr_node, expr_ast, BP_VAR_IS, false);
10577
10578
838k
  opnum = get_next_op_number();
10579
838k
  zend_emit_op_tmp(result, ZEND_COALESCE, &expr_node, NULL);
10580
10581
838k
  zend_compile_expr(&default_node, default_ast);
10582
10583
838k
  opline = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &default_node, NULL);
10584
838k
  SET_NODE(opline->result, result);
10585
10586
838k
  opline = &CG(active_op_array)->opcodes[opnum];
10587
838k
  opline->op2.opline_num = get_next_op_number();
10588
838k
}
10589
/* }}} */
10590
10591
67.2k
static void znode_dtor(zval *zv) {
10592
67.2k
  znode *node = Z_PTR_P(zv);
10593
67.2k
  if (node->op_type == IS_CONST) {
10594
6.37k
    zval_ptr_dtor_nogc(&node->u.constant);
10595
6.37k
  }
10596
67.2k
  efree(node);
10597
67.2k
}
10598
10599
static void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */
10600
17.2k
{
10601
17.2k
  zend_ast *var_ast = ast->child[0];
10602
17.2k
  zend_ast *default_ast = ast->child[1];
10603
10604
17.2k
  znode var_node_is, var_node_w, default_node, assign_node, *node;
10605
17.2k
  zend_op *opline;
10606
17.2k
  uint32_t coalesce_opnum;
10607
17.2k
  bool need_frees = false;
10608
10609
  /* Remember expressions compiled during the initial BP_VAR_IS lookup,
10610
   * to avoid double-evaluation when we compile again with BP_VAR_W. */
10611
17.2k
  HashTable *orig_memoized_exprs = CG(memoized_exprs);
10612
17.2k
  const zend_memoize_mode orig_memoize_mode = CG(memoize_mode);
10613
10614
17.2k
  zend_ensure_writable_variable(var_ast);
10615
17.2k
  if (is_this_fetch(var_ast)) {
10616
7
    zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
10617
7
  }
10618
10619
17.2k
  ALLOC_HASHTABLE(CG(memoized_exprs));
10620
17.2k
  zend_hash_init(CG(memoized_exprs), 0, NULL, znode_dtor, 0);
10621
10622
17.2k
  CG(memoize_mode) = ZEND_MEMOIZE_COMPILE;
10623
17.2k
  zend_compile_var(&var_node_is, var_ast, BP_VAR_IS, false);
10624
10625
17.2k
  coalesce_opnum = get_next_op_number();
10626
17.2k
  zend_emit_op_tmp(result, ZEND_COALESCE, &var_node_is, NULL);
10627
10628
17.2k
  CG(memoize_mode) = ZEND_MEMOIZE_NONE;
10629
17.2k
  if (var_ast->kind == ZEND_AST_DIM) {
10630
13.2k
    zend_compile_expr_with_potential_assign_to_self(&default_node, default_ast, var_ast);
10631
13.2k
  } else {
10632
3.96k
    zend_compile_expr(&default_node, default_ast);
10633
3.96k
  }
10634
10635
17.2k
  CG(memoize_mode) = ZEND_MEMOIZE_FETCH;
10636
17.2k
  zend_compile_var(&var_node_w, var_ast, BP_VAR_W, false);
10637
10638
  /* Reproduce some of the zend_compile_assign() opcode fixup logic here. */
10639
17.2k
  opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
10640
  /* Treat $GLOBALS['x'] assignment like assignment to variable. */
10641
17.2k
  zend_ast_kind kind = is_global_var_fetch(var_ast) ? ZEND_AST_VAR : var_ast->kind;
10642
17.2k
  switch (kind) {
10643
2.18k
    case ZEND_AST_VAR:
10644
2.18k
      zend_emit_op_tmp(&assign_node, ZEND_ASSIGN, &var_node_w, &default_node);
10645
2.18k
      break;
10646
1.21k
    case ZEND_AST_STATIC_PROP:
10647
1.21k
      opline->opcode = ZEND_ASSIGN_STATIC_PROP;
10648
1.21k
      opline->result_type = IS_TMP_VAR;
10649
1.21k
      var_node_w.op_type = IS_TMP_VAR;
10650
1.21k
      zend_emit_op_data(&default_node);
10651
1.21k
      assign_node = var_node_w;
10652
1.21k
      break;
10653
12.5k
    case ZEND_AST_DIM:
10654
12.5k
      opline->opcode = ZEND_ASSIGN_DIM;
10655
12.5k
      opline->result_type = IS_TMP_VAR;
10656
12.5k
      var_node_w.op_type = IS_TMP_VAR;
10657
12.5k
      zend_emit_op_data(&default_node);
10658
12.5k
      assign_node = var_node_w;
10659
12.5k
      break;
10660
916
    case ZEND_AST_PROP:
10661
916
    case ZEND_AST_NULLSAFE_PROP:
10662
916
      opline->opcode = ZEND_ASSIGN_OBJ;
10663
916
      opline->result_type = IS_TMP_VAR;
10664
916
      var_node_w.op_type = IS_TMP_VAR;
10665
916
      zend_emit_op_data(&default_node);
10666
916
      assign_node = var_node_w;
10667
916
      break;
10668
0
    EMPTY_SWITCH_DEFAULT_CASE();
10669
17.2k
  }
10670
10671
16.8k
  opline = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &assign_node, NULL);
10672
16.8k
  SET_NODE(opline->result, result);
10673
10674
51.3k
  ZEND_HASH_FOREACH_PTR(CG(memoized_exprs), node) {
10675
51.3k
    if (node->op_type == IS_TMP_VAR || node->op_type == IS_VAR) {
10676
12.7k
      need_frees = true;
10677
12.7k
      break;
10678
12.7k
    }
10679
51.3k
  } ZEND_HASH_FOREACH_END();
10680
10681
  /* Free DUPed expressions if there are any */
10682
16.8k
  if (need_frees) {
10683
12.7k
    uint32_t jump_opnum = zend_emit_jump(0);
10684
12.7k
    zend_update_jump_target_to_next(coalesce_opnum);
10685
139k
    ZEND_HASH_FOREACH_PTR(CG(memoized_exprs), node) {
10686
139k
      if (node->op_type == IS_TMP_VAR || node->op_type == IS_VAR) {
10687
59.6k
        zend_emit_op(NULL, ZEND_FREE, node, NULL);
10688
59.6k
      }
10689
139k
    } ZEND_HASH_FOREACH_END();
10690
12.7k
    zend_update_jump_target_to_next(jump_opnum);
10691
12.7k
  } else {
10692
4.14k
    zend_update_jump_target_to_next(coalesce_opnum);
10693
4.14k
  }
10694
10695
16.8k
  zend_hash_destroy(CG(memoized_exprs));
10696
16.8k
  FREE_HASHTABLE(CG(memoized_exprs));
10697
16.8k
  CG(memoized_exprs) = orig_memoized_exprs;
10698
16.8k
  CG(memoize_mode) = orig_memoize_mode;
10699
16.8k
}
10700
/* }}} */
10701
10702
static void zend_compile_print(znode *result, zend_ast *ast) /* {{{ */
10703
5.03k
{
10704
5.03k
  zend_op *opline;
10705
5.03k
  zend_ast *expr_ast = ast->child[0];
10706
10707
5.03k
  znode expr_node;
10708
5.03k
  zend_compile_expr(&expr_node, expr_ast);
10709
10710
5.03k
  opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL);
10711
5.03k
  opline->extended_value = 1;
10712
10713
5.03k
  result->op_type = IS_CONST;
10714
5.03k
  ZVAL_LONG(&result->u.constant, 1);
10715
5.03k
}
10716
/* }}} */
10717
10718
static void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */
10719
11.7k
{
10720
11.7k
  zend_ast *value_ast = ast->child[0];
10721
11.7k
  zend_ast *key_ast = ast->child[1];
10722
10723
11.7k
  znode value_node, key_node;
10724
11.7k
  znode *value_node_ptr = NULL, *key_node_ptr = NULL;
10725
11.7k
  zend_op *opline;
10726
11.7k
  bool returns_by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
10727
10728
11.7k
  zend_mark_function_as_generator();
10729
10730
11.7k
  if (key_ast) {
10731
671
    zend_compile_expr(&key_node, key_ast);
10732
671
    key_node_ptr = &key_node;
10733
671
  }
10734
10735
11.7k
  if (value_ast) {
10736
7.30k
    if (returns_by_ref && zend_is_variable(value_ast)) {
10737
150
      zend_assert_not_short_circuited(value_ast);
10738
150
      zend_compile_var(&value_node, value_ast, BP_VAR_W, true);
10739
7.15k
    } else {
10740
7.15k
      zend_compile_expr(&value_node, value_ast);
10741
7.15k
    }
10742
7.30k
    value_node_ptr = &value_node;
10743
7.30k
  }
10744
10745
11.7k
  opline = zend_emit_op(result, ZEND_YIELD, value_node_ptr, key_node_ptr);
10746
10747
11.7k
  if (value_ast && returns_by_ref && zend_is_call(value_ast)) {
10748
520
    opline->extended_value = ZEND_RETURNS_FUNCTION;
10749
520
  }
10750
11.7k
}
10751
/* }}} */
10752
10753
static void zend_compile_yield_from(znode *result, zend_ast *ast) /* {{{ */
10754
1.35k
{
10755
1.35k
  zend_ast *expr_ast = ast->child[0];
10756
1.35k
  znode expr_node;
10757
10758
1.35k
  zend_mark_function_as_generator();
10759
10760
1.35k
  if (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
10761
9
    zend_error_noreturn(E_COMPILE_ERROR,
10762
9
      "Cannot use \"yield from\" inside a by-reference generator");
10763
9
  }
10764
10765
1.34k
  zend_compile_expr(&expr_node, expr_ast);
10766
1.34k
  zend_emit_op_tmp(result, ZEND_YIELD_FROM, &expr_node, NULL);
10767
1.34k
}
10768
/* }}} */
10769
10770
static void zend_compile_instanceof(znode *result, zend_ast *ast) /* {{{ */
10771
722
{
10772
722
  zend_ast *obj_ast = ast->child[0];
10773
722
  zend_ast *class_ast = ast->child[1];
10774
10775
722
  znode obj_node, class_node;
10776
722
  zend_op *opline;
10777
10778
722
  zend_compile_expr(&obj_node, obj_ast);
10779
722
  if (obj_node.op_type == IS_CONST) {
10780
93
    zend_do_free(&obj_node);
10781
93
    result->op_type = IS_CONST;
10782
93
    ZVAL_FALSE(&result->u.constant);
10783
93
    return;
10784
93
  }
10785
10786
629
  zend_compile_class_ref(&class_node, class_ast,
10787
629
    ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_EXCEPTION | ZEND_FETCH_CLASS_SILENT);
10788
10789
629
  opline = zend_emit_op_tmp(result, ZEND_INSTANCEOF, &obj_node, NULL);
10790
10791
629
  if (class_node.op_type == IS_CONST) {
10792
367
    opline->op2_type = IS_CONST;
10793
367
    opline->op2.constant = zend_add_class_name_literal(
10794
367
      Z_STR(class_node.u.constant));
10795
367
    opline->extended_value = zend_alloc_cache_slot();
10796
367
  } else {
10797
262
    SET_NODE(opline->op2, &class_node);
10798
262
  }
10799
629
}
10800
/* }}} */
10801
10802
static void zend_compile_include_or_eval(znode *result, zend_ast *ast) /* {{{ */
10803
8.12k
{
10804
8.12k
  zend_ast *expr_ast = ast->child[0];
10805
8.12k
  znode expr_node;
10806
8.12k
  zend_op *opline;
10807
10808
8.12k
  zend_do_extended_fcall_begin();
10809
8.12k
  zend_compile_expr(&expr_node, expr_ast);
10810
10811
8.12k
  opline = zend_emit_op(result, ZEND_INCLUDE_OR_EVAL, &expr_node, NULL);
10812
8.12k
  opline->extended_value = ast->attr;
10813
10814
8.12k
  zend_do_extended_fcall_end();
10815
8.12k
}
10816
/* }}} */
10817
10818
static void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
10819
10.2k
{
10820
10.2k
  zend_ast *var_ast = ast->child[0];
10821
10822
10.2k
  znode var_node;
10823
10.2k
  zend_op *opline = NULL;
10824
10825
10.2k
  ZEND_ASSERT(ast->kind == ZEND_AST_ISSET || ast->kind == ZEND_AST_EMPTY);
10826
10827
10.2k
  if (!zend_is_variable(var_ast)) {
10828
198
    if (ast->kind == ZEND_AST_EMPTY) {
10829
      /* empty(expr) can be transformed to !expr */
10830
129
      zend_ast *not_ast = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, var_ast);
10831
129
      zend_compile_expr(result, not_ast);
10832
129
      return;
10833
129
    } else {
10834
69
      zend_error_noreturn(E_COMPILE_ERROR,
10835
69
        "Cannot use isset() on the result of an expression "
10836
69
        "(you can use \"null !== expression\" instead)");
10837
69
    }
10838
198
  }
10839
10840
10.0k
  if (is_globals_fetch(var_ast)) {
10841
434
    result->op_type = IS_CONST;
10842
434
    ZVAL_BOOL(&result->u.constant, ast->kind == ZEND_AST_ISSET);
10843
434
    return;
10844
434
  }
10845
10846
9.63k
  if (is_global_var_fetch(var_ast)) {
10847
370
    if (!var_ast->child[1]) {
10848
8
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
10849
8
    }
10850
10851
362
    zend_compile_expr(&var_node, var_ast->child[1]);
10852
362
    if (var_node.op_type == IS_CONST) {
10853
331
      convert_to_string(&var_node.u.constant);
10854
331
    }
10855
10856
362
    opline = zend_emit_op_tmp(result, ZEND_ISSET_ISEMPTY_VAR, &var_node, NULL);
10857
362
    opline->extended_value =
10858
362
      ZEND_FETCH_GLOBAL | (ast->kind == ZEND_AST_EMPTY ? ZEND_ISEMPTY : 0);
10859
362
    return;
10860
370
  }
10861
10862
9.26k
  zend_short_circuiting_mark_inner(var_ast);
10863
9.26k
  switch (var_ast->kind) {
10864
4.69k
    case ZEND_AST_VAR:
10865
4.69k
      if (is_this_fetch(var_ast)) {
10866
992
        opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_THIS, NULL, NULL);
10867
992
        CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
10868
3.70k
      } else if (zend_try_compile_cv(&var_node, var_ast, BP_VAR_IS) == SUCCESS) {
10869
3.24k
        opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_CV, &var_node, NULL);
10870
3.24k
      } else {
10871
458
        opline = zend_compile_simple_var_no_cv(result, var_ast, BP_VAR_IS, false);
10872
458
        opline->opcode = ZEND_ISSET_ISEMPTY_VAR;
10873
458
      }
10874
4.69k
      break;
10875
2.95k
    case ZEND_AST_DIM:
10876
2.95k
      opline = zend_compile_dim(result, var_ast, BP_VAR_IS, /* by_ref */ false);
10877
2.95k
      opline->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ;
10878
2.95k
      break;
10879
1.01k
    case ZEND_AST_PROP:
10880
1.26k
    case ZEND_AST_NULLSAFE_PROP:
10881
1.26k
      opline = zend_compile_prop(result, var_ast, BP_VAR_IS, false);
10882
1.26k
      opline->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ;
10883
1.26k
      break;
10884
340
    case ZEND_AST_STATIC_PROP:
10885
340
      opline = zend_compile_static_prop(result, var_ast, BP_VAR_IS, false, false);
10886
340
      opline->opcode = ZEND_ISSET_ISEMPTY_STATIC_PROP;
10887
340
      break;
10888
9.26k
    EMPTY_SWITCH_DEFAULT_CASE()
10889
9.26k
  }
10890
10891
9.24k
  result->op_type = opline->result_type = IS_TMP_VAR;
10892
9.24k
  if (!(ast->kind == ZEND_AST_ISSET)) {
10893
1.22k
    opline->extended_value |= ZEND_ISEMPTY;
10894
1.22k
  }
10895
9.24k
}
10896
/* }}} */
10897
10898
static void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
10899
7.69M
{
10900
7.69M
  zend_ast *expr_ast = ast->child[0];
10901
7.69M
  znode silence_node;
10902
10903
7.69M
  zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL);
10904
10905
7.69M
  if (expr_ast->kind == ZEND_AST_VAR) {
10906
    /* For @$var we need to force a FETCH instruction, otherwise the CV access will
10907
     * happen outside the silenced section. */
10908
241k
    zend_compile_simple_var_no_cv(result, expr_ast, BP_VAR_R, false );
10909
7.44M
  } else {
10910
7.44M
    zend_compile_expr(result, expr_ast);
10911
7.44M
  }
10912
10913
7.69M
  zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL);
10914
7.69M
}
10915
/* }}} */
10916
10917
static void zend_compile_shell_exec(znode *result, zend_ast *ast) /* {{{ */
10918
52.9k
{
10919
52.9k
  zend_ast *expr_ast = ast->child[0];
10920
10921
52.9k
  zval fn_name;
10922
52.9k
  zend_ast *name_ast, *args_ast, *call_ast;
10923
10924
52.9k
  zend_error(E_DEPRECATED, "The backtick (`) operator is deprecated, use shell_exec() instead");
10925
10926
52.9k
  ZVAL_STRING(&fn_name, "shell_exec");
10927
52.9k
  name_ast = zend_ast_create_zval(&fn_name);
10928
52.9k
  args_ast = zend_ast_create_list(1, ZEND_AST_ARG_LIST, expr_ast);
10929
52.9k
  call_ast = zend_ast_create(ZEND_AST_CALL, name_ast, args_ast);
10930
10931
52.9k
  zend_compile_expr(result, call_ast);
10932
10933
52.9k
  zval_ptr_dtor(&fn_name);
10934
52.9k
}
10935
/* }}} */
10936
10937
static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
10938
95.3k
{
10939
95.3k
  zend_ast_list *list = zend_ast_get_list(ast);
10940
95.3k
  zend_op *opline;
10941
95.3k
  uint32_t i, opnum_init = -1;
10942
95.3k
  bool packed = true;
10943
10944
95.3k
  if (zend_try_ct_eval_array(&result->u.constant, ast)) {
10945
57.3k
    result->op_type = IS_CONST;
10946
57.3k
    return;
10947
57.3k
  }
10948
10949
  /* Empty arrays are handled at compile-time */
10950
38.0k
  ZEND_ASSERT(list->children > 0);
10951
10952
198k
  for (i = 0; i < list->children; ++i) {
10953
160k
    zend_ast *elem_ast = list->child[i];
10954
160k
    zend_ast *value_ast, *key_ast;
10955
160k
    bool by_ref;
10956
160k
    znode value_node, key_node, *key_node_ptr = NULL;
10957
10958
160k
    if (elem_ast == NULL) {
10959
0
      zend_error(E_COMPILE_ERROR, "Cannot use empty array elements in arrays");
10960
0
    }
10961
10962
160k
    value_ast = elem_ast->child[0];
10963
10964
160k
    if (elem_ast->kind == ZEND_AST_UNPACK) {
10965
2.39k
      zend_compile_expr(&value_node, value_ast);
10966
2.39k
      if (i == 0) {
10967
1.20k
        opnum_init = get_next_op_number();
10968
1.20k
        opline = zend_emit_op_tmp(result, ZEND_INIT_ARRAY, NULL, NULL);
10969
1.20k
      }
10970
2.39k
      opline = zend_emit_op(NULL, ZEND_ADD_ARRAY_UNPACK, &value_node, NULL);
10971
2.39k
      SET_NODE(opline->result, result);
10972
2.39k
      continue;
10973
2.39k
    }
10974
10975
158k
    key_ast = elem_ast->child[1];
10976
158k
    by_ref = elem_ast->attr;
10977
10978
158k
    if (key_ast) {
10979
9.60k
      zend_compile_expr(&key_node, key_ast);
10980
9.60k
      zend_handle_numeric_op(&key_node);
10981
9.60k
      key_node_ptr = &key_node;
10982
9.60k
    }
10983
10984
158k
    if (by_ref) {
10985
767
      zend_ensure_writable_variable(value_ast);
10986
767
      zend_compile_var(&value_node, value_ast, BP_VAR_W, true);
10987
157k
    } else {
10988
157k
      zend_compile_expr(&value_node, value_ast);
10989
157k
    }
10990
10991
158k
    if (i == 0) {
10992
36.6k
      opnum_init = get_next_op_number();
10993
36.6k
      opline = zend_emit_op_tmp(result, ZEND_INIT_ARRAY, &value_node, key_node_ptr);
10994
36.6k
      opline->extended_value = list->children << ZEND_ARRAY_SIZE_SHIFT;
10995
121k
    } else {
10996
121k
      opline = zend_emit_op(NULL, ZEND_ADD_ARRAY_ELEMENT,
10997
121k
        &value_node, key_node_ptr);
10998
121k
      SET_NODE(opline->result, result);
10999
121k
    }
11000
158k
    opline->extended_value |= by_ref;
11001
11002
158k
    if (key_ast && key_node.op_type == IS_CONST && Z_TYPE(key_node.u.constant) == IS_STRING) {
11003
4.71k
      packed = false;
11004
4.71k
    }
11005
158k
  }
11006
11007
  /* Add a flag to INIT_ARRAY if we know this array cannot be packed */
11008
37.8k
  if (!packed) {
11009
2.27k
    ZEND_ASSERT(opnum_init != (uint32_t)-1);
11010
2.27k
    opline = &CG(active_op_array)->opcodes[opnum_init];
11011
2.27k
    opline->extended_value |= ZEND_ARRAY_NOT_PACKED;
11012
2.27k
  }
11013
37.8k
}
11014
/* }}} */
11015
11016
static void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */
11017
3.92M
{
11018
3.92M
  zend_ast *name_ast = ast->child[0];
11019
11020
3.92M
  zend_op *opline;
11021
11022
3.92M
  bool is_fully_qualified;
11023
3.92M
  zend_string *orig_name = zend_ast_get_str(name_ast);
11024
3.92M
  zend_string *resolved_name = zend_resolve_const_name(orig_name, name_ast->attr, &is_fully_qualified);
11025
11026
3.92M
  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__"))) {
11027
477
    zend_ast *last = CG(ast);
11028
11029
1.03k
    while (last && last->kind == ZEND_AST_STMT_LIST) {
11030
613
      zend_ast_list *list = zend_ast_get_list(last);
11031
613
      if (list->children == 0) {
11032
53
        break;
11033
53
      }
11034
560
      last = list->child[list->children-1];
11035
560
    }
11036
477
    if (last && last->kind == ZEND_AST_HALT_COMPILER) {
11037
103
      result->op_type = IS_CONST;
11038
103
      ZVAL_LONG(&result->u.constant, Z_LVAL_P(zend_ast_get_zval(last->child[0])));
11039
103
      zend_string_release_ex(resolved_name, 0);
11040
103
      return;
11041
103
    }
11042
477
  }
11043
11044
3.92M
  if (zend_try_ct_eval_const(&result->u.constant, resolved_name, is_fully_qualified)) {
11045
35.1k
    result->op_type = IS_CONST;
11046
35.1k
    zend_string_release_ex(resolved_name, 0);
11047
35.1k
    return;
11048
35.1k
  }
11049
11050
3.89M
  opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, NULL);
11051
3.89M
  opline->op2_type = IS_CONST;
11052
11053
3.89M
  if (is_fully_qualified || !FC(current_namespace)) {
11054
202k
    opline->op1.num = 0;
11055
202k
    opline->op2.constant = zend_add_const_name_literal(
11056
202k
      resolved_name, false);
11057
3.69M
  } else {
11058
3.69M
    opline->op1.num = IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE;
11059
3.69M
    opline->op2.constant = zend_add_const_name_literal(
11060
3.69M
      resolved_name, true);
11061
3.69M
  }
11062
3.89M
  opline->extended_value = zend_alloc_cache_slot();
11063
3.89M
}
11064
/* }}} */
11065
11066
static void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
11067
34.2k
{
11068
34.2k
  zend_ast *class_ast;
11069
34.2k
  zend_ast *const_ast;
11070
34.2k
  znode class_node, const_node;
11071
34.2k
  zend_op *opline;
11072
11073
34.2k
  zend_eval_const_expr(&ast->child[0]);
11074
34.2k
  zend_eval_const_expr(&ast->child[1]);
11075
11076
34.2k
  class_ast = ast->child[0];
11077
34.2k
  const_ast = ast->child[1];
11078
11079
34.2k
  if (class_ast->kind == ZEND_AST_ZVAL && const_ast->kind == ZEND_AST_ZVAL) {
11080
12.4k
    zval *const_zv = zend_ast_get_zval(const_ast);
11081
12.4k
    if (Z_TYPE_P(const_zv) == IS_STRING) {
11082
12.2k
      zend_string *const_str = Z_STR_P(const_zv);
11083
12.2k
      zend_string *resolved_name = zend_resolve_class_name_ast(class_ast);
11084
12.2k
      if (zend_try_ct_eval_class_const(&result->u.constant, resolved_name, const_str)) {
11085
221
        result->op_type = IS_CONST;
11086
221
        zend_string_release_ex(resolved_name, 0);
11087
221
        return;
11088
221
      }
11089
12.0k
      zend_string_release_ex(resolved_name, 0);
11090
12.0k
    }
11091
12.4k
  }
11092
11093
34.0k
  zend_compile_class_ref(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
11094
11095
34.0k
  zend_compile_expr(&const_node, const_ast);
11096
11097
34.0k
  opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_CONSTANT, NULL, &const_node);
11098
11099
34.0k
  zend_set_class_name_op1(opline, &class_node);
11100
11101
34.0k
  if (opline->op1_type == IS_CONST || opline->op2_type == IS_CONST) {
11102
33.4k
    opline->extended_value = zend_alloc_cache_slots(2);
11103
33.4k
  }
11104
34.0k
}
11105
/* }}} */
11106
11107
static void zend_compile_class_name(znode *result, zend_ast *ast) /* {{{ */
11108
5.71k
{
11109
5.71k
  zend_ast *class_ast = ast->child[0];
11110
11111
5.71k
  if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast)) {
11112
2.83k
    result->op_type = IS_CONST;
11113
2.83k
    return;
11114
2.83k
  }
11115
11116
2.87k
  if (class_ast->kind == ZEND_AST_ZVAL) {
11117
1.44k
    zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
11118
1.44k
    opline->op1.num = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
11119
1.44k
  } else {
11120
1.43k
    znode expr_node;
11121
1.43k
    zend_compile_expr(&expr_node, class_ast);
11122
1.43k
    if (expr_node.op_type == IS_CONST) {
11123
      /* Unlikely case that happen if class_ast is constant folded.
11124
       * Handle it here, to avoid needing a CONST specialization in the VM. */
11125
11
      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"::class\" on %s",
11126
11
        zend_zval_value_name(&expr_node.u.constant));
11127
11
    }
11128
11129
1.41k
    zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, &expr_node, NULL);
11130
1.41k
  }
11131
2.87k
}
11132
/* }}} */
11133
11134
static zend_op *zend_compile_rope_add_ex(zend_op *opline, znode *result, uint32_t num, znode *elem_node) /* {{{ */
11135
208k
{
11136
208k
  if (num == 0) {
11137
29.1k
    result->op_type = IS_TMP_VAR;
11138
29.1k
    result->u.op.var = -1;
11139
29.1k
    opline->opcode = ZEND_ROPE_INIT;
11140
179k
  } else {
11141
179k
    opline->opcode = ZEND_ROPE_ADD;
11142
179k
    SET_NODE(opline->op1, result);
11143
179k
  }
11144
208k
  SET_NODE(opline->op2, elem_node);
11145
208k
  SET_NODE(opline->result, result);
11146
208k
  opline->extended_value = num;
11147
208k
  return opline;
11148
208k
}
11149
/* }}} */
11150
11151
static zend_op *zend_compile_rope_add(znode *result, uint32_t num, znode *elem_node) /* {{{ */
11152
201k
{
11153
201k
  zend_op *opline = get_next_op();
11154
11155
201k
  if (num == 0) {
11156
15.4k
    result->op_type = IS_TMP_VAR;
11157
15.4k
    result->u.op.var = -1;
11158
15.4k
    opline->opcode = ZEND_ROPE_INIT;
11159
186k
  } else {
11160
186k
    opline->opcode = ZEND_ROPE_ADD;
11161
186k
    SET_NODE(opline->op1, result);
11162
186k
  }
11163
201k
  SET_NODE(opline->op2, elem_node);
11164
201k
  SET_NODE(opline->result, result);
11165
201k
  opline->extended_value = num;
11166
201k
  return opline;
11167
201k
}
11168
/* }}} */
11169
11170
static void zend_compile_rope_finalize(znode *result, uint32_t rope_elements, zend_op *init_opline, zend_op *opline)
11171
44.5k
{
11172
44.5k
  if (rope_elements == 1) {
11173
5.39k
    if (opline->op2_type == IS_CONST) {
11174
426
      GET_NODE(result, opline->op2);
11175
426
      ZVAL_UNDEF(CT_CONSTANT(opline->op2));
11176
426
      SET_UNUSED(opline->op2);
11177
426
      MAKE_NOP(opline);
11178
4.96k
    } else {
11179
4.96k
      opline->opcode = ZEND_CAST;
11180
4.96k
      opline->extended_value = IS_STRING;
11181
4.96k
      opline->op1_type = opline->op2_type;
11182
4.96k
      opline->op1 = opline->op2;
11183
4.96k
      SET_UNUSED(opline->op2);
11184
4.96k
      zend_make_tmp_result(result, opline);
11185
4.96k
    }
11186
39.1k
  } else if (rope_elements == 2) {
11187
9.01k
    opline->opcode = ZEND_FAST_CONCAT;
11188
9.01k
    opline->extended_value = 0;
11189
9.01k
    opline->op1_type = init_opline->op2_type;
11190
9.01k
    opline->op1 = init_opline->op2;
11191
9.01k
    zend_make_tmp_result(result, opline);
11192
9.01k
    MAKE_NOP(init_opline);
11193
30.1k
  } else {
11194
30.1k
    uint32_t var;
11195
11196
30.1k
    init_opline->extended_value = rope_elements;
11197
30.1k
    opline->opcode = ZEND_ROPE_END;
11198
30.1k
    zend_make_tmp_result(result, opline);
11199
30.1k
    var = opline->op1.var = get_temporary_variable();
11200
11201
    /* Allocates the necessary number of zval slots to keep the rope */
11202
30.1k
    uint32_t i = ((rope_elements * sizeof(zend_string*)) + (sizeof(zval) - 1)) / sizeof(zval);
11203
206k
    while (i > 1) {
11204
176k
      get_temporary_variable();
11205
176k
      i--;
11206
176k
    }
11207
11208
    /* Update all the previous opcodes to use the same variable */
11209
513k
    while (opline != init_opline) {
11210
482k
      opline--;
11211
482k
      if (opline->opcode == ZEND_ROPE_ADD &&
11212
331k
          opline->result.var == (uint32_t)-1) {
11213
326k
        opline->op1.var = var;
11214
326k
        opline->result.var = var;
11215
326k
      } else if (opline->opcode == ZEND_ROPE_INIT &&
11216
30.9k
                 opline->result.var == (uint32_t)-1) {
11217
30.1k
        opline->result.var = var;
11218
30.1k
      }
11219
482k
    }
11220
30.1k
  }
11221
44.5k
}
11222
11223
static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
11224
43.7k
{
11225
43.7k
  uint32_t i, j;
11226
43.7k
  uint32_t rope_init_lineno = -1;
11227
43.7k
  zend_op *opline = NULL, *init_opline;
11228
43.7k
  znode elem_node, last_const_node;
11229
43.7k
  zend_ast_list *list = zend_ast_get_list(ast);
11230
43.7k
  uint32_t reserved_op_number = -1;
11231
11232
43.7k
  ZEND_ASSERT(list->children > 0);
11233
11234
43.7k
  j = 0;
11235
43.7k
  last_const_node.op_type = IS_UNUSED;
11236
457k
  for (i = 0; i < list->children; i++) {
11237
414k
    zend_ast *encaps_var = list->child[i];
11238
11239
414k
    if (encaps_var->attr & (ZEND_ENCAPS_VAR_DOLLAR_CURLY|ZEND_ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR)) {
11240
3.61k
      if ((encaps_var->kind == ZEND_AST_VAR || encaps_var->kind == ZEND_AST_DIM) && (encaps_var->attr & ZEND_ENCAPS_VAR_DOLLAR_CURLY)) {
11241
583
        zend_error(E_DEPRECATED, "Using ${var} in strings is deprecated, use {$var} instead");
11242
3.03k
      } else if (encaps_var->kind == ZEND_AST_VAR && (encaps_var->attr & ZEND_ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR)) {
11243
3.03k
        zend_error(E_DEPRECATED, "Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead");
11244
3.03k
      }
11245
3.61k
    }
11246
11247
414k
    zend_compile_expr(&elem_node, encaps_var);
11248
11249
414k
    if (elem_node.op_type == IS_CONST) {
11250
214k
      convert_to_string(&elem_node.u.constant);
11251
11252
214k
      if (Z_STRLEN(elem_node.u.constant) == 0) {
11253
5.76k
        zval_ptr_dtor(&elem_node.u.constant);
11254
208k
      } else if (last_const_node.op_type == IS_CONST) {
11255
0
        concat_function(&last_const_node.u.constant, &last_const_node.u.constant, &elem_node.u.constant);
11256
0
        zval_ptr_dtor(&elem_node.u.constant);
11257
208k
      } else {
11258
208k
        last_const_node.op_type = IS_CONST;
11259
208k
        ZVAL_COPY_VALUE(&last_const_node.u.constant, &elem_node.u.constant);
11260
        /* Reserve place for ZEND_ROPE_ADD instruction */
11261
208k
        reserved_op_number = get_next_op_number();
11262
208k
        opline = get_next_op();
11263
208k
        opline->opcode = ZEND_NOP;
11264
208k
      }
11265
214k
      continue;
11266
214k
    } else {
11267
199k
      if (j == 0) {
11268
43.7k
        if (last_const_node.op_type == IS_CONST) {
11269
29.1k
          rope_init_lineno = reserved_op_number;
11270
29.1k
        } else {
11271
14.5k
          rope_init_lineno = get_next_op_number();
11272
14.5k
        }
11273
43.7k
      }
11274
199k
      if (last_const_node.op_type == IS_CONST) {
11275
176k
        opline = &CG(active_op_array)->opcodes[reserved_op_number];
11276
176k
        zend_compile_rope_add_ex(opline, result, j++, &last_const_node);
11277
176k
        last_const_node.op_type = IS_UNUSED;
11278
176k
      }
11279
199k
      opline = zend_compile_rope_add(result, j++, &elem_node);
11280
199k
    }
11281
414k
  }
11282
11283
43.7k
  if (j == 0) {
11284
0
    result->op_type = IS_CONST;
11285
0
    if (last_const_node.op_type == IS_CONST) {
11286
0
      ZVAL_COPY_VALUE(&result->u.constant, &last_const_node.u.constant);
11287
0
    } else {
11288
0
      ZVAL_EMPTY_STRING(&result->u.constant);
11289
      /* empty string */
11290
0
    }
11291
0
    CG(active_op_array)->last = reserved_op_number - 1;
11292
0
    return;
11293
43.7k
  } else if (last_const_node.op_type == IS_CONST) {
11294
32.0k
    opline = &CG(active_op_array)->opcodes[reserved_op_number];
11295
32.0k
    opline = zend_compile_rope_add_ex(opline, result, j++, &last_const_node);
11296
32.0k
  }
11297
43.7k
  init_opline = CG(active_op_array)->opcodes + rope_init_lineno;
11298
43.7k
  zend_compile_rope_finalize(result, j, init_opline, opline);
11299
43.7k
}
11300
/* }}} */
11301
11302
static void zend_compile_magic_const(znode *result, zend_ast *ast) /* {{{ */
11303
18.6k
{
11304
18.6k
  zend_op *opline;
11305
11306
18.6k
  if (zend_try_ct_eval_magic_const(&result->u.constant, ast)) {
11307
18.5k
    result->op_type = IS_CONST;
11308
18.5k
    return;
11309
18.5k
  }
11310
11311
137
  ZEND_ASSERT(ast->attr == T_CLASS_C &&
11312
137
              CG(active_class_entry) &&
11313
137
              (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != 0);
11314
11315
137
  opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
11316
137
  opline->op1.num = ZEND_FETCH_CLASS_SELF;
11317
137
}
11318
/* }}} */
11319
11320
static bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */
11321
45.3k
{
11322
45.3k
  return kind == ZEND_AST_ZVAL || kind == ZEND_AST_BINARY_OP
11323
40.0k
    || kind == ZEND_AST_GREATER || kind == ZEND_AST_GREATER_EQUAL
11324
39.2k
    || kind == ZEND_AST_AND || kind == ZEND_AST_OR
11325
39.0k
    || kind == ZEND_AST_UNARY_OP
11326
37.5k
    || kind == ZEND_AST_UNARY_PLUS || kind == ZEND_AST_UNARY_MINUS
11327
36.2k
    || kind == ZEND_AST_CAST
11328
35.5k
    || kind == ZEND_AST_CONDITIONAL || kind == ZEND_AST_DIM
11329
33.9k
    || kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM
11330
31.3k
    || kind == ZEND_AST_UNPACK
11331
31.3k
    || kind == ZEND_AST_CONST || kind == ZEND_AST_CLASS_CONST
11332
7.98k
    || kind == ZEND_AST_CLASS_NAME
11333
7.91k
    || kind == ZEND_AST_MAGIC_CONST || kind == ZEND_AST_COALESCE
11334
7.42k
    || kind == ZEND_AST_CONST_ENUM_INIT
11335
4.29k
    || kind == ZEND_AST_NEW || kind == ZEND_AST_ARG_LIST
11336
2.84k
    || kind == ZEND_AST_NAMED_ARG
11337
2.81k
    || kind == ZEND_AST_PROP || kind == ZEND_AST_NULLSAFE_PROP
11338
2.20k
    || kind == ZEND_AST_CLOSURE
11339
1.94k
    || kind == ZEND_AST_CALL || kind == ZEND_AST_STATIC_CALL || kind == ZEND_AST_CALLABLE_CONVERT;
11340
45.3k
}
11341
/* }}} */
11342
11343
static void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */
11344
2.81k
{
11345
2.81k
  zend_ast *ast = *ast_ptr;
11346
2.81k
  zend_ast *class_ast = ast->child[0];
11347
2.81k
  zend_string *class_name;
11348
2.81k
  int fetch_type;
11349
11350
2.81k
  if (class_ast->kind != ZEND_AST_ZVAL) {
11351
15
    zend_error_noreturn(E_COMPILE_ERROR,
11352
15
      "Dynamic class names are not allowed in compile-time class constant references");
11353
15
  }
11354
2.80k
  if (Z_TYPE_P(zend_ast_get_zval(class_ast)) != IS_STRING) {
11355
12
    zend_throw_error(NULL, "Class name must be a valid object or a string");
11356
12
  }
11357
11358
2.80k
  class_name = zend_ast_get_str(class_ast);
11359
2.80k
  fetch_type = zend_get_class_fetch_type(class_name);
11360
11361
2.80k
  if (ZEND_FETCH_CLASS_STATIC == fetch_type) {
11362
8
    zend_error_noreturn(E_COMPILE_ERROR,
11363
8
      "\"static::\" is not allowed in compile-time constants");
11364
8
  }
11365
11366
2.79k
  if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
11367
2.07k
    zend_string *tmp = zend_resolve_class_name_ast(class_ast);
11368
11369
2.07k
    zend_string_release_ex(class_name, 0);
11370
2.07k
    if (tmp != class_name) {
11371
619
      zval *zv = zend_ast_get_zval(class_ast);
11372
619
      ZVAL_STR(zv, tmp);
11373
619
      class_ast->attr = ZEND_NAME_FQ;
11374
619
    }
11375
2.07k
  }
11376
11377
2.79k
  ast->attr |= ZEND_FETCH_CLASS_EXCEPTION;
11378
2.79k
}
11379
/* }}} */
11380
11381
static void zend_compile_const_expr_class_name(zend_ast **ast_ptr) /* {{{ */
11382
78
{
11383
78
  zend_ast *ast = *ast_ptr;
11384
78
  zend_ast *class_ast = ast->child[0];
11385
78
  if (class_ast->kind != ZEND_AST_ZVAL) {
11386
7
    zend_error_noreturn(E_COMPILE_ERROR,
11387
7
      "(expression)::class cannot be used in constant expressions");
11388
7
  }
11389
11390
71
  zend_string *class_name = zend_ast_get_str(class_ast);
11391
71
  uint32_t fetch_type = zend_get_class_fetch_type(class_name);
11392
11393
71
  switch (fetch_type) {
11394
61
    case ZEND_FETCH_CLASS_SELF:
11395
64
    case ZEND_FETCH_CLASS_PARENT:
11396
      /* For the const-eval representation store the fetch type instead of the name. */
11397
64
      zend_string_release(class_name);
11398
64
      ast->child[0] = NULL;
11399
64
      ast->attr = fetch_type;
11400
64
      return;
11401
7
    case ZEND_FETCH_CLASS_STATIC:
11402
7
      zend_error_noreturn(E_COMPILE_ERROR,
11403
7
        "static::class cannot be used for compile-time class name resolution");
11404
0
      return;
11405
71
    EMPTY_SWITCH_DEFAULT_CASE()
11406
71
  }
11407
71
}
11408
11409
static void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */
11410
20.5k
{
11411
20.5k
  zend_ast *ast = *ast_ptr;
11412
20.5k
  zend_ast *name_ast = ast->child[0];
11413
20.5k
  zend_string *orig_name = zend_ast_get_str(name_ast);
11414
20.5k
  bool is_fully_qualified;
11415
20.5k
  zval result;
11416
20.5k
  zend_string *resolved_name;
11417
11418
20.5k
  CG(zend_lineno) = zend_ast_get_lineno(ast);
11419
11420
20.5k
  resolved_name = zend_resolve_const_name(
11421
20.5k
    orig_name, name_ast->attr, &is_fully_qualified);
11422
11423
20.5k
  if (zend_try_ct_eval_const(&result, resolved_name, is_fully_qualified)) {
11424
0
    zend_string_release_ex(resolved_name, 0);
11425
0
    zend_ast_destroy(ast);
11426
0
    *ast_ptr = zend_ast_create_zval(&result);
11427
0
    return;
11428
0
  }
11429
11430
20.5k
  zend_ast_destroy(ast);
11431
20.5k
  *ast_ptr = zend_ast_create_constant(resolved_name,
11432
20.5k
    !is_fully_qualified && FC(current_namespace) ? IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE : 0);
11433
20.5k
}
11434
/* }}} */
11435
11436
static void zend_compile_const_expr_magic_const(zend_ast **ast_ptr) /* {{{ */
11437
222
{
11438
222
  zend_ast *ast = *ast_ptr;
11439
11440
  /* Other cases already resolved by constant folding */
11441
222
  ZEND_ASSERT(ast->attr == T_CLASS_C);
11442
11443
222
  zend_ast_destroy(ast);
11444
222
  *ast_ptr = zend_ast_create(ZEND_AST_CONSTANT_CLASS);
11445
222
}
11446
/* }}} */
11447
11448
static void zend_compile_const_expr_class_reference(zend_ast *class_ast)
11449
905
{
11450
905
  if (class_ast->kind == ZEND_AST_CLASS) {
11451
1
    zend_error_noreturn(E_COMPILE_ERROR,
11452
1
      "Cannot use anonymous class in constant expression");
11453
1
  }
11454
904
  if (class_ast->kind != ZEND_AST_ZVAL) {
11455
7
    zend_error_noreturn(E_COMPILE_ERROR,
11456
7
      "Cannot use dynamic class name in constant expression");
11457
7
  }
11458
11459
897
  zend_string *class_name = zend_resolve_class_name_ast(class_ast);
11460
897
  int fetch_type = zend_get_class_fetch_type(class_name);
11461
897
  if (ZEND_FETCH_CLASS_STATIC == fetch_type) {
11462
6
    zend_error_noreturn(E_COMPILE_ERROR,
11463
6
      "\"static\" is not allowed in compile-time constants");
11464
6
  }
11465
11466
891
  zval *class_ast_zv = zend_ast_get_zval(class_ast);
11467
891
  zval_ptr_dtor_nogc(class_ast_zv);
11468
891
  ZVAL_STR(class_ast_zv, class_name);
11469
891
  class_ast->attr = fetch_type << ZEND_CONST_EXPR_NEW_FETCH_TYPE_SHIFT;
11470
891
}
11471
11472
static void zend_compile_const_expr_new(zend_ast **ast_ptr)
11473
724
{
11474
724
  zend_ast *class_ast = (*ast_ptr)->child[0];
11475
724
  zend_compile_const_expr_class_reference(class_ast);
11476
724
}
11477
11478
static void zend_compile_const_expr_closure(zend_ast **ast_ptr)
11479
264
{
11480
264
  zend_ast_decl *closure_ast = (zend_ast_decl *) *ast_ptr;
11481
264
  zend_ast *uses_ast = closure_ast->child[1];
11482
264
  if (!(closure_ast->flags & ZEND_ACC_STATIC)) {
11483
11
    zend_error_noreturn(E_COMPILE_ERROR,
11484
11
      "Closures in constant expressions must be static");
11485
11
  }
11486
253
  if (uses_ast) {
11487
7
    zend_error_noreturn(E_COMPILE_ERROR,
11488
7
      "Cannot use(...) variables in constant expression");
11489
7
  }
11490
11491
246
  znode node;
11492
246
  zend_op_array *op = zend_compile_func_decl(&node, (zend_ast*)closure_ast, FUNC_DECL_LEVEL_CONSTEXPR);
11493
11494
246
  zend_ast_destroy(*ast_ptr);
11495
246
  *ast_ptr = zend_ast_create_op_array(op);
11496
246
}
11497
11498
static void zend_compile_const_expr_fcc(zend_ast **ast_ptr)
11499
983
{
11500
983
  zend_ast **args_ast;
11501
983
  switch ((*ast_ptr)->kind) {
11502
800
    case ZEND_AST_CALL:
11503
800
      args_ast = &(*ast_ptr)->child[1];
11504
800
      break;
11505
183
    case ZEND_AST_STATIC_CALL:
11506
183
      args_ast = &(*ast_ptr)->child[2];
11507
183
      break;
11508
0
    EMPTY_SWITCH_DEFAULT_CASE();
11509
983
  }
11510
983
  if ((*args_ast)->kind != ZEND_AST_CALLABLE_CONVERT) {
11511
29
    zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
11512
29
  }
11513
954
  ZEND_MAP_PTR_NEW(((zend_ast_fcc *)*args_ast)->fptr);
11514
11515
954
  switch ((*ast_ptr)->kind) {
11516
773
    case ZEND_AST_CALL: {
11517
773
      zend_ast *name_ast = (*ast_ptr)->child[0];
11518
773
      if (name_ast->kind != ZEND_AST_ZVAL) {
11519
19
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use dynamic function name in constant expression");
11520
19
      }
11521
754
      zval *name_ast_zv = zend_ast_get_zval(name_ast);
11522
754
      if (Z_TYPE_P(name_ast_zv) != IS_STRING) {
11523
7
        zend_error_noreturn(E_COMPILE_ERROR, "Illegal function name");
11524
7
      }
11525
754
      bool is_fully_qualified;
11526
747
      zend_string *name = zend_resolve_function_name(Z_STR_P(name_ast_zv), name_ast->attr, &is_fully_qualified);
11527
747
      zval_ptr_dtor_nogc(name_ast_zv);
11528
747
      ZVAL_STR(name_ast_zv, name);
11529
747
      if (is_fully_qualified) {
11530
196
        name_ast->attr = ZEND_NAME_FQ;
11531
196
      }
11532
747
      break;
11533
754
    }
11534
181
    case ZEND_AST_STATIC_CALL: {
11535
181
      zend_ast *class_ast = (*ast_ptr)->child[0];
11536
181
      zend_compile_const_expr_class_reference(class_ast);
11537
181
      zend_ast *method_ast = (*ast_ptr)->child[1];
11538
181
      if (method_ast->kind != ZEND_AST_ZVAL) {
11539
1
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use dynamic method name in constant expression");
11540
1
      }
11541
180
      if (Z_TYPE_P(zend_ast_get_zval(method_ast)) != IS_STRING) {
11542
0
        zend_error_noreturn(E_COMPILE_ERROR, "Illegal method name");
11543
0
      }
11544
180
      break;
11545
180
    }
11546
180
    EMPTY_SWITCH_DEFAULT_CASE();
11547
954
  }
11548
954
}
11549
11550
static void zend_compile_const_expr_args(zend_ast **ast_ptr)
11551
715
{
11552
715
  zend_ast_list *list = zend_ast_get_list(*ast_ptr);
11553
715
  bool uses_named_args = false;
11554
1.06k
  for (uint32_t i = 0; i < list->children; i++) {
11555
346
    zend_ast *arg = list->child[i];
11556
346
    if (arg->kind == ZEND_AST_UNPACK) {
11557
0
      zend_error_noreturn(E_COMPILE_ERROR,
11558
0
        "Argument unpacking in constant expressions is not supported");
11559
0
    }
11560
346
    if (arg->kind == ZEND_AST_NAMED_ARG) {
11561
31
      uses_named_args = true;
11562
315
    } else if (uses_named_args) {
11563
1
      zend_error_noreturn(E_COMPILE_ERROR,
11564
1
        "Cannot use positional argument after named argument");
11565
1
    }
11566
346
  }
11567
714
  if (uses_named_args) {
11568
29
    list->attr = 1;
11569
29
  }
11570
714
}
11571
11572
typedef struct {
11573
  /* Whether the value of this expression may differ on each evaluation. */
11574
  bool allow_dynamic;
11575
} const_expr_context;
11576
11577
static void zend_compile_const_expr(zend_ast **ast_ptr, void *context) /* {{{ */
11578
172k
{
11579
172k
  const_expr_context *ctx = (const_expr_context *) context;
11580
172k
  zend_ast *ast = *ast_ptr;
11581
172k
  if (ast == NULL || ast->kind == ZEND_AST_ZVAL) {
11582
127k
    return;
11583
127k
  }
11584
11585
45.3k
  if (!zend_is_allowed_in_const_expr(ast->kind)) {
11586
40
    zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
11587
40
  }
11588
11589
45.2k
  switch (ast->kind) {
11590
2.81k
    case ZEND_AST_CLASS_CONST:
11591
2.81k
      zend_compile_const_expr_class_const(ast_ptr);
11592
2.81k
      break;
11593
78
    case ZEND_AST_CLASS_NAME:
11594
78
      zend_compile_const_expr_class_name(ast_ptr);
11595
78
      break;
11596
20.5k
    case ZEND_AST_CONST:
11597
20.5k
      zend_compile_const_expr_const(ast_ptr);
11598
20.5k
      break;
11599
222
    case ZEND_AST_MAGIC_CONST:
11600
222
      zend_compile_const_expr_magic_const(ast_ptr);
11601
222
      break;
11602
724
    case ZEND_AST_CAST:
11603
724
      if (ast->attr == IS_OBJECT && !ctx->allow_dynamic) {
11604
7
        zend_error_noreturn(E_COMPILE_ERROR,
11605
7
          "Object casts are not supported in this context");
11606
7
      }
11607
717
      break;
11608
730
    case ZEND_AST_NEW:
11609
730
      if (!ctx->allow_dynamic) {
11610
6
        zend_error_noreturn(E_COMPILE_ERROR,
11611
6
          "New expressions are not supported in this context");
11612
6
      }
11613
724
      zend_compile_const_expr_new(ast_ptr);
11614
724
      break;
11615
715
    case ZEND_AST_ARG_LIST:
11616
715
      zend_compile_const_expr_args(ast_ptr);
11617
715
      break;
11618
264
    case ZEND_AST_CLOSURE:
11619
264
      zend_compile_const_expr_closure(ast_ptr);
11620
      /* Return, because we do not want to traverse the children. */
11621
264
      return;
11622
800
    case ZEND_AST_CALL:
11623
983
    case ZEND_AST_STATIC_CALL:
11624
983
      zend_compile_const_expr_fcc(ast_ptr);
11625
983
      break;
11626
45.2k
  }
11627
11628
44.8k
  zend_ast_apply(ast, zend_compile_const_expr, context);
11629
44.8k
}
11630
/* }}} */
11631
11632
void zend_const_expr_to_zval(zval *result, zend_ast **ast_ptr, bool allow_dynamic) /* {{{ */
11633
106k
{
11634
106k
  const_expr_context context;
11635
106k
  context.allow_dynamic = allow_dynamic;
11636
11637
106k
  zend_eval_const_expr(ast_ptr);
11638
106k
  zend_compile_const_expr(ast_ptr, &context);
11639
106k
  if ((*ast_ptr)->kind != ZEND_AST_ZVAL) {
11640
    /* Replace with compiled AST zval representation. */
11641
22.7k
    zval ast_zv;
11642
22.7k
    ZVAL_AST(&ast_zv, zend_ast_copy(*ast_ptr));
11643
22.7k
    zend_ast_destroy(*ast_ptr);
11644
22.7k
    *ast_ptr = zend_ast_create_zval(&ast_zv);
11645
22.7k
  }
11646
106k
  ZVAL_COPY(result, zend_ast_get_zval(*ast_ptr));
11647
106k
}
11648
/* }}} */
11649
11650
/* Same as compile_stmt, but with early binding */
11651
void zend_compile_top_stmt(zend_ast *ast) /* {{{ */
11652
735k
{
11653
735k
  if (!ast) {
11654
106k
    return;
11655
106k
  }
11656
11657
629k
  if (ast->kind == ZEND_AST_STMT_LIST) {
11658
119k
    zend_ast_list *list = zend_ast_get_list(ast);
11659
119k
    uint32_t i;
11660
757k
    for (i = 0; i < list->children; ++i) {
11661
638k
      zend_compile_top_stmt(list->child[i]);
11662
638k
    }
11663
119k
    return;
11664
119k
  }
11665
11666
509k
  if (ast->kind == ZEND_AST_FUNC_DECL) {
11667
15.3k
    CG(zend_lineno) = ast->lineno;
11668
15.3k
    zend_compile_func_decl(NULL, ast, FUNC_DECL_LEVEL_TOPLEVEL);
11669
15.3k
    CG(zend_lineno) = ((zend_ast_decl *) ast)->end_lineno;
11670
494k
  } else if (ast->kind == ZEND_AST_CLASS) {
11671
46.3k
    CG(zend_lineno) = ast->lineno;
11672
46.3k
    zend_compile_class_decl(NULL, ast, true);
11673
46.3k
    CG(zend_lineno) = ((zend_ast_decl *) ast)->end_lineno;
11674
448k
  } else {
11675
448k
    zend_compile_stmt(ast);
11676
448k
  }
11677
509k
  if (ast->kind != ZEND_AST_NAMESPACE && ast->kind != ZEND_AST_HALT_COMPILER) {
11678
497k
    zend_verify_namespace();
11679
497k
  }
11680
509k
}
11681
/* }}} */
11682
11683
static void zend_compile_stmt(zend_ast *ast) /* {{{ */
11684
4.51M
{
11685
4.51M
  if (!ast) {
11686
331k
    return;
11687
331k
  }
11688
11689
4.17M
  CG(zend_lineno) = ast->lineno;
11690
11691
4.17M
  if ((CG(compiler_options) & ZEND_COMPILE_EXTENDED_STMT) && !zend_is_unticked_stmt(ast)) {
11692
0
    zend_do_extended_stmt(NULL);
11693
0
  }
11694
11695
4.17M
  switch (ast->kind) {
11696
1.03M
    case ZEND_AST_STMT_LIST:
11697
1.03M
      zend_compile_stmt_list(ast);
11698
1.03M
      break;
11699
2.13k
    case ZEND_AST_GLOBAL:
11700
2.13k
      zend_compile_global_var(ast);
11701
2.13k
      break;
11702
1.48k
    case ZEND_AST_STATIC:
11703
1.48k
      zend_compile_static_var(ast);
11704
1.48k
      break;
11705
8.49k
    case ZEND_AST_UNSET:
11706
8.49k
      zend_compile_unset(ast);
11707
8.49k
      break;
11708
39.2k
    case ZEND_AST_RETURN:
11709
39.2k
      zend_compile_return(ast);
11710
39.2k
      break;
11711
940k
    case ZEND_AST_ECHO:
11712
940k
      zend_compile_echo(ast);
11713
940k
      break;
11714
946
    case ZEND_AST_BREAK:
11715
1.87k
    case ZEND_AST_CONTINUE:
11716
1.87k
      zend_compile_break_continue(ast);
11717
1.87k
      break;
11718
2.82k
    case ZEND_AST_GOTO:
11719
2.82k
      zend_compile_goto(ast);
11720
2.82k
      break;
11721
4.46k
    case ZEND_AST_LABEL:
11722
4.46k
      zend_compile_label(ast);
11723
4.46k
      break;
11724
17.4k
    case ZEND_AST_WHILE:
11725
17.4k
      zend_compile_while(ast);
11726
17.4k
      break;
11727
1.30k
    case ZEND_AST_DO_WHILE:
11728
1.30k
      zend_compile_do_while(ast);
11729
1.30k
      break;
11730
13.1k
    case ZEND_AST_FOR:
11731
13.1k
      zend_compile_for(ast);
11732
13.1k
      break;
11733
42.3k
    case ZEND_AST_FOREACH:
11734
42.3k
      zend_compile_foreach(ast);
11735
42.3k
      break;
11736
21.7k
    case ZEND_AST_IF:
11737
21.7k
      zend_compile_if(ast);
11738
21.7k
      break;
11739
16.4k
    case ZEND_AST_SWITCH:
11740
16.4k
      zend_compile_switch(ast);
11741
16.4k
      break;
11742
46.9k
    case ZEND_AST_TRY:
11743
46.9k
      zend_compile_try(ast);
11744
46.9k
      break;
11745
5.24k
    case ZEND_AST_DECLARE:
11746
5.24k
      zend_compile_declare(ast);
11747
5.24k
      break;
11748
5.96k
    case ZEND_AST_FUNC_DECL:
11749
47.9k
    case ZEND_AST_METHOD:
11750
47.9k
      zend_compile_func_decl(NULL, ast, FUNC_DECL_LEVEL_NESTED);
11751
47.9k
      break;
11752
3.16k
    case ZEND_AST_ENUM_CASE:
11753
3.16k
      zend_compile_enum_case(ast);
11754
3.16k
      break;
11755
47.7k
    case ZEND_AST_PROP_GROUP:
11756
47.7k
      zend_compile_prop_group(ast);
11757
47.7k
      break;
11758
5.72k
    case ZEND_AST_CLASS_CONST_GROUP:
11759
5.72k
      zend_compile_class_const_group(ast);
11760
5.72k
      break;
11761
3.67k
    case ZEND_AST_USE_TRAIT:
11762
3.67k
      zend_compile_use_trait(ast);
11763
3.67k
      break;
11764
64.6k
    case ZEND_AST_CLASS:
11765
64.6k
      zend_compile_class_decl(NULL, ast, false);
11766
64.6k
      break;
11767
189
    case ZEND_AST_GROUP_USE:
11768
189
      zend_compile_group_use(ast);
11769
189
      break;
11770
1.41k
    case ZEND_AST_USE:
11771
1.41k
      zend_compile_use(ast);
11772
1.41k
      break;
11773
5.53k
    case ZEND_AST_CONST_DECL:
11774
5.53k
      zend_compile_const_decl(ast);
11775
5.53k
      break;
11776
5.44k
    case ZEND_AST_NAMESPACE:
11777
5.44k
      zend_compile_namespace(ast);
11778
5.44k
      break;
11779
62
    case ZEND_AST_HALT_COMPILER:
11780
62
      zend_compile_halt_compiler(ast);
11781
62
      break;
11782
2.50k
    case ZEND_AST_THROW:
11783
2.50k
      zend_compile_expr(NULL, ast);
11784
2.50k
      break;
11785
1.18k
    case ZEND_AST_CAST_VOID:
11786
1.18k
      zend_compile_void_cast(NULL, ast);
11787
1.18k
      break;
11788
1.78M
    default:
11789
1.78M
    {
11790
1.78M
      znode result;
11791
1.78M
      zend_compile_expr(&result, ast);
11792
1.78M
      zend_do_free(&result);
11793
1.78M
    }
11794
4.17M
  }
11795
11796
4.17M
  if (FC(declarables).ticks && !zend_is_unticked_stmt(ast)) {
11797
11.4k
    zend_emit_tick();
11798
11.4k
  }
11799
4.17M
}
11800
/* }}} */
11801
11802
static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */
11803
21.1M
{
11804
  /* CG(zend_lineno) = ast->lineno; */
11805
21.1M
  CG(zend_lineno) = zend_ast_get_lineno(ast);
11806
11807
21.1M
  if (CG(memoize_mode) != ZEND_MEMOIZE_NONE) {
11808
125k
    zend_compile_memoized_expr(result, ast);
11809
125k
    return;
11810
125k
  }
11811
11812
21.0M
  switch (ast->kind) {
11813
2.34M
    case ZEND_AST_ZVAL:
11814
2.34M
      ZVAL_COPY(&result->u.constant, zend_ast_get_zval(ast));
11815
2.34M
      result->op_type = IS_CONST;
11816
2.34M
      return;
11817
149k
    case ZEND_AST_ZNODE:
11818
149k
      *result = *zend_ast_get_znode(ast);
11819
149k
      return;
11820
460k
    case ZEND_AST_VAR:
11821
521k
    case ZEND_AST_DIM:
11822
544k
    case ZEND_AST_PROP:
11823
580k
    case ZEND_AST_NULLSAFE_PROP:
11824
585k
    case ZEND_AST_STATIC_PROP:
11825
2.26M
    case ZEND_AST_CALL:
11826
2.30M
    case ZEND_AST_METHOD_CALL:
11827
2.30M
    case ZEND_AST_NULLSAFE_METHOD_CALL:
11828
2.32M
    case ZEND_AST_STATIC_CALL:
11829
2.32M
    case ZEND_AST_PARENT_PROPERTY_HOOK_CALL:
11830
2.32M
      zend_compile_var(result, ast, BP_VAR_R, false);
11831
2.32M
      return;
11832
240k
    case ZEND_AST_ASSIGN:
11833
240k
      zend_compile_assign(result, ast);
11834
240k
      return;
11835
9.18k
    case ZEND_AST_ASSIGN_REF:
11836
9.18k
      zend_compile_assign_ref(result, ast);
11837
9.18k
      return;
11838
72.2k
    case ZEND_AST_NEW:
11839
72.2k
      zend_compile_new(result, ast);
11840
72.2k
      return;
11841
151k
    case ZEND_AST_ASSIGN_OP:
11842
151k
      zend_compile_compound_assign(result, ast);
11843
151k
      return;
11844
1.22M
    case ZEND_AST_BINARY_OP:
11845
1.22M
      zend_compile_binary_op(result, ast);
11846
1.22M
      return;
11847
237k
    case ZEND_AST_GREATER:
11848
303k
    case ZEND_AST_GREATER_EQUAL:
11849
303k
      zend_compile_greater(result, ast);
11850
303k
      return;
11851
646k
    case ZEND_AST_UNARY_OP:
11852
646k
      zend_compile_unary_op(result, ast);
11853
646k
      return;
11854
14.7k
    case ZEND_AST_UNARY_PLUS:
11855
52.5k
    case ZEND_AST_UNARY_MINUS:
11856
52.5k
      zend_compile_unary_pm(result, ast);
11857
52.5k
      return;
11858
14.8k
    case ZEND_AST_AND:
11859
20.3k
    case ZEND_AST_OR:
11860
20.3k
      zend_compile_short_circuiting(result, ast);
11861
20.3k
      return;
11862
6.79k
    case ZEND_AST_POST_INC:
11863
9.79k
    case ZEND_AST_POST_DEC:
11864
9.79k
      zend_compile_post_incdec(result, ast);
11865
9.79k
      return;
11866
2.92k
    case ZEND_AST_PRE_INC:
11867
4.73k
    case ZEND_AST_PRE_DEC:
11868
4.73k
      zend_compile_pre_incdec(result, ast);
11869
4.73k
      return;
11870
4.53k
    case ZEND_AST_CAST:
11871
4.53k
      zend_compile_cast(result, ast);
11872
4.53k
      return;
11873
12.3k
    case ZEND_AST_CONDITIONAL:
11874
12.3k
      zend_compile_conditional(result, ast);
11875
12.3k
      return;
11876
838k
    case ZEND_AST_COALESCE:
11877
838k
      zend_compile_coalesce(result, ast);
11878
838k
      return;
11879
17.2k
    case ZEND_AST_ASSIGN_COALESCE:
11880
17.2k
      zend_compile_assign_coalesce(result, ast);
11881
17.2k
      return;
11882
5.03k
    case ZEND_AST_PRINT:
11883
5.03k
      zend_compile_print(result, ast);
11884
5.03k
      return;
11885
11.7k
    case ZEND_AST_YIELD:
11886
11.7k
      zend_compile_yield(result, ast);
11887
11.7k
      return;
11888
1.35k
    case ZEND_AST_YIELD_FROM:
11889
1.35k
      zend_compile_yield_from(result, ast);
11890
1.35k
      return;
11891
722
    case ZEND_AST_INSTANCEOF:
11892
722
      zend_compile_instanceof(result, ast);
11893
722
      return;
11894
8.12k
    case ZEND_AST_INCLUDE_OR_EVAL:
11895
8.12k
      zend_compile_include_or_eval(result, ast);
11896
8.12k
      return;
11897
8.91k
    case ZEND_AST_ISSET:
11898
10.2k
    case ZEND_AST_EMPTY:
11899
10.2k
      zend_compile_isset_or_empty(result, ast);
11900
10.2k
      return;
11901
7.69M
    case ZEND_AST_SILENCE:
11902
7.69M
      zend_compile_silence(result, ast);
11903
7.69M
      return;
11904
52.9k
    case ZEND_AST_SHELL_EXEC:
11905
52.9k
      zend_compile_shell_exec(result, ast);
11906
52.9k
      return;
11907
95.3k
    case ZEND_AST_ARRAY:
11908
95.3k
      zend_compile_array(result, ast);
11909
95.3k
      return;
11910
3.92M
    case ZEND_AST_CONST:
11911
3.92M
      zend_compile_const(result, ast);
11912
3.92M
      return;
11913
34.2k
    case ZEND_AST_CLASS_CONST:
11914
34.2k
      zend_compile_class_const(result, ast);
11915
34.2k
      return;
11916
5.71k
    case ZEND_AST_CLASS_NAME:
11917
5.71k
      zend_compile_class_name(result, ast);
11918
5.71k
      return;
11919
43.7k
    case ZEND_AST_ENCAPS_LIST:
11920
43.7k
      zend_compile_encaps_list(result, ast);
11921
43.7k
      return;
11922
18.6k
    case ZEND_AST_MAGIC_CONST:
11923
18.6k
      zend_compile_magic_const(result, ast);
11924
18.6k
      return;
11925
622k
    case ZEND_AST_CLOSURE:
11926
643k
    case ZEND_AST_ARROW_FUNC:
11927
643k
      zend_compile_func_decl(result, ast, FUNC_DECL_LEVEL_NESTED);
11928
643k
      return;
11929
4.17k
    case ZEND_AST_THROW:
11930
4.17k
      zend_compile_throw(result, ast);
11931
4.17k
      return;
11932
3.56k
    case ZEND_AST_MATCH:
11933
3.56k
      zend_compile_match(result, ast);
11934
3.56k
      return;
11935
71.9k
    case ZEND_AST_PIPE:
11936
71.9k
      zend_compile_pipe(result, ast);
11937
71.9k
      return;
11938
0
    default:
11939
0
      ZEND_ASSERT(0 /* not supported */);
11940
21.0M
  }
11941
21.0M
}
11942
/* }}} */
11943
11944
static void zend_compile_expr(znode *result, zend_ast *ast)
11945
21.1M
{
11946
21.1M
  zend_check_stack_limit();
11947
11948
21.1M
  uint32_t checkpoint = zend_short_circuiting_checkpoint();
11949
21.1M
  zend_compile_expr_inner(result, ast);
11950
21.1M
  zend_short_circuiting_commit(checkpoint, result, ast);
11951
21.1M
}
11952
11953
static zend_op *zend_compile_var_inner(znode *result, zend_ast *ast, uint32_t type, bool by_ref)
11954
3.49M
{
11955
3.49M
  CG(zend_lineno) = zend_ast_get_lineno(ast);
11956
11957
3.49M
  if (CG(memoize_mode) != ZEND_MEMOIZE_NONE) {
11958
44.8k
    switch (ast->kind) {
11959
605
      case ZEND_AST_CALL:
11960
1.67k
      case ZEND_AST_METHOD_CALL:
11961
1.67k
      case ZEND_AST_NULLSAFE_METHOD_CALL:
11962
10.3k
      case ZEND_AST_STATIC_CALL:
11963
10.3k
        zend_compile_memoized_expr(result, ast);
11964
        /* This might not actually produce an opcode, e.g. for expressions evaluated at comptime. */
11965
10.3k
        return NULL;
11966
44.8k
    }
11967
44.8k
  }
11968
11969
3.47M
  switch (ast->kind) {
11970
509k
    case ZEND_AST_VAR:
11971
509k
      return zend_compile_simple_var(result, ast, type, false);
11972
97.4k
    case ZEND_AST_DIM:
11973
97.4k
      return zend_compile_dim(result, ast, type, by_ref);
11974
32.1k
    case ZEND_AST_PROP:
11975
69.0k
    case ZEND_AST_NULLSAFE_PROP:
11976
69.0k
      return zend_compile_prop(result, ast, type, by_ref);
11977
11.2k
    case ZEND_AST_STATIC_PROP:
11978
11.2k
      return zend_compile_static_prop(result, ast, type, by_ref, false);
11979
1.81M
    case ZEND_AST_CALL:
11980
1.81M
      zend_compile_call(result, ast, type);
11981
1.81M
      return NULL;
11982
0
    case ZEND_AST_PARENT_PROPERTY_HOOK_CALL:
11983
0
      zend_compile_parent_property_hook_call(result, ast, type);
11984
0
      return NULL;
11985
61.3k
    case ZEND_AST_METHOD_CALL:
11986
63.9k
    case ZEND_AST_NULLSAFE_METHOD_CALL:
11987
63.9k
      zend_compile_method_call(result, ast, type);
11988
63.9k
      return NULL;
11989
28.9k
    case ZEND_AST_STATIC_CALL:
11990
28.9k
      zend_compile_static_call(result, ast, type);
11991
28.9k
      return NULL;
11992
3.74k
    case ZEND_AST_ZNODE:
11993
3.74k
      *result = *zend_ast_get_znode(ast);
11994
3.74k
      return NULL;
11995
884k
    default:
11996
884k
      if (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) {
11997
237
        zend_error_noreturn(E_COMPILE_ERROR,
11998
237
          "Cannot use temporary expression in write context");
11999
237
      }
12000
12001
884k
      zend_compile_expr(result, ast);
12002
884k
      return NULL;
12003
3.47M
  }
12004
3.47M
}
12005
12006
static zend_op *zend_compile_var(znode *result, zend_ast *ast, uint32_t type, bool by_ref) /* {{{ */
12007
3.49M
{
12008
3.49M
  zend_check_stack_limit();
12009
12010
3.49M
  uint32_t checkpoint = zend_short_circuiting_checkpoint();
12011
3.49M
  zend_op *opcode = zend_compile_var_inner(result, ast, type, by_ref);
12012
3.49M
  zend_short_circuiting_commit(checkpoint, result, ast);
12013
3.49M
  return opcode;
12014
3.49M
}
12015
12016
static zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type, bool by_ref) /* {{{ */
12017
683k
{
12018
683k
  zend_check_stack_limit();
12019
12020
683k
  switch (ast->kind) {
12021
465k
    case ZEND_AST_VAR:
12022
465k
      return zend_compile_simple_var(result, ast, type, true);
12023
95.0k
    case ZEND_AST_DIM:
12024
95.0k
      return zend_delayed_compile_dim(result, ast, type, by_ref);
12025
24.2k
    case ZEND_AST_PROP:
12026
32.2k
    case ZEND_AST_NULLSAFE_PROP:
12027
32.2k
    {
12028
32.2k
      zend_op *opline = zend_delayed_compile_prop(result, ast, type);
12029
32.2k
      if (by_ref) {
12030
925
        opline->extended_value |= ZEND_FETCH_REF;
12031
925
      }
12032
32.2k
      return opline;
12033
24.2k
    }
12034
8.91k
    case ZEND_AST_STATIC_PROP:
12035
8.91k
      return zend_compile_static_prop(result, ast, type, by_ref, true);
12036
81.6k
    default:
12037
81.6k
      return zend_compile_var(result, ast, type, false);
12038
683k
  }
12039
683k
}
12040
/* }}} */
12041
12042
bool zend_try_ct_eval_cast(zval *result, uint32_t type, zval *op1)
12043
12.7k
{
12044
  /* NAN warns when casting */
12045
12.7k
  if (UNEXPECTED(Z_TYPE_P(op1) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op1)))) {
12046
0
    return false;
12047
0
  }
12048
12.7k
  switch (type) {
12049
98
    case _IS_BOOL:
12050
98
      ZVAL_BOOL(result, zval_is_true(op1));
12051
98
      return true;
12052
288
    case IS_LONG:
12053
288
      if (Z_TYPE_P(op1) == IS_DOUBLE && !ZEND_DOUBLE_FITS_LONG(Z_DVAL_P((op1)))) {
12054
10
        return false;
12055
10
      }
12056
278
      ZVAL_LONG(result, zval_get_long(op1));
12057
278
      return true;
12058
692
    case IS_DOUBLE:
12059
692
      ZVAL_DOUBLE(result, zval_get_double(op1));
12060
692
      return true;
12061
10.8k
    case IS_STRING:
12062
      /* Conversion from double to string takes into account run-time
12063
         'precision' setting and cannot be evaluated at compile-time */
12064
10.8k
      if (Z_TYPE_P(op1) != IS_ARRAY && Z_TYPE_P(op1) != IS_DOUBLE) {
12065
10.1k
        ZVAL_STR(result, zval_get_string(op1));
12066
10.1k
        return true;
12067
10.1k
      }
12068
702
      break;
12069
702
    case IS_ARRAY:
12070
183
      ZVAL_COPY(result, op1);
12071
183
      convert_to_array(result);
12072
183
      return true;
12073
12.7k
  }
12074
1.38k
  return false;
12075
12.7k
}
12076
12077
static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
12078
9.95M
{
12079
9.95M
  zend_ast *ast = *ast_ptr;
12080
9.95M
  zval result;
12081
12082
9.95M
  if (!ast) {
12083
3.04M
    return;
12084
3.04M
  }
12085
12086
6.90M
  zend_check_stack_limit();
12087
12088
6.90M
  switch (ast->kind) {
12089
100k
    case ZEND_AST_BINARY_OP:
12090
100k
      zend_eval_const_expr(&ast->child[0]);
12091
100k
      zend_eval_const_expr(&ast->child[1]);
12092
100k
      if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
12093
68.3k
        return;
12094
68.3k
      }
12095
12096
31.8k
      if (!zend_try_ct_eval_binary_op(&result, ast->attr,
12097
31.8k
          zend_ast_get_zval(ast->child[0]), zend_ast_get_zval(ast->child[1]))
12098
31.8k
      ) {
12099
13.9k
        return;
12100
13.9k
      }
12101
17.8k
      break;
12102
17.8k
    case ZEND_AST_GREATER:
12103
4.78k
    case ZEND_AST_GREATER_EQUAL:
12104
4.78k
      zend_eval_const_expr(&ast->child[0]);
12105
4.78k
      zend_eval_const_expr(&ast->child[1]);
12106
4.78k
      if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
12107
3.23k
        return;
12108
3.23k
      }
12109
12110
1.54k
      zend_ct_eval_greater(&result, ast->kind,
12111
1.54k
        zend_ast_get_zval(ast->child[0]), zend_ast_get_zval(ast->child[1]));
12112
1.54k
      break;
12113
3.41k
    case ZEND_AST_AND:
12114
4.61k
    case ZEND_AST_OR:
12115
4.61k
    {
12116
4.61k
      bool child0_is_true, child1_is_true;
12117
4.61k
      zend_eval_const_expr(&ast->child[0]);
12118
4.61k
      zend_eval_const_expr(&ast->child[1]);
12119
4.61k
      if (ast->child[0]->kind != ZEND_AST_ZVAL) {
12120
3.37k
        return;
12121
3.37k
      }
12122
12123
1.24k
      child0_is_true = zend_is_true(zend_ast_get_zval(ast->child[0]));
12124
1.24k
      if (child0_is_true == (ast->kind == ZEND_AST_OR)) {
12125
329
        ZVAL_BOOL(&result, ast->kind == ZEND_AST_OR);
12126
329
        break;
12127
329
      }
12128
12129
911
      if (ast->child[1]->kind != ZEND_AST_ZVAL) {
12130
197
        return;
12131
197
      }
12132
12133
714
      child1_is_true = zend_is_true(zend_ast_get_zval(ast->child[1]));
12134
714
      if (ast->kind == ZEND_AST_OR) {
12135
48
        ZVAL_BOOL(&result, child0_is_true || child1_is_true);
12136
666
      } else {
12137
666
        ZVAL_BOOL(&result, child0_is_true && child1_is_true);
12138
666
      }
12139
714
      break;
12140
911
    }
12141
7.90k
    case ZEND_AST_UNARY_OP:
12142
7.90k
      zend_eval_const_expr(&ast->child[0]);
12143
7.90k
      if (ast->child[0]->kind != ZEND_AST_ZVAL) {
12144
3.06k
        return;
12145
3.06k
      }
12146
12147
4.84k
      if (!zend_try_ct_eval_unary_op(&result, ast->attr, zend_ast_get_zval(ast->child[0]))) {
12148
782
        return;
12149
782
      }
12150
4.05k
      break;
12151
4.05k
    case ZEND_AST_UNARY_PLUS:
12152
55.3k
    case ZEND_AST_UNARY_MINUS:
12153
55.3k
      zend_eval_const_expr(&ast->child[0]);
12154
55.3k
      if (ast->child[0]->kind != ZEND_AST_ZVAL) {
12155
37.6k
        return;
12156
37.6k
      }
12157
12158
17.6k
      if (!zend_try_ct_eval_unary_pm(&result, ast->kind, zend_ast_get_zval(ast->child[0]))) {
12159
4.38k
        return;
12160
4.38k
      }
12161
13.3k
      break;
12162
43.9k
    case ZEND_AST_COALESCE:
12163
      /* Set isset fetch indicator here, opcache disallows runtime altering of the AST */
12164
43.9k
      if (ast->child[0]->kind == ZEND_AST_DIM) {
12165
296
        ast->child[0]->attr |= ZEND_DIM_IS;
12166
296
      }
12167
43.9k
      zend_eval_const_expr(&ast->child[0]);
12168
12169
43.9k
      if (ast->child[0]->kind != ZEND_AST_ZVAL) {
12170
        /* ensure everything was compile-time evaluated at least once */
12171
43.6k
        zend_eval_const_expr(&ast->child[1]);
12172
43.6k
        return;
12173
43.6k
      }
12174
12175
264
      if (Z_TYPE_P(zend_ast_get_zval(ast->child[0])) == IS_NULL) {
12176
200
        zend_eval_const_expr(&ast->child[1]);
12177
200
        *ast_ptr = ast->child[1];
12178
200
        ast->child[1] = NULL;
12179
200
        zend_ast_destroy(ast);
12180
200
      } else {
12181
64
        *ast_ptr = ast->child[0];
12182
64
        ast->child[0] = NULL;
12183
64
        zend_ast_destroy(ast);
12184
64
      }
12185
264
      return;
12186
2.31k
    case ZEND_AST_CONDITIONAL:
12187
2.31k
    {
12188
2.31k
      zend_ast **child, *child_ast;
12189
2.31k
      zend_eval_const_expr(&ast->child[0]);
12190
2.31k
      if (ast->child[0]->kind != ZEND_AST_ZVAL) {
12191
        /* ensure everything was compile-time evaluated at least once */
12192
2.16k
        if (ast->child[1]) {
12193
1.34k
          zend_eval_const_expr(&ast->child[1]);
12194
1.34k
        }
12195
2.16k
        zend_eval_const_expr(&ast->child[2]);
12196
2.16k
        return;
12197
2.16k
      }
12198
12199
143
      child = &ast->child[2 - zend_is_true(zend_ast_get_zval(ast->child[0]))];
12200
143
      if (*child == NULL) {
12201
84
        child--;
12202
84
      }
12203
143
      child_ast = *child;
12204
143
      *child = NULL;
12205
143
      zend_ast_destroy(ast);
12206
143
      *ast_ptr = child_ast;
12207
143
      zend_eval_const_expr(ast_ptr);
12208
143
      return;
12209
2.31k
    }
12210
1.15M
    case ZEND_AST_DIM:
12211
1.15M
    {
12212
      /* constant expression should be always read context ... */
12213
1.15M
      zval *container, *dim;
12214
12215
1.15M
      if (ast->child[1] == NULL) {
12216
44
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
12217
44
      }
12218
12219
      /* Set isset fetch indicator here, opcache disallows runtime altering of the AST */
12220
1.15M
      if ((ast->attr & ZEND_DIM_IS) && ast->child[0]->kind == ZEND_AST_DIM) {
12221
488
        ast->child[0]->attr |= ZEND_DIM_IS;
12222
488
      }
12223
12224
1.15M
      zend_eval_const_expr(&ast->child[0]);
12225
1.15M
      zend_eval_const_expr(&ast->child[1]);
12226
1.15M
      if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
12227
1.08M
        return;
12228
1.08M
      }
12229
12230
71.8k
      container = zend_ast_get_zval(ast->child[0]);
12231
71.8k
      dim = zend_ast_get_zval(ast->child[1]);
12232
12233
71.8k
      if (Z_TYPE_P(container) == IS_ARRAY) {
12234
69.1k
        zval *el;
12235
69.1k
        if (Z_TYPE_P(dim) == IS_LONG) {
12236
703
          el = zend_hash_index_find(Z_ARR_P(container), Z_LVAL_P(dim));
12237
703
          if (el) {
12238
363
            ZVAL_COPY(&result, el);
12239
363
          } else {
12240
340
            return;
12241
340
          }
12242
68.4k
        } else if (Z_TYPE_P(dim) == IS_STRING) {
12243
67.2k
          el = zend_symtable_find(Z_ARR_P(container), Z_STR_P(dim));
12244
67.2k
          if (el) {
12245
393
            ZVAL_COPY(&result, el);
12246
66.9k
          } else {
12247
66.9k
            return;
12248
66.9k
          }
12249
67.2k
        } else {
12250
1.15k
          return; /* warning... handle at runtime */
12251
1.15k
        }
12252
69.1k
      } else if (Z_TYPE_P(container) == IS_STRING) {
12253
2.21k
        zend_long offset;
12254
2.21k
        uint8_t c;
12255
2.21k
        if (Z_TYPE_P(dim) == IS_LONG) {
12256
650
          offset = Z_LVAL_P(dim);
12257
1.56k
        } else if (Z_TYPE_P(dim) != IS_STRING || is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), &offset, NULL, 1) != IS_LONG) {
12258
1.27k
          return;
12259
1.27k
        }
12260
936
        if (offset < 0 || (size_t)offset >= Z_STRLEN_P(container)) {
12261
805
          return;
12262
805
        }
12263
131
        c = (uint8_t) Z_STRVAL_P(container)[offset];
12264
131
        ZVAL_CHAR(&result, c);
12265
443
      } else if (Z_TYPE_P(container) <= IS_FALSE) {
12266
134
        return; /* warning... handle at runtime */
12267
309
      } else {
12268
309
        return;
12269
309
      }
12270
887
      break;
12271
71.8k
    }
12272
2.65M
    case ZEND_AST_ARRAY:
12273
2.65M
      if (!zend_try_ct_eval_array(&result, ast)) {
12274
2.61M
        return;
12275
2.61M
      }
12276
38.1k
      break;
12277
38.1k
    case ZEND_AST_MAGIC_CONST:
12278
1.62k
      if (!zend_try_ct_eval_magic_const(&result, ast)) {
12279
222
        return;
12280
222
      }
12281
1.40k
      break;
12282
153k
    case ZEND_AST_CONST:
12283
153k
    {
12284
153k
      zend_ast *name_ast = ast->child[0];
12285
153k
      bool is_fully_qualified;
12286
153k
      zend_string *resolved_name = zend_resolve_const_name(
12287
153k
        zend_ast_get_str(name_ast), name_ast->attr, &is_fully_qualified);
12288
12289
153k
      if (!zend_try_ct_eval_const(&result, resolved_name, is_fully_qualified)) {
12290
148k
        zend_string_release_ex(resolved_name, 0);
12291
148k
        return;
12292
148k
      }
12293
12294
5.08k
      zend_string_release_ex(resolved_name, 0);
12295
5.08k
      break;
12296
153k
    }
12297
259k
    case ZEND_AST_CLASS_CONST:
12298
259k
    {
12299
259k
      zend_ast *class_ast;
12300
259k
      zend_ast *name_ast;
12301
259k
      zend_string *resolved_name;
12302
12303
259k
      zend_eval_const_expr(&ast->child[0]);
12304
259k
      zend_eval_const_expr(&ast->child[1]);
12305
12306
259k
      if (UNEXPECTED(ast->child[1]->kind != ZEND_AST_ZVAL
12307
259k
        || Z_TYPE_P(zend_ast_get_zval(ast->child[1])) != IS_STRING)) {
12308
1.57k
        return;
12309
1.57k
      }
12310
12311
258k
      class_ast = ast->child[0];
12312
258k
      name_ast = ast->child[1];
12313
12314
258k
      if (class_ast->kind != ZEND_AST_ZVAL || name_ast->kind != ZEND_AST_ZVAL) {
12315
240k
        return;
12316
240k
      }
12317
12318
17.4k
      resolved_name = zend_resolve_class_name_ast(class_ast);
12319
17.4k
      if (!zend_try_ct_eval_class_const(&result, resolved_name, zend_ast_get_str(name_ast))) {
12320
17.1k
        zend_string_release_ex(resolved_name, 0);
12321
17.1k
        return;
12322
17.1k
      }
12323
12324
242
      zend_string_release_ex(resolved_name, 0);
12325
242
      break;
12326
17.4k
    }
12327
2.88k
    case ZEND_AST_CLASS_NAME:
12328
2.88k
    {
12329
2.88k
      zend_ast *class_ast = ast->child[0];
12330
2.88k
      if (!zend_try_compile_const_expr_resolve_class_name(&result, class_ast)) {
12331
1.71k
        return;
12332
1.71k
      }
12333
1.17k
      break;
12334
2.88k
    }
12335
    // TODO: We should probably use zend_ast_apply to recursively walk nodes without
12336
    // special handling. It is required that all nodes that are part of a const expr
12337
    // are visited. Probably we should be distinguishing evaluation of const expr and
12338
    // normal exprs here.
12339
3.48k
    case ZEND_AST_ARG_LIST:
12340
3.48k
    {
12341
3.48k
      zend_ast_list *list = zend_ast_get_list(ast);
12342
4.44k
      for (uint32_t i = 0; i < list->children; i++) {
12343
955
        zend_eval_const_expr(&list->child[i]);
12344
955
      }
12345
3.48k
      return;
12346
2.88k
    }
12347
3.48k
    case ZEND_AST_NEW:
12348
3.48k
      zend_eval_const_expr(&ast->child[0]);
12349
3.48k
      zend_eval_const_expr(&ast->child[1]);
12350
3.48k
      return;
12351
99
    case ZEND_AST_NAMED_ARG:
12352
99
      zend_eval_const_expr(&ast->child[1]);
12353
99
      return;
12354
3.13k
    case ZEND_AST_CONST_ENUM_INIT:
12355
3.13k
      zend_eval_const_expr(&ast->child[2]);
12356
3.13k
      return;
12357
1.84k
    case ZEND_AST_PROP:
12358
2.43k
    case ZEND_AST_NULLSAFE_PROP:
12359
2.43k
      zend_eval_const_expr(&ast->child[0]);
12360
2.43k
      zend_eval_const_expr(&ast->child[1]);
12361
2.43k
      return;
12362
243k
    case ZEND_AST_CAST:
12363
243k
      zend_eval_const_expr(&ast->child[0]);
12364
243k
      if (ast->child[0]->kind == ZEND_AST_ZVAL
12365
1.42k
       && zend_try_ct_eval_cast(&result, ast->attr, zend_ast_get_zval(ast->child[0]))) {
12366
1.16k
        break;
12367
1.16k
      }
12368
242k
      return;
12369
2.20M
    default:
12370
2.20M
      return;
12371
6.90M
  }
12372
12373
85.3k
  zend_ast_destroy(ast);
12374
85.3k
  *ast_ptr = zend_ast_create_zval(&result);
12375
85.3k
}
12376
/* }}} */