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_attributes.h"
24 #include "zend_compile.h"
25 #include "zend_constants.h"
26 #include "zend_llist.h"
27 #include "zend_API.h"
28 #include "zend_exceptions.h"
29 #include "zend_interfaces.h"
30 #include "zend_virtual_cwd.h"
31 #include "zend_multibyte.h"
32 #include "zend_language_scanner.h"
33 #include "zend_inheritance.h"
34 #include "zend_vm.h"
35 #include "zend_enum.h"
36 
37 #define SET_NODE(target, src) do { \
38 		target ## _type = (src)->op_type; \
39 		if ((src)->op_type == IS_CONST) { \
40 			target.constant = zend_add_literal(&(src)->u.constant); \
41 		} else { \
42 			target = (src)->u.op; \
43 		} \
44 	} while (0)
45 
46 #define GET_NODE(target, src) do { \
47 		(target)->op_type = src ## _type; \
48 		if ((target)->op_type == IS_CONST) { \
49 			ZVAL_COPY_VALUE(&(target)->u.constant, CT_CONSTANT(src)); \
50 		} else { \
51 			(target)->u.op = src; \
52 		} \
53 	} while (0)
54 
55 #define FC(member) (CG(file_context).member)
56 
57 typedef struct _zend_loop_var {
58 	zend_uchar opcode;
59 	zend_uchar var_type;
60 	uint32_t   var_num;
61 	uint32_t   try_catch_offset;
62 } zend_loop_var;
63 
zend_alloc_cache_slots(unsigned count)64 static inline uint32_t zend_alloc_cache_slots(unsigned count) {
65 	if (count == 0) {
66 		/* Even if no cache slots are desired, the VM handler may still want to acquire
67 		 * CACHE_ADDR() unconditionally. Returning zero makes sure that the address
68 		 * calculation is still legal and ubsan does not complain. */
69 		return 0;
70 	}
71 
72 	zend_op_array *op_array = CG(active_op_array);
73 	uint32_t ret = op_array->cache_size;
74 	op_array->cache_size += count * sizeof(void*);
75 	return ret;
76 }
77 
zend_alloc_cache_slot(void)78 static inline uint32_t zend_alloc_cache_slot(void) {
79 	return zend_alloc_cache_slots(1);
80 }
81 
82 ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type);
83 ZEND_API zend_op_array *(*zend_compile_string)(zend_string *source_string, const char *filename);
84 
85 #ifndef ZTS
86 ZEND_API zend_compiler_globals compiler_globals;
87 ZEND_API zend_executor_globals executor_globals;
88 #endif
89 
90 static zend_op *zend_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2);
91 static bool zend_try_ct_eval_array(zval *result, zend_ast *ast);
92 static void zend_eval_const_expr(zend_ast **ast_ptr);
93 
94 static zend_op *zend_compile_var(znode *result, zend_ast *ast, uint32_t type, bool by_ref);
95 static zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type, bool by_ref);
96 static void zend_compile_expr(znode *result, zend_ast *ast);
97 static void zend_compile_stmt(zend_ast *ast);
98 static void zend_compile_assign(znode *result, zend_ast *ast);
99 
init_op(zend_op * op)100 static void init_op(zend_op *op)
101 {
102 	MAKE_NOP(op);
103 	op->extended_value = 0;
104 	op->lineno = CG(zend_lineno);
105 }
106 
get_next_op_number(void)107 static zend_always_inline uint32_t get_next_op_number(void)
108 {
109 	return CG(active_op_array)->last;
110 }
111 
get_next_op(void)112 static zend_op *get_next_op(void)
113 {
114 	zend_op_array *op_array = CG(active_op_array);
115 	uint32_t next_op_num = op_array->last++;
116 	zend_op *next_op;
117 
118 	if (UNEXPECTED(next_op_num >= CG(context).opcodes_size)) {
119 		CG(context).opcodes_size *= 4;
120 		op_array->opcodes = erealloc(op_array->opcodes, CG(context).opcodes_size * sizeof(zend_op));
121 	}
122 
123 	next_op = &(op_array->opcodes[next_op_num]);
124 
125 	init_op(next_op);
126 
127 	return next_op;
128 }
129 
get_next_brk_cont_element(void)130 static zend_brk_cont_element *get_next_brk_cont_element(void)
131 {
132 	CG(context).last_brk_cont++;
133 	CG(context).brk_cont_array = erealloc(CG(context).brk_cont_array, sizeof(zend_brk_cont_element) * CG(context).last_brk_cont);
134 	return &CG(context).brk_cont_array[CG(context).last_brk_cont-1];
135 }
136 
zend_build_runtime_definition_key(zend_string * name,uint32_t start_lineno)137 static zend_string *zend_build_runtime_definition_key(zend_string *name, uint32_t start_lineno) /* {{{ */
138 {
139 	zend_string *filename = CG(active_op_array)->filename;
140 	zend_string *result = zend_strpprintf(0, "%c%s%s:%" PRIu32 "$%" PRIx32,
141 		'\0', ZSTR_VAL(name), ZSTR_VAL(filename), start_lineno, CG(rtd_key_counter)++);
142 	return zend_new_interned_string(result);
143 }
144 /* }}} */
145 
zend_get_unqualified_name(const zend_string * name,const char ** result,size_t * result_len)146 static bool zend_get_unqualified_name(const zend_string *name, const char **result, size_t *result_len) /* {{{ */
147 {
148 	const char *ns_separator = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
149 	if (ns_separator != NULL) {
150 		*result = ns_separator + 1;
151 		*result_len = ZSTR_VAL(name) + ZSTR_LEN(name) - *result;
152 		return 1;
153 	}
154 
155 	return 0;
156 }
157 /* }}} */
158 
159 struct reserved_class_name {
160 	const char *name;
161 	size_t len;
162 };
163 static const struct reserved_class_name reserved_class_names[] = {
164 	{ZEND_STRL("bool")},
165 	{ZEND_STRL("false")},
166 	{ZEND_STRL("float")},
167 	{ZEND_STRL("int")},
168 	{ZEND_STRL("null")},
169 	{ZEND_STRL("parent")},
170 	{ZEND_STRL("self")},
171 	{ZEND_STRL("static")},
172 	{ZEND_STRL("string")},
173 	{ZEND_STRL("true")},
174 	{ZEND_STRL("void")},
175 	{ZEND_STRL("never")},
176 	{ZEND_STRL("iterable")},
177 	{ZEND_STRL("object")},
178 	{ZEND_STRL("mixed")},
179 	{NULL, 0}
180 };
181 
zend_is_reserved_class_name(const zend_string * name)182 static bool zend_is_reserved_class_name(const zend_string *name) /* {{{ */
183 {
184 	const struct reserved_class_name *reserved = reserved_class_names;
185 
186 	const char *uqname = ZSTR_VAL(name);
187 	size_t uqname_len = ZSTR_LEN(name);
188 	zend_get_unqualified_name(name, &uqname, &uqname_len);
189 
190 	for (; reserved->name; ++reserved) {
191 		if (uqname_len == reserved->len
192 			&& zend_binary_strcasecmp(uqname, uqname_len, reserved->name, reserved->len) == 0
193 		) {
194 			return 1;
195 		}
196 	}
197 
198 	return 0;
199 }
200 /* }}} */
201 
zend_assert_valid_class_name(const zend_string * name)202 void zend_assert_valid_class_name(const zend_string *name) /* {{{ */
203 {
204 	if (zend_is_reserved_class_name(name)) {
205 		zend_error_noreturn(E_COMPILE_ERROR,
206 			"Cannot use '%s' as class name as it is reserved", ZSTR_VAL(name));
207 	}
208 }
209 /* }}} */
210 
211 typedef struct _builtin_type_info {
212 	const char* name;
213 	const size_t name_len;
214 	const zend_uchar type;
215 } builtin_type_info;
216 
217 static const builtin_type_info builtin_types[] = {
218 	{ZEND_STRL("null"), IS_NULL},
219 	{ZEND_STRL("false"), IS_FALSE},
220 	{ZEND_STRL("int"), IS_LONG},
221 	{ZEND_STRL("float"), IS_DOUBLE},
222 	{ZEND_STRL("string"), IS_STRING},
223 	{ZEND_STRL("bool"), _IS_BOOL},
224 	{ZEND_STRL("void"), IS_VOID},
225 	{ZEND_STRL("never"), IS_NEVER},
226 	{ZEND_STRL("iterable"), IS_ITERABLE},
227 	{ZEND_STRL("object"), IS_OBJECT},
228 	{ZEND_STRL("mixed"), IS_MIXED},
229 	{NULL, 0, IS_UNDEF}
230 };
231 
232 typedef struct {
233 	const char *name;
234 	size_t name_len;
235 	const char *correct_name;
236 } confusable_type_info;
237 
238 static const confusable_type_info confusable_types[] = {
239 	{ZEND_STRL("boolean"), "bool"},
240 	{ZEND_STRL("integer"), "int"},
241 	{ZEND_STRL("double"), "float"},
242 	{ZEND_STRL("resource"), NULL},
243 	{NULL, 0, NULL},
244 };
245 
zend_lookup_builtin_type_by_name(const zend_string * name)246 static zend_always_inline zend_uchar zend_lookup_builtin_type_by_name(const zend_string *name) /* {{{ */
247 {
248 	const builtin_type_info *info = &builtin_types[0];
249 
250 	for (; info->name; ++info) {
251 		if (ZSTR_LEN(name) == info->name_len
252 			&& zend_binary_strcasecmp(ZSTR_VAL(name), ZSTR_LEN(name), info->name, info->name_len) == 0
253 		) {
254 			return info->type;
255 		}
256 	}
257 
258 	return 0;
259 }
260 /* }}} */
261 
zend_is_confusable_type(const zend_string * name,const char ** correct_name)262 static zend_always_inline bool zend_is_confusable_type(const zend_string *name, const char **correct_name) /* {{{ */
263 {
264 	const confusable_type_info *info = confusable_types;
265 
266 	/* Intentionally using case-sensitive comparison here, because "integer" is likely intended
267 	 * as a scalar type, while "Integer" is likely a class type. */
268 	for (; info->name; ++info) {
269 		if (ZSTR_LEN(name) == info->name_len
270 			&& memcmp(ZSTR_VAL(name), info->name, info->name_len) == 0
271 		) {
272 			*correct_name = info->correct_name;
273 			return 1;
274 		}
275 	}
276 
277 	return 0;
278 }
279 /* }}} */
280 
zend_is_not_imported(zend_string * name)281 static bool zend_is_not_imported(zend_string *name) {
282 	/* Assuming "name" is unqualified here. */
283 	return !FC(imports) || zend_hash_find_ptr_lc(FC(imports), name) == NULL;
284 }
285 
zend_oparray_context_begin(zend_oparray_context * prev_context)286 void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */
287 {
288 	*prev_context = CG(context);
289 	CG(context).opcodes_size = INITIAL_OP_ARRAY_SIZE;
290 	CG(context).vars_size = 0;
291 	CG(context).literals_size = 0;
292 	CG(context).fast_call_var = -1;
293 	CG(context).try_catch_offset = -1;
294 	CG(context).current_brk_cont = -1;
295 	CG(context).last_brk_cont = 0;
296 	CG(context).brk_cont_array = NULL;
297 	CG(context).labels = NULL;
298 }
299 /* }}} */
300 
zend_oparray_context_end(zend_oparray_context * prev_context)301 void zend_oparray_context_end(zend_oparray_context *prev_context) /* {{{ */
302 {
303 	if (CG(context).brk_cont_array) {
304 		efree(CG(context).brk_cont_array);
305 		CG(context).brk_cont_array = NULL;
306 	}
307 	if (CG(context).labels) {
308 		zend_hash_destroy(CG(context).labels);
309 		FREE_HASHTABLE(CG(context).labels);
310 		CG(context).labels = NULL;
311 	}
312 	CG(context) = *prev_context;
313 }
314 /* }}} */
315 
zend_reset_import_tables(void)316 static void zend_reset_import_tables(void) /* {{{ */
317 {
318 	if (FC(imports)) {
319 		zend_hash_destroy(FC(imports));
320 		efree(FC(imports));
321 		FC(imports) = NULL;
322 	}
323 
324 	if (FC(imports_function)) {
325 		zend_hash_destroy(FC(imports_function));
326 		efree(FC(imports_function));
327 		FC(imports_function) = NULL;
328 	}
329 
330 	if (FC(imports_const)) {
331 		zend_hash_destroy(FC(imports_const));
332 		efree(FC(imports_const));
333 		FC(imports_const) = NULL;
334 	}
335 }
336 /* }}} */
337 
zend_end_namespace(void)338 static void zend_end_namespace(void) /* {{{ */ {
339 	FC(in_namespace) = 0;
340 	zend_reset_import_tables();
341 	if (FC(current_namespace)) {
342 		zend_string_release_ex(FC(current_namespace), 0);
343 		FC(current_namespace) = NULL;
344 	}
345 }
346 /* }}} */
347 
zend_file_context_begin(zend_file_context * prev_context)348 void zend_file_context_begin(zend_file_context *prev_context) /* {{{ */
349 {
350 	*prev_context = CG(file_context);
351 	FC(imports) = NULL;
352 	FC(imports_function) = NULL;
353 	FC(imports_const) = NULL;
354 	FC(current_namespace) = NULL;
355 	FC(in_namespace) = 0;
356 	FC(has_bracketed_namespaces) = 0;
357 	FC(declarables).ticks = 0;
358 	zend_hash_init(&FC(seen_symbols), 8, NULL, NULL, 0);
359 }
360 /* }}} */
361 
zend_file_context_end(zend_file_context * prev_context)362 void zend_file_context_end(zend_file_context *prev_context) /* {{{ */
363 {
364 	zend_end_namespace();
365 	zend_hash_destroy(&FC(seen_symbols));
366 	CG(file_context) = *prev_context;
367 }
368 /* }}} */
369 
zend_init_compiler_data_structures(void)370 void zend_init_compiler_data_structures(void) /* {{{ */
371 {
372 	zend_stack_init(&CG(loop_var_stack), sizeof(zend_loop_var));
373 	zend_stack_init(&CG(delayed_oplines_stack), sizeof(zend_op));
374 	zend_stack_init(&CG(short_circuiting_opnums), sizeof(uint32_t));
375 	CG(active_class_entry) = NULL;
376 	CG(in_compilation) = 0;
377 	CG(skip_shebang) = 0;
378 
379 	CG(encoding_declared) = 0;
380 	CG(memoized_exprs) = NULL;
381 	CG(memoize_mode) = 0;
382 }
383 /* }}} */
384 
zend_register_seen_symbol(zend_string * name,uint32_t kind)385 static void zend_register_seen_symbol(zend_string *name, uint32_t kind) {
386 	zval *zv = zend_hash_find(&FC(seen_symbols), name);
387 	if (zv) {
388 		Z_LVAL_P(zv) |= kind;
389 	} else {
390 		zval tmp;
391 		ZVAL_LONG(&tmp, kind);
392 		zend_hash_add_new(&FC(seen_symbols), name, &tmp);
393 	}
394 }
395 
zend_have_seen_symbol(zend_string * name,uint32_t kind)396 static bool zend_have_seen_symbol(zend_string *name, uint32_t kind) {
397 	zval *zv = zend_hash_find(&FC(seen_symbols), name);
398 	return zv && (Z_LVAL_P(zv) & kind) != 0;
399 }
400 
init_compiler(void)401 void init_compiler(void) /* {{{ */
402 {
403 	CG(arena) = zend_arena_create(64 * 1024);
404 	CG(active_op_array) = NULL;
405 	memset(&CG(context), 0, sizeof(CG(context)));
406 	zend_init_compiler_data_structures();
407 	zend_init_rsrc_list();
408 	zend_stream_init();
409 	CG(unclean_shutdown) = 0;
410 
411 	CG(delayed_variance_obligations) = NULL;
412 	CG(delayed_autoloads) = NULL;
413 	CG(unlinked_uses) = NULL;
414 	CG(current_linking_class) = NULL;
415 }
416 /* }}} */
417 
shutdown_compiler(void)418 void shutdown_compiler(void) /* {{{ */
419 {
420 	/* Reset filename before destroying the arena, as file cache may use arena allocated strings. */
421 	zend_restore_compiled_filename(NULL);
422 
423 	zend_stack_destroy(&CG(loop_var_stack));
424 	zend_stack_destroy(&CG(delayed_oplines_stack));
425 	zend_stack_destroy(&CG(short_circuiting_opnums));
426 
427 	if (CG(delayed_variance_obligations)) {
428 		zend_hash_destroy(CG(delayed_variance_obligations));
429 		FREE_HASHTABLE(CG(delayed_variance_obligations));
430 		CG(delayed_variance_obligations) = NULL;
431 	}
432 	if (CG(delayed_autoloads)) {
433 		zend_hash_destroy(CG(delayed_autoloads));
434 		FREE_HASHTABLE(CG(delayed_autoloads));
435 		CG(delayed_autoloads) = NULL;
436 	}
437 	if (CG(unlinked_uses)) {
438 		zend_hash_destroy(CG(unlinked_uses));
439 		FREE_HASHTABLE(CG(unlinked_uses));
440 		CG(unlinked_uses) = NULL;
441 	}
442 	CG(current_linking_class) = NULL;
443 }
444 /* }}} */
445 
zend_set_compiled_filename(zend_string * new_compiled_filename)446 ZEND_API zend_string *zend_set_compiled_filename(zend_string *new_compiled_filename) /* {{{ */
447 {
448 	CG(compiled_filename) = zend_string_copy(new_compiled_filename);
449 	return new_compiled_filename;
450 }
451 /* }}} */
452 
zend_restore_compiled_filename(zend_string * original_compiled_filename)453 ZEND_API void zend_restore_compiled_filename(zend_string *original_compiled_filename) /* {{{ */
454 {
455 	if (CG(compiled_filename)) {
456 		zend_string_release(CG(compiled_filename));
457 		CG(compiled_filename) = NULL;
458 	}
459 	CG(compiled_filename) = original_compiled_filename;
460 }
461 /* }}} */
462 
zend_get_compiled_filename(void)463 ZEND_API zend_string *zend_get_compiled_filename(void) /* {{{ */
464 {
465 	return CG(compiled_filename);
466 }
467 /* }}} */
468 
zend_get_compiled_lineno(void)469 ZEND_API int zend_get_compiled_lineno(void) /* {{{ */
470 {
471 	return CG(zend_lineno);
472 }
473 /* }}} */
474 
zend_is_compiling(void)475 ZEND_API bool zend_is_compiling(void) /* {{{ */
476 {
477 	return CG(in_compilation);
478 }
479 /* }}} */
480 
get_temporary_variable(void)481 static zend_always_inline uint32_t get_temporary_variable(void) /* {{{ */
482 {
483 	return (uint32_t)CG(active_op_array)->T++;
484 }
485 /* }}} */
486 
lookup_cv(zend_string * name)487 static int lookup_cv(zend_string *name) /* {{{ */{
488 	zend_op_array *op_array = CG(active_op_array);
489 	int i = 0;
490 	zend_ulong hash_value = zend_string_hash_val(name);
491 
492 	while (i < op_array->last_var) {
493 		if (ZSTR_H(op_array->vars[i]) == hash_value
494 		 && zend_string_equals(op_array->vars[i], name)) {
495 			return EX_NUM_TO_VAR(i);
496 		}
497 		i++;
498 	}
499 	i = op_array->last_var;
500 	op_array->last_var++;
501 	if (op_array->last_var > CG(context).vars_size) {
502 		CG(context).vars_size += 16; /* FIXME */
503 		op_array->vars = erealloc(op_array->vars, CG(context).vars_size * sizeof(zend_string*));
504 	}
505 
506 	op_array->vars[i] = zend_string_copy(name);
507 	return EX_NUM_TO_VAR(i);
508 }
509 /* }}} */
510 
zval_make_interned_string(zval * zv)511 zend_string *zval_make_interned_string(zval *zv)
512 {
513 	ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
514 	Z_STR_P(zv) = zend_new_interned_string(Z_STR_P(zv));
515 	if (ZSTR_IS_INTERNED(Z_STR_P(zv))) {
516 		Z_TYPE_FLAGS_P(zv) = 0;
517 	}
518 	return Z_STR_P(zv);
519 }
520 
521 /* Common part of zend_add_literal and zend_append_individual_literal */
zend_insert_literal(zend_op_array * op_array,zval * zv,int literal_position)522 static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int literal_position) /* {{{ */
523 {
524 	zval *lit = CT_CONSTANT_EX(op_array, literal_position);
525 	if (Z_TYPE_P(zv) == IS_STRING) {
526 		zval_make_interned_string(zv);
527 	}
528 	ZVAL_COPY_VALUE(lit, zv);
529 	Z_EXTRA_P(lit) = 0;
530 }
531 /* }}} */
532 
533 /* Is used while compiling a function, using the context to keep track
534    of an approximate size to avoid to relocate to often.
535    Literals are truncated to actual size in the second compiler pass (pass_two()). */
zend_add_literal(zval * zv)536 static int zend_add_literal(zval *zv) /* {{{ */
537 {
538 	zend_op_array *op_array = CG(active_op_array);
539 	int i = op_array->last_literal;
540 	op_array->last_literal++;
541 	if (i >= CG(context).literals_size) {
542 		while (i >= CG(context).literals_size) {
543 			CG(context).literals_size += 16; /* FIXME */
544 		}
545 		op_array->literals = (zval*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zval));
546 	}
547 	zend_insert_literal(op_array, zv, i);
548 	return i;
549 }
550 /* }}} */
551 
zend_add_literal_string(zend_string ** str)552 static inline int zend_add_literal_string(zend_string **str) /* {{{ */
553 {
554 	int ret;
555 	zval zv;
556 	ZVAL_STR(&zv, *str);
557 	ret = zend_add_literal(&zv);
558 	*str = Z_STR(zv);
559 	return ret;
560 }
561 /* }}} */
562 
zend_add_func_name_literal(zend_string * name)563 static int zend_add_func_name_literal(zend_string *name) /* {{{ */
564 {
565 	/* Original name */
566 	int ret = zend_add_literal_string(&name);
567 
568 	/* Lowercased name */
569 	zend_string *lc_name = zend_string_tolower(name);
570 	zend_add_literal_string(&lc_name);
571 
572 	return ret;
573 }
574 /* }}} */
575 
zend_add_ns_func_name_literal(zend_string * name)576 static int zend_add_ns_func_name_literal(zend_string *name) /* {{{ */
577 {
578 	const char *unqualified_name;
579 	size_t unqualified_name_len;
580 
581 	/* Original name */
582 	int ret = zend_add_literal_string(&name);
583 
584 	/* Lowercased name */
585 	zend_string *lc_name = zend_string_tolower(name);
586 	zend_add_literal_string(&lc_name);
587 
588 	/* Lowercased unqualified name */
589 	if (zend_get_unqualified_name(name, &unqualified_name, &unqualified_name_len)) {
590 		lc_name = zend_string_alloc(unqualified_name_len, 0);
591 		zend_str_tolower_copy(ZSTR_VAL(lc_name), unqualified_name, unqualified_name_len);
592 		zend_add_literal_string(&lc_name);
593 	}
594 
595 	return ret;
596 }
597 /* }}} */
598 
zend_add_class_name_literal(zend_string * name)599 static int zend_add_class_name_literal(zend_string *name) /* {{{ */
600 {
601 	/* Original name */
602 	int ret = zend_add_literal_string(&name);
603 
604 	/* Lowercased name */
605 	zend_string *lc_name = zend_string_tolower(name);
606 	zend_add_literal_string(&lc_name);
607 
608 	return ret;
609 }
610 /* }}} */
611 
zend_add_const_name_literal(zend_string * name,bool unqualified)612 static int zend_add_const_name_literal(zend_string *name, bool unqualified) /* {{{ */
613 {
614 	zend_string *tmp_name;
615 
616 	int ret = zend_add_literal_string(&name);
617 
618 	size_t ns_len = 0, after_ns_len = ZSTR_LEN(name);
619 	const char *after_ns = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
620 	if (after_ns) {
621 		after_ns += 1;
622 		ns_len = after_ns - ZSTR_VAL(name) - 1;
623 		after_ns_len = ZSTR_LEN(name) - ns_len - 1;
624 
625 		/* lowercased namespace name & original constant name */
626 		tmp_name = zend_string_init(ZSTR_VAL(name), ZSTR_LEN(name), 0);
627 		zend_str_tolower(ZSTR_VAL(tmp_name), ns_len);
628 		zend_add_literal_string(&tmp_name);
629 
630 		if (!unqualified) {
631 			return ret;
632 		}
633 	} else {
634 		after_ns = ZSTR_VAL(name);
635 	}
636 
637 	/* original unqualified constant name */
638 	tmp_name = zend_string_init(after_ns, after_ns_len, 0);
639 	zend_add_literal_string(&tmp_name);
640 
641 	return ret;
642 }
643 /* }}} */
644 
645 #define LITERAL_STR(op, str) do { \
646 		zval _c; \
647 		ZVAL_STR(&_c, str); \
648 		op.constant = zend_add_literal(&_c); \
649 	} while (0)
650 
zend_stop_lexing(void)651 void zend_stop_lexing(void)
652 {
653 	if (LANG_SCNG(on_event)) {
654 		LANG_SCNG(on_event)(ON_STOP, END, 0, NULL, 0, LANG_SCNG(on_event_context));
655 	}
656 
657 	LANG_SCNG(yy_cursor) = LANG_SCNG(yy_limit);
658 }
659 
zend_begin_loop(zend_uchar free_opcode,const znode * loop_var,bool is_switch)660 static inline void zend_begin_loop(
661 		zend_uchar free_opcode, const znode *loop_var, bool is_switch) /* {{{ */
662 {
663 	zend_brk_cont_element *brk_cont_element;
664 	int parent = CG(context).current_brk_cont;
665 	zend_loop_var info = {0};
666 
667 	CG(context).current_brk_cont = CG(context).last_brk_cont;
668 	brk_cont_element = get_next_brk_cont_element();
669 	brk_cont_element->parent = parent;
670 	brk_cont_element->is_switch = is_switch;
671 
672 	if (loop_var && (loop_var->op_type & (IS_VAR|IS_TMP_VAR))) {
673 		uint32_t start = get_next_op_number();
674 
675 		info.opcode = free_opcode;
676 		info.var_type = loop_var->op_type;
677 		info.var_num = loop_var->u.op.var;
678 		brk_cont_element->start = start;
679 	} else {
680 		info.opcode = ZEND_NOP;
681 		/* The start field is used to free temporary variables in case of exceptions.
682 		 * We won't try to free something of we don't have loop variable.  */
683 		brk_cont_element->start = -1;
684 	}
685 
686 	zend_stack_push(&CG(loop_var_stack), &info);
687 }
688 /* }}} */
689 
zend_end_loop(int cont_addr,const znode * var_node)690 static inline void zend_end_loop(int cont_addr, const znode *var_node) /* {{{ */
691 {
692 	uint32_t end = get_next_op_number();
693 	zend_brk_cont_element *brk_cont_element
694 		= &CG(context).brk_cont_array[CG(context).current_brk_cont];
695 	brk_cont_element->cont = cont_addr;
696 	brk_cont_element->brk = end;
697 	CG(context).current_brk_cont = brk_cont_element->parent;
698 
699 	zend_stack_del_top(&CG(loop_var_stack));
700 }
701 /* }}} */
702 
zend_do_free(znode * op1)703 static void zend_do_free(znode *op1) /* {{{ */
704 {
705 	if (op1->op_type == IS_TMP_VAR) {
706 		zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
707 
708 		while (opline->opcode == ZEND_END_SILENCE ||
709 		       opline->opcode == ZEND_OP_DATA) {
710 			opline--;
711 		}
712 
713 		if (opline->result_type == IS_TMP_VAR && opline->result.var == op1->u.op.var) {
714 			switch (opline->opcode) {
715 				case ZEND_BOOL:
716 				case ZEND_BOOL_NOT:
717 					/* boolean results don't have to be freed */
718 					return;
719 				case ZEND_POST_INC_STATIC_PROP:
720 				case ZEND_POST_DEC_STATIC_PROP:
721 				case ZEND_POST_INC_OBJ:
722 				case ZEND_POST_DEC_OBJ:
723 				case ZEND_POST_INC:
724 				case ZEND_POST_DEC:
725 					/* convert $i++ to ++$i */
726 					opline->opcode -= 2;
727 					opline->result_type = IS_UNUSED;
728 					return;
729 				case ZEND_ASSIGN:
730 				case ZEND_ASSIGN_DIM:
731 				case ZEND_ASSIGN_OBJ:
732 				case ZEND_ASSIGN_STATIC_PROP:
733 				case ZEND_ASSIGN_OP:
734 				case ZEND_ASSIGN_DIM_OP:
735 				case ZEND_ASSIGN_OBJ_OP:
736 				case ZEND_ASSIGN_STATIC_PROP_OP:
737 				case ZEND_PRE_INC_STATIC_PROP:
738 				case ZEND_PRE_DEC_STATIC_PROP:
739 				case ZEND_PRE_INC_OBJ:
740 				case ZEND_PRE_DEC_OBJ:
741 				case ZEND_PRE_INC:
742 				case ZEND_PRE_DEC:
743 					opline->result_type = IS_UNUSED;
744 					return;
745 			}
746 		}
747 
748 		zend_emit_op(NULL, ZEND_FREE, op1, NULL);
749 	} else if (op1->op_type == IS_VAR) {
750 		zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
751 		while (opline->opcode == ZEND_END_SILENCE ||
752 				opline->opcode == ZEND_EXT_FCALL_END ||
753 				opline->opcode == ZEND_OP_DATA) {
754 			opline--;
755 		}
756 		if (opline->result_type == IS_VAR
757 			&& opline->result.var == op1->u.op.var) {
758 			if (opline->opcode == ZEND_FETCH_THIS) {
759 				opline->opcode = ZEND_NOP;
760 				opline->result_type = IS_UNUSED;
761 			} else {
762 				opline->result_type = IS_UNUSED;
763 			}
764 		} else {
765 			while (opline >= CG(active_op_array)->opcodes) {
766 				if ((opline->opcode == ZEND_FETCH_LIST_R ||
767 				     opline->opcode == ZEND_FETCH_LIST_W) &&
768 				    opline->op1_type == IS_VAR &&
769 				    opline->op1.var == op1->u.op.var) {
770 					zend_emit_op(NULL, ZEND_FREE, op1, NULL);
771 					return;
772 				}
773 				if (opline->result_type == IS_VAR
774 					&& opline->result.var == op1->u.op.var) {
775 					if (opline->opcode == ZEND_NEW) {
776 						zend_emit_op(NULL, ZEND_FREE, op1, NULL);
777 					}
778 					break;
779 				}
780 				opline--;
781 			}
782 		}
783 	} else if (op1->op_type == IS_CONST) {
784 		/* Destroy value without using GC: When opcache moves arrays into SHM it will
785 		 * free the zend_array structure, so references to it from outside the op array
786 		 * become invalid. GC would cause such a reference in the root buffer. */
787 		zval_ptr_dtor_nogc(&op1->u.constant);
788 	}
789 }
790 /* }}} */
791 
zend_add_class_modifier(uint32_t flags,uint32_t new_flag)792 uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
793 {
794 	uint32_t new_flags = flags | new_flag;
795 	if ((flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flag & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
796 		zend_throw_exception(zend_ce_compile_error,
797 			"Multiple abstract modifiers are not allowed", 0);
798 		return 0;
799 	}
800 	if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
801 		zend_throw_exception(zend_ce_compile_error, "Multiple final modifiers are not allowed", 0);
802 		return 0;
803 	}
804 	if ((new_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flags & ZEND_ACC_FINAL)) {
805 		zend_throw_exception(zend_ce_compile_error,
806 			"Cannot use the final modifier on an abstract class", 0);
807 		return 0;
808 	}
809 	return new_flags;
810 }
811 /* }}} */
812 
zend_add_member_modifier(uint32_t flags,uint32_t new_flag)813 uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
814 {
815 	uint32_t new_flags = flags | new_flag;
816 	if ((flags & ZEND_ACC_PPP_MASK) && (new_flag & ZEND_ACC_PPP_MASK)) {
817 		zend_throw_exception(zend_ce_compile_error,
818 			"Multiple access type modifiers are not allowed", 0);
819 		return 0;
820 	}
821 	if ((flags & ZEND_ACC_ABSTRACT) && (new_flag & ZEND_ACC_ABSTRACT)) {
822 		zend_throw_exception(zend_ce_compile_error, "Multiple abstract modifiers are not allowed", 0);
823 		return 0;
824 	}
825 	if ((flags & ZEND_ACC_STATIC) && (new_flag & ZEND_ACC_STATIC)) {
826 		zend_throw_exception(zend_ce_compile_error, "Multiple static modifiers are not allowed", 0);
827 		return 0;
828 	}
829 	if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
830 		zend_throw_exception(zend_ce_compile_error, "Multiple final modifiers are not allowed", 0);
831 		return 0;
832 	}
833 	if ((flags & ZEND_ACC_READONLY) && (new_flag & ZEND_ACC_READONLY)) {
834 		zend_throw_exception(zend_ce_compile_error,
835 			"Multiple readonly modifiers are not allowed", 0);
836 		return 0;
837 	}
838 	if ((new_flags & ZEND_ACC_ABSTRACT) && (new_flags & ZEND_ACC_FINAL)) {
839 		zend_throw_exception(zend_ce_compile_error,
840 			"Cannot use the final modifier on an abstract class member", 0);
841 		return 0;
842 	}
843 	return new_flags;
844 }
845 /* }}} */
846 
zend_create_member_string(zend_string * class_name,zend_string * member_name)847 ZEND_API zend_string *zend_create_member_string(zend_string *class_name, zend_string *member_name) {
848 	return zend_string_concat3(
849 		ZSTR_VAL(class_name), ZSTR_LEN(class_name),
850 		"::", sizeof("::") - 1,
851 		ZSTR_VAL(member_name), ZSTR_LEN(member_name));
852 }
853 
zend_concat_names(char * name1,size_t name1_len,char * name2,size_t name2_len)854 static zend_string *zend_concat_names(char *name1, size_t name1_len, char *name2, size_t name2_len) {
855 	return zend_string_concat3(name1, name1_len, "\\", 1, name2, name2_len);
856 }
857 
zend_prefix_with_ns(zend_string * name)858 static zend_string *zend_prefix_with_ns(zend_string *name) {
859 	if (FC(current_namespace)) {
860 		zend_string *ns = FC(current_namespace);
861 		return zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
862 	} else {
863 		return zend_string_copy(name);
864 	}
865 }
866 
zend_resolve_non_class_name(zend_string * name,uint32_t type,bool * is_fully_qualified,bool case_sensitive,HashTable * current_import_sub)867 static zend_string *zend_resolve_non_class_name(
868 	zend_string *name, uint32_t type, bool *is_fully_qualified,
869 	bool case_sensitive, HashTable *current_import_sub
870 ) {
871 	char *compound;
872 	*is_fully_qualified = 0;
873 
874 	if (ZSTR_VAL(name)[0] == '\\') {
875 		/* Remove \ prefix (only relevant if this is a string rather than a label) */
876 		*is_fully_qualified = 1;
877 		return zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
878 	}
879 
880 	if (type == ZEND_NAME_FQ) {
881 		*is_fully_qualified = 1;
882 		return zend_string_copy(name);
883 	}
884 
885 	if (type == ZEND_NAME_RELATIVE) {
886 		*is_fully_qualified = 1;
887 		return zend_prefix_with_ns(name);
888 	}
889 
890 	if (current_import_sub) {
891 		/* If an unqualified name is a function/const alias, replace it. */
892 		zend_string *import_name;
893 		if (case_sensitive) {
894 			import_name = zend_hash_find_ptr(current_import_sub, name);
895 		} else {
896 			import_name = zend_hash_find_ptr_lc(current_import_sub, name);
897 		}
898 
899 		if (import_name) {
900 			*is_fully_qualified = 1;
901 			return zend_string_copy(import_name);
902 		}
903 	}
904 
905 	compound = memchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
906 	if (compound) {
907 		*is_fully_qualified = 1;
908 	}
909 
910 	if (compound && FC(imports)) {
911 		/* If the first part of a qualified name is an alias, substitute it. */
912 		size_t len = compound - ZSTR_VAL(name);
913 		zend_string *import_name = zend_hash_str_find_ptr_lc(FC(imports), ZSTR_VAL(name), len);
914 
915 		if (import_name) {
916 			return zend_concat_names(
917 				ZSTR_VAL(import_name), ZSTR_LEN(import_name), ZSTR_VAL(name) + len + 1, ZSTR_LEN(name) - len - 1);
918 		}
919 	}
920 
921 	return zend_prefix_with_ns(name);
922 }
923 /* }}} */
924 
zend_resolve_function_name(zend_string * name,uint32_t type,bool * is_fully_qualified)925 static zend_string *zend_resolve_function_name(zend_string *name, uint32_t type, bool *is_fully_qualified)
926 {
927 	return zend_resolve_non_class_name(
928 		name, type, is_fully_qualified, 0, FC(imports_function));
929 }
930 
zend_resolve_const_name(zend_string * name,uint32_t type,bool * is_fully_qualified)931 static zend_string *zend_resolve_const_name(zend_string *name, uint32_t type, bool *is_fully_qualified)
932 {
933 	return zend_resolve_non_class_name(
934 		name, type, is_fully_qualified, 1, FC(imports_const));
935 }
936 
zend_resolve_class_name(zend_string * name,uint32_t type)937 static zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
938 {
939 	char *compound;
940 
941 	if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
942 		if (type == ZEND_NAME_FQ) {
943 			zend_error_noreturn(E_COMPILE_ERROR,
944 				"'\\%s' is an invalid class name", ZSTR_VAL(name));
945 		}
946 		if (type == ZEND_NAME_RELATIVE) {
947 			zend_error_noreturn(E_COMPILE_ERROR,
948 				"'namespace\\%s' is an invalid class name", ZSTR_VAL(name));
949 		}
950 		ZEND_ASSERT(type == ZEND_NAME_NOT_FQ);
951 		return zend_string_copy(name);
952 	}
953 
954 	if (type == ZEND_NAME_RELATIVE) {
955 		return zend_prefix_with_ns(name);
956 	}
957 
958 	if (type == ZEND_NAME_FQ) {
959 		if (ZSTR_VAL(name)[0] == '\\') {
960 			/* Remove \ prefix (only relevant if this is a string rather than a label) */
961 			name = zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
962 			if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
963 				zend_error_noreturn(E_COMPILE_ERROR,
964 					"'\\%s' is an invalid class name", ZSTR_VAL(name));
965 			}
966 			return name;
967 		}
968 
969 		return zend_string_copy(name);
970 	}
971 
972 	if (FC(imports)) {
973 		compound = memchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
974 		if (compound) {
975 			/* If the first part of a qualified name is an alias, substitute it. */
976 			size_t len = compound - ZSTR_VAL(name);
977 			zend_string *import_name =
978 				zend_hash_str_find_ptr_lc(FC(imports), ZSTR_VAL(name), len);
979 
980 			if (import_name) {
981 				return zend_concat_names(
982 					ZSTR_VAL(import_name), ZSTR_LEN(import_name), ZSTR_VAL(name) + len + 1, ZSTR_LEN(name) - len - 1);
983 			}
984 		} else {
985 			/* If an unqualified name is an alias, replace it. */
986 			zend_string *import_name
987 				= zend_hash_find_ptr_lc(FC(imports), name);
988 
989 			if (import_name) {
990 				return zend_string_copy(import_name);
991 			}
992 		}
993 	}
994 
995 	/* If not fully qualified and not an alias, prepend the current namespace */
996 	return zend_prefix_with_ns(name);
997 }
998 /* }}} */
999 
zend_resolve_class_name_ast(zend_ast * ast)1000 zend_string *zend_resolve_class_name_ast(zend_ast *ast) /* {{{ */
1001 {
1002 	zval *class_name = zend_ast_get_zval(ast);
1003 	if (Z_TYPE_P(class_name) != IS_STRING) {
1004 		zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
1005 	}
1006 	return zend_resolve_class_name(Z_STR_P(class_name), ast->attr);
1007 }
1008 /* }}} */
1009 
label_ptr_dtor(zval * zv)1010 static void label_ptr_dtor(zval *zv) /* {{{ */
1011 {
1012 	efree_size(Z_PTR_P(zv), sizeof(zend_label));
1013 }
1014 /* }}} */
1015 
str_dtor(zval * zv)1016 static void str_dtor(zval *zv)  /* {{{ */ {
1017 	zend_string_release_ex(Z_STR_P(zv), 0);
1018 }
1019 /* }}} */
1020 
1021 static bool zend_is_call(zend_ast *ast);
1022 
zend_add_try_element(uint32_t try_op)1023 static uint32_t zend_add_try_element(uint32_t try_op) /* {{{ */
1024 {
1025 	zend_op_array *op_array = CG(active_op_array);
1026 	uint32_t try_catch_offset = op_array->last_try_catch++;
1027 	zend_try_catch_element *elem;
1028 
1029 	op_array->try_catch_array = safe_erealloc(
1030 		op_array->try_catch_array, sizeof(zend_try_catch_element), op_array->last_try_catch, 0);
1031 
1032 	elem = &op_array->try_catch_array[try_catch_offset];
1033 	elem->try_op = try_op;
1034 	elem->catch_op = 0;
1035 	elem->finally_op = 0;
1036 	elem->finally_end = 0;
1037 
1038 	return try_catch_offset;
1039 }
1040 /* }}} */
1041 
zend_init_static_variables_map_ptr(zend_op_array * op_array)1042 void zend_init_static_variables_map_ptr(zend_op_array *op_array)
1043 {
1044 	if (op_array->static_variables) {
1045 		ZEND_MAP_PTR_INIT(op_array->static_variables_ptr,
1046 			zend_arena_alloc(&CG(arena), sizeof(HashTable *)));
1047 		ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
1048 	}
1049 }
1050 
function_add_ref(zend_function * function)1051 ZEND_API void function_add_ref(zend_function *function) /* {{{ */
1052 {
1053 	if (function->type == ZEND_USER_FUNCTION) {
1054 		zend_op_array *op_array = &function->op_array;
1055 		if (op_array->refcount) {
1056 			(*op_array->refcount)++;
1057 		}
1058 
1059 		ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void *)));
1060 		ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
1061 
1062 		zend_init_static_variables_map_ptr(op_array);
1063 	}
1064 
1065 	if (function->common.function_name) {
1066 		zend_string_addref(function->common.function_name);
1067 	}
1068 }
1069 /* }}} */
1070 
do_bind_function_error(zend_string * lcname,zend_op_array * op_array,bool compile_time)1071 static zend_never_inline ZEND_COLD ZEND_NORETURN void do_bind_function_error(zend_string *lcname, zend_op_array *op_array, bool compile_time) /* {{{ */
1072 {
1073 	zval *zv = zend_hash_find_known_hash(compile_time ? CG(function_table) : EG(function_table), lcname);
1074 	int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
1075 	zend_function *old_function;
1076 
1077 	ZEND_ASSERT(zv != NULL);
1078 	old_function = (zend_function*)Z_PTR_P(zv);
1079 	if (old_function->type == ZEND_USER_FUNCTION
1080 		&& old_function->op_array.last > 0) {
1081 		zend_error_noreturn(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
1082 					op_array ? ZSTR_VAL(op_array->function_name) : ZSTR_VAL(old_function->common.function_name),
1083 					ZSTR_VAL(old_function->op_array.filename),
1084 					old_function->op_array.opcodes[0].lineno);
1085 	} else {
1086 		zend_error_noreturn(error_level, "Cannot redeclare %s()",
1087 			op_array ? ZSTR_VAL(op_array->function_name) : ZSTR_VAL(old_function->common.function_name));
1088 	}
1089 }
1090 
do_bind_function(zend_function * func,zval * lcname)1091 ZEND_API zend_result do_bind_function(zend_function *func, zval *lcname) /* {{{ */
1092 {
1093 	zend_function *added_func = zend_hash_add_ptr(EG(function_table), Z_STR_P(lcname), func);
1094 	if (UNEXPECTED(!added_func)) {
1095 		do_bind_function_error(Z_STR_P(lcname), &func->op_array, 0);
1096 		return FAILURE;
1097 	}
1098 
1099 	if (func->op_array.refcount) {
1100 		++*func->op_array.refcount;
1101 	}
1102 	if (func->common.function_name) {
1103 		zend_string_addref(func->common.function_name);
1104 	}
1105 	return SUCCESS;
1106 }
1107 /* }}} */
1108 
zend_bind_class_in_slot(zval * class_table_slot,zval * lcname,zend_string * lc_parent_name)1109 ZEND_API zend_class_entry *zend_bind_class_in_slot(
1110 		zval *class_table_slot, zval *lcname, zend_string *lc_parent_name)
1111 {
1112 	zend_class_entry *ce = Z_PTR_P(class_table_slot);
1113 	bool is_preloaded =
1114 		(ce->ce_flags & ZEND_ACC_PRELOADED) && !(CG(compiler_options) & ZEND_COMPILE_PRELOAD);
1115 	bool success;
1116 	if (EXPECTED(!is_preloaded)) {
1117 		success = zend_hash_set_bucket_key(EG(class_table), (Bucket*) class_table_slot, Z_STR_P(lcname)) != NULL;
1118 	} else {
1119 		/* If preloading is used, don't replace the existing bucket, add a new one. */
1120 		success = zend_hash_add_ptr(EG(class_table), Z_STR_P(lcname), ce) != NULL;
1121 	}
1122 	if (UNEXPECTED(!success)) {
1123 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
1124 		return NULL;
1125 	}
1126 
1127 	if (ce->ce_flags & ZEND_ACC_LINKED) {
1128 		return ce;
1129 	}
1130 
1131 	ce = zend_do_link_class(ce, lc_parent_name, Z_STR_P(lcname));
1132 	if (ce) {
1133 		ZEND_ASSERT(!EG(exception));
1134 		return ce;
1135 	}
1136 
1137 	if (!is_preloaded) {
1138 		/* Reload bucket pointer, the hash table may have been reallocated */
1139 		zval *zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
1140 		zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1));
1141 	} else {
1142 		zend_hash_del(EG(class_table), Z_STR_P(lcname));
1143 	}
1144 	return NULL;
1145 }
1146 
do_bind_class(zval * lcname,zend_string * lc_parent_name)1147 ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */
1148 {
1149 	zend_class_entry *ce;
1150 	zval *rtd_key, *zv;
1151 
1152 	rtd_key = lcname + 1;
1153 
1154 	zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(rtd_key));
1155 
1156 	if (UNEXPECTED(!zv)) {
1157 		ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname));
1158 		ZEND_ASSERT(ce);
1159 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
1160 		return FAILURE;
1161 	}
1162 
1163 	/* Register the derived class */
1164 	return zend_bind_class_in_slot(zv, lcname, lc_parent_name) ? SUCCESS : FAILURE;
1165 }
1166 /* }}} */
1167 
add_type_string(zend_string * type,zend_string * new_type,bool is_intersection)1168 static zend_string *add_type_string(zend_string *type, zend_string *new_type, bool is_intersection) {
1169 	zend_string *result;
1170 	if (type == NULL) {
1171 		return zend_string_copy(new_type);
1172 	}
1173 
1174 	if (is_intersection) {
1175 		result = zend_string_concat3(ZSTR_VAL(type), ZSTR_LEN(type),
1176 			"&", 1, ZSTR_VAL(new_type), ZSTR_LEN(new_type));
1177 		zend_string_release(type);
1178 	} else {
1179 		result = zend_string_concat3(
1180 			ZSTR_VAL(type), ZSTR_LEN(type), "|", 1, ZSTR_VAL(new_type), ZSTR_LEN(new_type));
1181 		zend_string_release(type);
1182 	}
1183 	return result;
1184 }
1185 
resolve_class_name(zend_string * name,zend_class_entry * scope)1186 static zend_string *resolve_class_name(zend_string *name, zend_class_entry *scope) {
1187 	if (scope) {
1188 		if (zend_string_equals_literal_ci(name, "self")) {
1189 			name = scope->name;
1190 		} else if (zend_string_equals_literal_ci(name, "parent") && scope->parent) {
1191 			name = scope->parent->name;
1192 		}
1193 	}
1194 
1195 	/* The resolved name for anonymous classes contains null bytes. Cut off everything after the
1196 	 * null byte here, to avoid larger parts of the type being omitted by printing code later. */
1197 	size_t len = strlen(ZSTR_VAL(name));
1198 	if (len != ZSTR_LEN(name)) {
1199 		ZEND_ASSERT(scope && "This should only happen with resolved types");
1200 		return zend_string_init(ZSTR_VAL(name), len, 0);
1201 	}
1202 	return zend_string_copy(name);
1203 }
1204 
zend_type_to_string_resolved(zend_type type,zend_class_entry * scope)1205 zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scope) {
1206 	zend_string *str = NULL;
1207 
1208 	if (ZEND_TYPE_HAS_LIST(type)) {
1209 		zend_type *list_type;
1210 		bool is_intersection = ZEND_TYPE_IS_INTERSECTION(type);
1211 		ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) {
1212 			zend_string *name = ZEND_TYPE_NAME(*list_type);
1213 			zend_string *resolved = resolve_class_name(name, scope);
1214 			str = add_type_string(str, resolved, is_intersection);
1215 			zend_string_release(resolved);
1216 		} ZEND_TYPE_LIST_FOREACH_END();
1217 	} else if (ZEND_TYPE_HAS_NAME(type)) {
1218 		str = resolve_class_name(ZEND_TYPE_NAME(type), scope);
1219 	}
1220 
1221 	uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
1222 
1223 	if (type_mask == MAY_BE_ANY) {
1224 		str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_MIXED), /* is_intersection */ false);
1225 
1226 		return str;
1227 	}
1228 	if (type_mask & MAY_BE_STATIC) {
1229 		zend_string *name = ZSTR_KNOWN(ZEND_STR_STATIC);
1230 		if (scope) {
1231 			zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
1232 			if (called_scope) {
1233 				name = called_scope->name;
1234 			}
1235 		}
1236 		str = add_type_string(str, name, /* is_intersection */ false);
1237 	}
1238 	if (type_mask & MAY_BE_CALLABLE) {
1239 		str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_CALLABLE), /* is_intersection */ false);
1240 	}
1241 	if (type_mask & MAY_BE_ITERABLE) {
1242 		str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_ITERABLE), /* is_intersection */ false);
1243 	}
1244 	if (type_mask & MAY_BE_OBJECT) {
1245 		str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_OBJECT), /* is_intersection */ false);
1246 	}
1247 	if (type_mask & MAY_BE_ARRAY) {
1248 		str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_ARRAY), /* is_intersection */ false);
1249 	}
1250 	if (type_mask & MAY_BE_STRING) {
1251 		str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_STRING), /* is_intersection */ false);
1252 	}
1253 	if (type_mask & MAY_BE_LONG) {
1254 		str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_INT), /* is_intersection */ false);
1255 	}
1256 	if (type_mask & MAY_BE_DOUBLE) {
1257 		str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_FLOAT), /* is_intersection */ false);
1258 	}
1259 	if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL) {
1260 		str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_BOOL), /* is_intersection */ false);
1261 	} else if (type_mask & MAY_BE_FALSE) {
1262 		str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_FALSE), /* is_intersection */ false);
1263 	}
1264 	if (type_mask & MAY_BE_VOID) {
1265 		str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_VOID), /* is_intersection */ false);
1266 	}
1267 	if (type_mask & MAY_BE_NEVER) {
1268 		str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_NEVER), /* is_intersection */ false);
1269 	}
1270 
1271 	if (type_mask & MAY_BE_NULL) {
1272 		bool is_union = !str || memchr(ZSTR_VAL(str), '|', ZSTR_LEN(str)) != NULL;
1273 		if (!is_union) {
1274 			zend_string *nullable_str = zend_string_concat2("?", 1, ZSTR_VAL(str), ZSTR_LEN(str));
1275 			zend_string_release(str);
1276 			return nullable_str;
1277 		}
1278 
1279 		str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_NULL_LOWERCASE), /* is_intersection */ false);
1280 	}
1281 	return str;
1282 }
1283 
zend_type_to_string(zend_type type)1284 ZEND_API zend_string *zend_type_to_string(zend_type type) {
1285 	return zend_type_to_string_resolved(type, NULL);
1286 }
1287 
is_generator_compatible_class_type(zend_string * name)1288 static bool is_generator_compatible_class_type(zend_string *name) {
1289 	return zend_string_equals_literal_ci(name, "Traversable")
1290 		|| zend_string_equals_literal_ci(name, "Iterator")
1291 		|| zend_string_equals_literal_ci(name, "Generator");
1292 }
1293 
zend_mark_function_as_generator(void)1294 static void zend_mark_function_as_generator(void) /* {{{ */
1295 {
1296 	if (!CG(active_op_array)->function_name) {
1297 		zend_error_noreturn(E_COMPILE_ERROR,
1298 			"The \"yield\" expression can only be used inside a function");
1299 	}
1300 
1301 	if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
1302 		zend_type return_type = CG(active_op_array)->arg_info[-1].type;
1303 		bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & (MAY_BE_ITERABLE | MAY_BE_OBJECT)) != 0;
1304 		if (!valid_type) {
1305 			zend_type *single_type;
1306 			ZEND_TYPE_FOREACH(return_type, single_type) {
1307 				if (ZEND_TYPE_HAS_NAME(*single_type)
1308 						&& is_generator_compatible_class_type(ZEND_TYPE_NAME(*single_type))) {
1309 					valid_type = 1;
1310 					break;
1311 				}
1312 			} ZEND_TYPE_FOREACH_END();
1313 		}
1314 
1315 		if (!valid_type) {
1316 			zend_string *str = zend_type_to_string(return_type);
1317 			zend_error_noreturn(E_COMPILE_ERROR,
1318 				"Generator return type must be a supertype of Generator, %s given",
1319 				ZSTR_VAL(str));
1320 		}
1321 	}
1322 
1323 	CG(active_op_array)->fn_flags |= ZEND_ACC_GENERATOR;
1324 }
1325 /* }}} */
1326 
zend_build_delayed_early_binding_list(const zend_op_array * op_array)1327 ZEND_API uint32_t zend_build_delayed_early_binding_list(const zend_op_array *op_array) /* {{{ */
1328 {
1329 	if (op_array->fn_flags & ZEND_ACC_EARLY_BINDING) {
1330 		uint32_t  first_early_binding_opline = (uint32_t)-1;
1331 		uint32_t *prev_opline_num = &first_early_binding_opline;
1332 		zend_op  *opline = op_array->opcodes;
1333 		zend_op  *end = opline + op_array->last;
1334 
1335 		while (opline < end) {
1336 			if (opline->opcode == ZEND_DECLARE_CLASS_DELAYED) {
1337 				*prev_opline_num = opline - op_array->opcodes;
1338 				prev_opline_num = &opline->result.opline_num;
1339 			}
1340 			++opline;
1341 		}
1342 		*prev_opline_num = -1;
1343 		return first_early_binding_opline;
1344 	}
1345 	return (uint32_t)-1;
1346 }
1347 /* }}} */
1348 
zend_do_delayed_early_binding(zend_op_array * op_array,uint32_t first_early_binding_opline)1349 ZEND_API void zend_do_delayed_early_binding(zend_op_array *op_array, uint32_t first_early_binding_opline) /* {{{ */
1350 {
1351 	if (first_early_binding_opline != (uint32_t)-1) {
1352 		bool orig_in_compilation = CG(in_compilation);
1353 		uint32_t opline_num = first_early_binding_opline;
1354 		void **run_time_cache;
1355 
1356 		if (!ZEND_MAP_PTR(op_array->run_time_cache)) {
1357 			void *ptr;
1358 
1359 			ZEND_ASSERT(op_array->fn_flags & ZEND_ACC_HEAP_RT_CACHE);
1360 			ptr = emalloc(op_array->cache_size + sizeof(void*));
1361 			ZEND_MAP_PTR_INIT(op_array->run_time_cache, ptr);
1362 			ptr = (char*)ptr + sizeof(void*);
1363 			ZEND_MAP_PTR_SET(op_array->run_time_cache, ptr);
1364 			memset(ptr, 0, op_array->cache_size);
1365 		}
1366 		run_time_cache = RUN_TIME_CACHE(op_array);
1367 
1368 		CG(in_compilation) = 1;
1369 		while (opline_num != (uint32_t)-1) {
1370 			const zend_op *opline = &op_array->opcodes[opline_num];
1371 			zval *lcname = RT_CONSTANT(opline, opline->op1);
1372 			zval *zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(lcname + 1));
1373 
1374 			if (zv) {
1375 				zend_class_entry *ce = Z_CE_P(zv);
1376 				zend_string *lc_parent_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
1377 				zend_class_entry *parent_ce = zend_hash_find_ex_ptr(EG(class_table), lc_parent_name, 1);
1378 
1379 				if (parent_ce) {
1380 					ce = zend_try_early_bind(ce, parent_ce, Z_STR_P(lcname), zv);
1381 					if (ce) {
1382 						/* Store in run-time cache */
1383 						((void**)((char*)run_time_cache + opline->extended_value))[0] = ce;
1384 					}
1385 				}
1386 			}
1387 			opline_num = op_array->opcodes[opline_num].result.opline_num;
1388 		}
1389 		CG(in_compilation) = orig_in_compilation;
1390 	}
1391 }
1392 /* }}} */
1393 
zend_mangle_property_name(const char * src1,size_t src1_length,const char * src2,size_t src2_length,bool internal)1394 ZEND_API zend_string *zend_mangle_property_name(const char *src1, size_t src1_length, const char *src2, size_t src2_length, bool internal) /* {{{ */
1395 {
1396 	size_t prop_name_length = 1 + src1_length + 1 + src2_length;
1397 	zend_string *prop_name = zend_string_alloc(prop_name_length, internal);
1398 
1399 	ZSTR_VAL(prop_name)[0] = '\0';
1400 	memcpy(ZSTR_VAL(prop_name) + 1, src1, src1_length+1);
1401 	memcpy(ZSTR_VAL(prop_name) + 1 + src1_length + 1, src2, src2_length+1);
1402 	return prop_name;
1403 }
1404 /* }}} */
1405 
zend_strnlen(const char * s,size_t maxlen)1406 static zend_always_inline size_t zend_strnlen(const char* s, size_t maxlen) /* {{{ */
1407 {
1408 	size_t len = 0;
1409 	while (*s++ && maxlen--) len++;
1410 	return len;
1411 }
1412 /* }}} */
1413 
zend_unmangle_property_name_ex(const zend_string * name,const char ** class_name,const char ** prop_name,size_t * prop_len)1414 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) /* {{{ */
1415 {
1416 	size_t class_name_len;
1417 	size_t anonclass_src_len;
1418 
1419 	*class_name = NULL;
1420 
1421 	if (!ZSTR_LEN(name) || ZSTR_VAL(name)[0] != '\0') {
1422 		*prop_name = ZSTR_VAL(name);
1423 		if (prop_len) {
1424 			*prop_len = ZSTR_LEN(name);
1425 		}
1426 		return SUCCESS;
1427 	}
1428 	if (ZSTR_LEN(name) < 3 || ZSTR_VAL(name)[1] == '\0') {
1429 		zend_error(E_NOTICE, "Illegal member variable name");
1430 		*prop_name = ZSTR_VAL(name);
1431 		if (prop_len) {
1432 			*prop_len = ZSTR_LEN(name);
1433 		}
1434 		return FAILURE;
1435 	}
1436 
1437 	class_name_len = zend_strnlen(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 2);
1438 	if (class_name_len >= ZSTR_LEN(name) - 2 || ZSTR_VAL(name)[class_name_len + 1] != '\0') {
1439 		zend_error(E_NOTICE, "Corrupt member variable name");
1440 		*prop_name = ZSTR_VAL(name);
1441 		if (prop_len) {
1442 			*prop_len = ZSTR_LEN(name);
1443 		}
1444 		return FAILURE;
1445 	}
1446 
1447 	*class_name = ZSTR_VAL(name) + 1;
1448 	anonclass_src_len = zend_strnlen(*class_name + class_name_len + 1, ZSTR_LEN(name) - class_name_len - 2);
1449 	if (class_name_len + anonclass_src_len + 2 != ZSTR_LEN(name)) {
1450 		class_name_len += anonclass_src_len + 1;
1451 	}
1452 	*prop_name = ZSTR_VAL(name) + class_name_len + 2;
1453 	if (prop_len) {
1454 		*prop_len = ZSTR_LEN(name) - class_name_len - 2;
1455 	}
1456 	return SUCCESS;
1457 }
1458 /* }}} */
1459 
can_ct_eval_const(zend_constant * c)1460 static bool can_ct_eval_const(zend_constant *c) {
1461 	if (ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED) {
1462 		return 0;
1463 	}
1464 	if ((ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)
1465 			&& !(CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION)
1466 			&& !((ZEND_CONSTANT_FLAGS(c) & CONST_NO_FILE_CACHE)
1467 				&& (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) {
1468 		return 1;
1469 	}
1470 	if (Z_TYPE(c->value) < IS_OBJECT
1471 			&& !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
1472 		return 1;
1473 	}
1474 	return 0;
1475 }
1476 
zend_try_ct_eval_const(zval * zv,zend_string * name,bool is_fully_qualified)1477 static bool zend_try_ct_eval_const(zval *zv, zend_string *name, bool is_fully_qualified) /* {{{ */
1478 {
1479 	/* Substitute true, false and null (including unqualified usage in namespaces)
1480 	 * before looking up the possibly namespaced name. */
1481 	const char *lookup_name = ZSTR_VAL(name);
1482 	size_t lookup_len = ZSTR_LEN(name);
1483 
1484 	if (!is_fully_qualified) {
1485 		zend_get_unqualified_name(name, &lookup_name, &lookup_len);
1486 	}
1487 
1488 	zend_constant *c;
1489 	if ((c = zend_get_special_const(lookup_name, lookup_len))) {
1490 		ZVAL_COPY_VALUE(zv, &c->value);
1491 		return 1;
1492 	}
1493 	c = zend_hash_find_ptr(EG(zend_constants), name);
1494 	if (c && can_ct_eval_const(c)) {
1495 		ZVAL_COPY_OR_DUP(zv, &c->value);
1496 		return 1;
1497 	}
1498 	return 0;
1499 }
1500 /* }}} */
1501 
zend_is_scope_known(void)1502 static inline bool zend_is_scope_known(void) /* {{{ */
1503 {
1504 	if (!CG(active_op_array)) {
1505 		/* This can only happen when evaluating a default value string. */
1506 		return 0;
1507 	}
1508 
1509 	if (CG(active_op_array)->fn_flags & ZEND_ACC_CLOSURE) {
1510 		/* Closures can be rebound to a different scope */
1511 		return 0;
1512 	}
1513 
1514 	if (!CG(active_class_entry)) {
1515 		/* The scope is known if we're in a free function (no scope), but not if we're in
1516 		 * a file/eval (which inherits including/eval'ing scope). */
1517 		return CG(active_op_array)->function_name != NULL;
1518 	}
1519 
1520 	/* For traits self etc refers to the using class, not the trait itself */
1521 	return (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == 0;
1522 }
1523 /* }}} */
1524 
class_name_refers_to_active_ce(zend_string * class_name,uint32_t fetch_type)1525 static inline bool class_name_refers_to_active_ce(zend_string *class_name, uint32_t fetch_type) /* {{{ */
1526 {
1527 	if (!CG(active_class_entry)) {
1528 		return 0;
1529 	}
1530 	if (fetch_type == ZEND_FETCH_CLASS_SELF && zend_is_scope_known()) {
1531 		return 1;
1532 	}
1533 	return fetch_type == ZEND_FETCH_CLASS_DEFAULT
1534 		&& zend_string_equals_ci(class_name, CG(active_class_entry)->name);
1535 }
1536 /* }}} */
1537 
zend_get_class_fetch_type(zend_string * name)1538 uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ */
1539 {
1540 	if (zend_string_equals_literal_ci(name, "self")) {
1541 		return ZEND_FETCH_CLASS_SELF;
1542 	} else if (zend_string_equals_literal_ci(name, "parent")) {
1543 		return ZEND_FETCH_CLASS_PARENT;
1544 	} else if (zend_string_equals_literal_ci(name, "static")) {
1545 		return ZEND_FETCH_CLASS_STATIC;
1546 	} else {
1547 		return ZEND_FETCH_CLASS_DEFAULT;
1548 	}
1549 }
1550 /* }}} */
1551 
zend_get_class_fetch_type_ast(zend_ast * name_ast)1552 static uint32_t zend_get_class_fetch_type_ast(zend_ast *name_ast) /* {{{ */
1553 {
1554 	/* Fully qualified names are always default refs */
1555 	if (name_ast->attr == ZEND_NAME_FQ) {
1556 		return ZEND_FETCH_CLASS_DEFAULT;
1557 	}
1558 
1559 	return zend_get_class_fetch_type(zend_ast_get_str(name_ast));
1560 }
1561 /* }}} */
1562 
zend_resolve_const_class_name_reference(zend_ast * ast,const char * type)1563 static zend_string *zend_resolve_const_class_name_reference(zend_ast *ast, const char *type)
1564 {
1565 	zend_string *class_name = zend_ast_get_str(ast);
1566 	if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type_ast(ast)) {
1567 		zend_error_noreturn(E_COMPILE_ERROR,
1568 			"Cannot use '%s' as %s, as it is reserved",
1569 			ZSTR_VAL(class_name), type);
1570 	}
1571 	return zend_resolve_class_name(class_name, ast->attr);
1572 }
1573 
zend_ensure_valid_class_fetch_type(uint32_t fetch_type)1574 static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
1575 {
1576 	if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && zend_is_scope_known()) {
1577 		zend_class_entry *ce = CG(active_class_entry);
1578 		if (!ce) {
1579 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"%s\" when no class scope is active",
1580 				fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
1581 				fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
1582 		} else if (fetch_type == ZEND_FETCH_CLASS_PARENT && !ce->parent_name) {
1583 			zend_error_noreturn(E_COMPILE_ERROR,
1584 				"Cannot use \"parent\" when current class scope has no parent");
1585 		}
1586 	}
1587 }
1588 /* }}} */
1589 
zend_try_compile_const_expr_resolve_class_name(zval * zv,zend_ast * class_ast)1590 static bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast) /* {{{ */
1591 {
1592 	uint32_t fetch_type;
1593 	zval *class_name;
1594 
1595 	if (class_ast->kind != ZEND_AST_ZVAL) {
1596 		return 0;
1597 	}
1598 
1599 	class_name = zend_ast_get_zval(class_ast);
1600 
1601 	if (Z_TYPE_P(class_name) != IS_STRING) {
1602 		zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
1603 	}
1604 
1605 	fetch_type = zend_get_class_fetch_type(Z_STR_P(class_name));
1606 	zend_ensure_valid_class_fetch_type(fetch_type);
1607 
1608 	switch (fetch_type) {
1609 		case ZEND_FETCH_CLASS_SELF:
1610 			if (CG(active_class_entry) && zend_is_scope_known()) {
1611 				ZVAL_STR_COPY(zv, CG(active_class_entry)->name);
1612 				return 1;
1613 			}
1614 			return 0;
1615 		case ZEND_FETCH_CLASS_PARENT:
1616 			if (CG(active_class_entry) && CG(active_class_entry)->parent_name
1617 					&& zend_is_scope_known()) {
1618 				ZVAL_STR_COPY(zv, CG(active_class_entry)->parent_name);
1619 				return 1;
1620 			}
1621 			return 0;
1622 		case ZEND_FETCH_CLASS_STATIC:
1623 			return 0;
1624 		case ZEND_FETCH_CLASS_DEFAULT:
1625 			ZVAL_STR(zv, zend_resolve_class_name_ast(class_ast));
1626 			return 1;
1627 		EMPTY_SWITCH_DEFAULT_CASE()
1628 	}
1629 }
1630 /* }}} */
1631 
1632 /* We don't use zend_verify_const_access because we need to deal with unlinked classes. */
zend_verify_ct_const_access(zend_class_constant * c,zend_class_entry * scope)1633 static bool zend_verify_ct_const_access(zend_class_constant *c, zend_class_entry *scope)
1634 {
1635 	if (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_PUBLIC) {
1636 		return 1;
1637 	} else if (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_PRIVATE) {
1638 		return c->ce == scope;
1639 	} else {
1640 		zend_class_entry *ce = c->ce;
1641 		while (1) {
1642 			if (ce == scope) {
1643 				return 1;
1644 			}
1645 			if (!ce->parent) {
1646 				break;
1647 			}
1648 			if (ce->ce_flags & ZEND_ACC_RESOLVED_PARENT) {
1649 				ce = ce->parent;
1650 			} else {
1651 				ce = zend_hash_find_ptr_lc(CG(class_table), ce->parent_name);
1652 				if (!ce) {
1653 					break;
1654 				}
1655 			}
1656 		}
1657 		/* Reverse case cannot be true during compilation */
1658 		return 0;
1659 	}
1660 }
1661 
zend_try_ct_eval_class_const(zval * zv,zend_string * class_name,zend_string * name)1662 static bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend_string *name) /* {{{ */
1663 {
1664 	uint32_t fetch_type = zend_get_class_fetch_type(class_name);
1665 	zend_class_constant *cc;
1666 	zval *c;
1667 
1668 	if (class_name_refers_to_active_ce(class_name, fetch_type)) {
1669 		cc = zend_hash_find_ptr(&CG(active_class_entry)->constants_table, name);
1670 	} else if (fetch_type == ZEND_FETCH_CLASS_DEFAULT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
1671 		zend_class_entry *ce = zend_hash_find_ptr_lc(CG(class_table), class_name);
1672 		if (ce) {
1673 			cc = zend_hash_find_ptr(&ce->constants_table, name);
1674 		} else {
1675 			return 0;
1676 		}
1677 	} else {
1678 		return 0;
1679 	}
1680 
1681 	if (CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION) {
1682 		return 0;
1683 	}
1684 
1685 	if (!cc || !zend_verify_ct_const_access(cc, CG(active_class_entry))) {
1686 		return 0;
1687 	}
1688 
1689 	c = &cc->value;
1690 
1691 	/* Substitute case-sensitive (or lowercase) persistent class constants */
1692 	if (Z_TYPE_P(c) < IS_OBJECT) {
1693 		ZVAL_COPY_OR_DUP(zv, c);
1694 		return 1;
1695 	}
1696 
1697 	return 0;
1698 }
1699 /* }}} */
1700 
zend_add_to_list(void * result,void * item)1701 static void zend_add_to_list(void *result, void *item) /* {{{ */
1702 {
1703 	void** list = *(void**)result;
1704 	size_t n = 0;
1705 
1706 	if (list) {
1707 		while (list[n]) {
1708 			n++;
1709 		}
1710 	}
1711 
1712 	list = erealloc(list, sizeof(void*) * (n+2));
1713 
1714 	list[n]   = item;
1715 	list[n+1] = NULL;
1716 
1717 	*(void**)result = list;
1718 }
1719 /* }}} */
1720 
zend_do_extended_stmt(void)1721 static void zend_do_extended_stmt(void) /* {{{ */
1722 {
1723 	zend_op *opline;
1724 
1725 	if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_STMT)) {
1726 		return;
1727 	}
1728 
1729 	opline = get_next_op();
1730 
1731 	opline->opcode = ZEND_EXT_STMT;
1732 }
1733 /* }}} */
1734 
zend_do_extended_fcall_begin(void)1735 static void zend_do_extended_fcall_begin(void) /* {{{ */
1736 {
1737 	zend_op *opline;
1738 
1739 	if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_FCALL)) {
1740 		return;
1741 	}
1742 
1743 	opline = get_next_op();
1744 
1745 	opline->opcode = ZEND_EXT_FCALL_BEGIN;
1746 }
1747 /* }}} */
1748 
zend_do_extended_fcall_end(void)1749 static void zend_do_extended_fcall_end(void) /* {{{ */
1750 {
1751 	zend_op *opline;
1752 
1753 	if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_FCALL)) {
1754 		return;
1755 	}
1756 
1757 	opline = get_next_op();
1758 
1759 	opline->opcode = ZEND_EXT_FCALL_END;
1760 }
1761 /* }}} */
1762 
zend_is_auto_global_str(const char * name,size_t len)1763 ZEND_API bool zend_is_auto_global_str(const char *name, size_t len) /* {{{ */ {
1764 	zend_auto_global *auto_global;
1765 
1766 	if ((auto_global = zend_hash_str_find_ptr(CG(auto_globals), name, len)) != NULL) {
1767 		if (auto_global->armed) {
1768 			auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1769 		}
1770 		return 1;
1771 	}
1772 	return 0;
1773 }
1774 /* }}} */
1775 
zend_is_auto_global(zend_string * name)1776 ZEND_API bool zend_is_auto_global(zend_string *name) /* {{{ */
1777 {
1778 	zend_auto_global *auto_global;
1779 
1780 	if ((auto_global = zend_hash_find_ptr(CG(auto_globals), name)) != NULL) {
1781 		if (auto_global->armed) {
1782 			auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1783 		}
1784 		return 1;
1785 	}
1786 	return 0;
1787 }
1788 /* }}} */
1789 
zend_register_auto_global(zend_string * name,bool jit,zend_auto_global_callback auto_global_callback)1790 ZEND_API zend_result zend_register_auto_global(zend_string *name, bool jit, zend_auto_global_callback auto_global_callback) /* {{{ */
1791 {
1792 	zend_auto_global auto_global;
1793 	zend_result retval;
1794 
1795 	auto_global.name = name;
1796 	auto_global.auto_global_callback = auto_global_callback;
1797 	auto_global.jit = jit;
1798 
1799 	retval = zend_hash_add_mem(CG(auto_globals), auto_global.name, &auto_global, sizeof(zend_auto_global)) != NULL ? SUCCESS : FAILURE;
1800 
1801 	return retval;
1802 }
1803 /* }}} */
1804 
zend_activate_auto_globals(void)1805 ZEND_API void zend_activate_auto_globals(void) /* {{{ */
1806 {
1807 	zend_auto_global *auto_global;
1808 
1809 	ZEND_HASH_FOREACH_PTR(CG(auto_globals), auto_global) {
1810 		if (auto_global->jit) {
1811 			auto_global->armed = 1;
1812 		} else if (auto_global->auto_global_callback) {
1813 			auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1814 		} else {
1815 			auto_global->armed = 0;
1816 		}
1817 	} ZEND_HASH_FOREACH_END();
1818 }
1819 /* }}} */
1820 
zendlex(zend_parser_stack_elem * elem)1821 int ZEND_FASTCALL zendlex(zend_parser_stack_elem *elem) /* {{{ */
1822 {
1823 	zval zv;
1824 	int ret;
1825 
1826 	if (CG(increment_lineno)) {
1827 		CG(zend_lineno)++;
1828 		CG(increment_lineno) = 0;
1829 	}
1830 
1831 	ret = lex_scan(&zv, elem);
1832 	ZEND_ASSERT(!EG(exception) || ret == T_ERROR);
1833 	return ret;
1834 
1835 }
1836 /* }}} */
1837 
zend_initialize_class_data(zend_class_entry * ce,bool nullify_handlers)1838 ZEND_API void zend_initialize_class_data(zend_class_entry *ce, bool nullify_handlers) /* {{{ */
1839 {
1840 	bool persistent_hashes = ce->type == ZEND_INTERNAL_CLASS;
1841 
1842 	ce->refcount = 1;
1843 	ce->ce_flags = ZEND_ACC_CONSTANTS_UPDATED;
1844 
1845 	if (CG(compiler_options) & ZEND_COMPILE_GUARDS) {
1846 		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
1847 	}
1848 
1849 	ce->default_properties_table = NULL;
1850 	ce->default_static_members_table = NULL;
1851 	zend_hash_init(&ce->properties_info, 8, NULL, NULL, persistent_hashes);
1852 	zend_hash_init(&ce->constants_table, 8, NULL, NULL, persistent_hashes);
1853 	zend_hash_init(&ce->function_table, 8, NULL, ZEND_FUNCTION_DTOR, persistent_hashes);
1854 
1855 	if (ce->type == ZEND_USER_CLASS) {
1856 		ce->info.user.doc_comment = NULL;
1857 	}
1858 	ZEND_MAP_PTR_INIT(ce->static_members_table, NULL);
1859 	ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
1860 
1861 	ce->default_properties_count = 0;
1862 	ce->default_static_members_count = 0;
1863 	ce->properties_info_table = NULL;
1864 	ce->attributes = NULL;
1865 	ce->enum_backing_type = IS_UNDEF;
1866 	ce->backed_enum_table = NULL;
1867 
1868 	if (nullify_handlers) {
1869 		ce->constructor = NULL;
1870 		ce->destructor = NULL;
1871 		ce->clone = NULL;
1872 		ce->__get = NULL;
1873 		ce->__set = NULL;
1874 		ce->__unset = NULL;
1875 		ce->__isset = NULL;
1876 		ce->__call = NULL;
1877 		ce->__callstatic = NULL;
1878 		ce->__tostring = NULL;
1879 		ce->__serialize = NULL;
1880 		ce->__unserialize = NULL;
1881 		ce->__debugInfo = NULL;
1882 		ce->create_object = NULL;
1883 		ce->get_iterator = NULL;
1884 		ce->iterator_funcs_ptr = NULL;
1885 		ce->get_static_method = NULL;
1886 		ce->parent = NULL;
1887 		ce->parent_name = NULL;
1888 		ce->num_interfaces = 0;
1889 		ce->interfaces = NULL;
1890 		ce->num_traits = 0;
1891 		ce->trait_names = NULL;
1892 		ce->trait_aliases = NULL;
1893 		ce->trait_precedences = NULL;
1894 		ce->serialize = NULL;
1895 		ce->unserialize = NULL;
1896 		if (ce->type == ZEND_INTERNAL_CLASS) {
1897 			ce->info.internal.module = NULL;
1898 			ce->info.internal.builtin_functions = NULL;
1899 		}
1900 	}
1901 }
1902 /* }}} */
1903 
zend_get_compiled_variable_name(const zend_op_array * op_array,uint32_t var)1904 ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, uint32_t var) /* {{{ */
1905 {
1906 	return op_array->vars[EX_VAR_TO_NUM(var)];
1907 }
1908 /* }}} */
1909 
zend_ast_append_str(zend_ast * left_ast,zend_ast * right_ast)1910 zend_ast *zend_ast_append_str(zend_ast *left_ast, zend_ast *right_ast) /* {{{ */
1911 {
1912 	zval *left_zv = zend_ast_get_zval(left_ast);
1913 	zend_string *left = Z_STR_P(left_zv);
1914 	zend_string *right = zend_ast_get_str(right_ast);
1915 
1916 	zend_string *result;
1917 	size_t left_len = ZSTR_LEN(left);
1918 	size_t len = left_len + ZSTR_LEN(right) + 1; /* left\right */
1919 
1920 	result = zend_string_extend(left, len, 0);
1921 	ZSTR_VAL(result)[left_len] = '\\';
1922 	memcpy(&ZSTR_VAL(result)[left_len + 1], ZSTR_VAL(right), ZSTR_LEN(right));
1923 	ZSTR_VAL(result)[len] = '\0';
1924 	zend_string_release_ex(right, 0);
1925 
1926 	ZVAL_STR(left_zv, result);
1927 	return left_ast;
1928 }
1929 /* }}} */
1930 
zend_negate_num_string(zend_ast * ast)1931 zend_ast *zend_negate_num_string(zend_ast *ast) /* {{{ */
1932 {
1933 	zval *zv = zend_ast_get_zval(ast);
1934 	if (Z_TYPE_P(zv) == IS_LONG) {
1935 		if (Z_LVAL_P(zv) == 0) {
1936 			ZVAL_NEW_STR(zv, zend_string_init("-0", sizeof("-0")-1, 0));
1937 		} else {
1938 			ZEND_ASSERT(Z_LVAL_P(zv) > 0);
1939 			Z_LVAL_P(zv) *= -1;
1940 		}
1941 	} else if (Z_TYPE_P(zv) == IS_STRING) {
1942 		size_t orig_len = Z_STRLEN_P(zv);
1943 		Z_STR_P(zv) = zend_string_extend(Z_STR_P(zv), orig_len + 1, 0);
1944 		memmove(Z_STRVAL_P(zv) + 1, Z_STRVAL_P(zv), orig_len + 1);
1945 		Z_STRVAL_P(zv)[0] = '-';
1946 	} else {
1947 		ZEND_UNREACHABLE();
1948 	}
1949 	return ast;
1950 }
1951 /* }}} */
1952 
zend_verify_namespace(void)1953 static void zend_verify_namespace(void) /* {{{ */
1954 {
1955 	if (FC(has_bracketed_namespaces) && !FC(in_namespace)) {
1956 		zend_error_noreturn(E_COMPILE_ERROR, "No code may exist outside of namespace {}");
1957 	}
1958 }
1959 /* }}} */
1960 
1961 /* {{{ zend_dirname
1962    Returns directory name component of path */
zend_dirname(char * path,size_t len)1963 ZEND_API size_t zend_dirname(char *path, size_t len)
1964 {
1965 	char *end = path + len - 1;
1966 	unsigned int len_adjust = 0;
1967 
1968 #ifdef ZEND_WIN32
1969 	/* Note that on Win32 CWD is per drive (heritage from CP/M).
1970 	 * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
1971 	 */
1972 	if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
1973 		/* Skip over the drive spec (if any) so as not to change */
1974 		path += 2;
1975 		len_adjust += 2;
1976 		if (2 == len) {
1977 			/* Return "c:" on Win32 for dirname("c:").
1978 			 * It would be more consistent to return "c:."
1979 			 * but that would require making the string *longer*.
1980 			 */
1981 			return len;
1982 		}
1983 	}
1984 #endif
1985 
1986 	if (len == 0) {
1987 		/* Illegal use of this function */
1988 		return 0;
1989 	}
1990 
1991 	/* Strip trailing slashes */
1992 	while (end >= path && IS_SLASH_P(end)) {
1993 		end--;
1994 	}
1995 	if (end < path) {
1996 		/* The path only contained slashes */
1997 		path[0] = DEFAULT_SLASH;
1998 		path[1] = '\0';
1999 		return 1 + len_adjust;
2000 	}
2001 
2002 	/* Strip filename */
2003 	while (end >= path && !IS_SLASH_P(end)) {
2004 		end--;
2005 	}
2006 	if (end < path) {
2007 		/* No slash found, therefore return '.' */
2008 		path[0] = '.';
2009 		path[1] = '\0';
2010 		return 1 + len_adjust;
2011 	}
2012 
2013 	/* Strip slashes which came before the file name */
2014 	while (end >= path && IS_SLASH_P(end)) {
2015 		end--;
2016 	}
2017 	if (end < path) {
2018 		path[0] = DEFAULT_SLASH;
2019 		path[1] = '\0';
2020 		return 1 + len_adjust;
2021 	}
2022 	*(end+1) = '\0';
2023 
2024 	return (size_t)(end + 1 - path) + len_adjust;
2025 }
2026 /* }}} */
2027 
zend_adjust_for_fetch_type(zend_op * opline,znode * result,uint32_t type)2028 static void zend_adjust_for_fetch_type(zend_op *opline, znode *result, uint32_t type) /* {{{ */
2029 {
2030 	zend_uchar factor = (opline->opcode == ZEND_FETCH_STATIC_PROP_R) ? 1 : 3;
2031 
2032 	switch (type) {
2033 		case BP_VAR_R:
2034 			opline->result_type = IS_TMP_VAR;
2035 			result->op_type = IS_TMP_VAR;
2036 			return;
2037 		case BP_VAR_W:
2038 			opline->opcode += 1 * factor;
2039 			return;
2040 		case BP_VAR_RW:
2041 			opline->opcode += 2 * factor;
2042 			return;
2043 		case BP_VAR_IS:
2044 			opline->result_type = IS_TMP_VAR;
2045 			result->op_type = IS_TMP_VAR;
2046 			opline->opcode += 3 * factor;
2047 			return;
2048 		case BP_VAR_FUNC_ARG:
2049 			opline->opcode += 4 * factor;
2050 			return;
2051 		case BP_VAR_UNSET:
2052 			opline->opcode += 5 * factor;
2053 			return;
2054 		EMPTY_SWITCH_DEFAULT_CASE()
2055 	}
2056 }
2057 /* }}} */
2058 
zend_make_var_result(znode * result,zend_op * opline)2059 static inline void zend_make_var_result(znode *result, zend_op *opline) /* {{{ */
2060 {
2061 	opline->result_type = IS_VAR;
2062 	opline->result.var = get_temporary_variable();
2063 	GET_NODE(result, opline->result);
2064 }
2065 /* }}} */
2066 
zend_make_tmp_result(znode * result,zend_op * opline)2067 static inline void zend_make_tmp_result(znode *result, zend_op *opline) /* {{{ */
2068 {
2069 	opline->result_type = IS_TMP_VAR;
2070 	opline->result.var = get_temporary_variable();
2071 	GET_NODE(result, opline->result);
2072 }
2073 /* }}} */
2074 
zend_emit_op(znode * result,zend_uchar opcode,znode * op1,znode * op2)2075 static zend_op *zend_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2) /* {{{ */
2076 {
2077 	zend_op *opline = get_next_op();
2078 	opline->opcode = opcode;
2079 
2080 	if (op1 != NULL) {
2081 		SET_NODE(opline->op1, op1);
2082 	}
2083 
2084 	if (op2 != NULL) {
2085 		SET_NODE(opline->op2, op2);
2086 	}
2087 
2088 	if (result) {
2089 		zend_make_var_result(result, opline);
2090 	}
2091 	return opline;
2092 }
2093 /* }}} */
2094 
zend_emit_op_tmp(znode * result,zend_uchar opcode,znode * op1,znode * op2)2095 static zend_op *zend_emit_op_tmp(znode *result, zend_uchar opcode, znode *op1, znode *op2) /* {{{ */
2096 {
2097 	zend_op *opline = get_next_op();
2098 	opline->opcode = opcode;
2099 
2100 	if (op1 != NULL) {
2101 		SET_NODE(opline->op1, op1);
2102 	}
2103 
2104 	if (op2 != NULL) {
2105 		SET_NODE(opline->op2, op2);
2106 	}
2107 
2108 	if (result) {
2109 		zend_make_tmp_result(result, opline);
2110 	}
2111 
2112 	return opline;
2113 }
2114 /* }}} */
2115 
zend_emit_tick(void)2116 static void zend_emit_tick(void) /* {{{ */
2117 {
2118 	zend_op *opline;
2119 
2120 	/* This prevents a double TICK generated by the parser statement of "declare()" */
2121 	if (CG(active_op_array)->last && CG(active_op_array)->opcodes[CG(active_op_array)->last - 1].opcode == ZEND_TICKS) {
2122 		return;
2123 	}
2124 
2125 	opline = get_next_op();
2126 
2127 	opline->opcode = ZEND_TICKS;
2128 	opline->extended_value = FC(declarables).ticks;
2129 }
2130 /* }}} */
2131 
zend_emit_op_data(znode * value)2132 static inline zend_op *zend_emit_op_data(znode *value) /* {{{ */
2133 {
2134 	return zend_emit_op(NULL, ZEND_OP_DATA, value, NULL);
2135 }
2136 /* }}} */
2137 
zend_emit_jump(uint32_t opnum_target)2138 static inline uint32_t zend_emit_jump(uint32_t opnum_target) /* {{{ */
2139 {
2140 	uint32_t opnum = get_next_op_number();
2141 	zend_op *opline = zend_emit_op(NULL, ZEND_JMP, NULL, NULL);
2142 	opline->op1.opline_num = opnum_target;
2143 	return opnum;
2144 }
2145 /* }}} */
2146 
zend_is_smart_branch(const zend_op * opline)2147 ZEND_API bool zend_is_smart_branch(const zend_op *opline) /* {{{ */
2148 {
2149 	switch (opline->opcode) {
2150 		case ZEND_IS_IDENTICAL:
2151 		case ZEND_IS_NOT_IDENTICAL:
2152 		case ZEND_IS_EQUAL:
2153 		case ZEND_IS_NOT_EQUAL:
2154 		case ZEND_IS_SMALLER:
2155 		case ZEND_IS_SMALLER_OR_EQUAL:
2156 		case ZEND_CASE:
2157 		case ZEND_CASE_STRICT:
2158 		case ZEND_ISSET_ISEMPTY_CV:
2159 		case ZEND_ISSET_ISEMPTY_VAR:
2160 		case ZEND_ISSET_ISEMPTY_DIM_OBJ:
2161 		case ZEND_ISSET_ISEMPTY_PROP_OBJ:
2162 		case ZEND_ISSET_ISEMPTY_STATIC_PROP:
2163 		case ZEND_INSTANCEOF:
2164 		case ZEND_TYPE_CHECK:
2165 		case ZEND_DEFINED:
2166 		case ZEND_IN_ARRAY:
2167 		case ZEND_ARRAY_KEY_EXISTS:
2168 			return 1;
2169 		default:
2170 			return 0;
2171 	}
2172 }
2173 /* }}} */
2174 
zend_emit_cond_jump(zend_uchar opcode,znode * cond,uint32_t opnum_target)2175 static inline uint32_t zend_emit_cond_jump(zend_uchar opcode, znode *cond, uint32_t opnum_target) /* {{{ */
2176 {
2177 	uint32_t opnum = get_next_op_number();
2178 	zend_op *opline;
2179 
2180 	if (cond->op_type == IS_TMP_VAR && opnum > 0) {
2181 		opline = CG(active_op_array)->opcodes + opnum - 1;
2182 		if (opline->result_type == IS_TMP_VAR
2183 		 && opline->result.var == cond->u.op.var
2184 		 && zend_is_smart_branch(opline)) {
2185 			if (opcode == ZEND_JMPZ) {
2186 				opline->result_type = IS_TMP_VAR | IS_SMART_BRANCH_JMPZ;
2187 			} else {
2188 				ZEND_ASSERT(opcode == ZEND_JMPNZ);
2189 				opline->result_type = IS_TMP_VAR | IS_SMART_BRANCH_JMPNZ;
2190 			}
2191 		}
2192 	}
2193 	opline = zend_emit_op(NULL, opcode, cond, NULL);
2194 	opline->op2.opline_num = opnum_target;
2195 	return opnum;
2196 }
2197 /* }}} */
2198 
zend_update_jump_target(uint32_t opnum_jump,uint32_t opnum_target)2199 static inline void zend_update_jump_target(uint32_t opnum_jump, uint32_t opnum_target) /* {{{ */
2200 {
2201 	zend_op *opline = &CG(active_op_array)->opcodes[opnum_jump];
2202 	switch (opline->opcode) {
2203 		case ZEND_JMP:
2204 			opline->op1.opline_num = opnum_target;
2205 			break;
2206 		case ZEND_JMPZ:
2207 		case ZEND_JMPNZ:
2208 		case ZEND_JMPZ_EX:
2209 		case ZEND_JMPNZ_EX:
2210 		case ZEND_JMP_SET:
2211 		case ZEND_COALESCE:
2212 		case ZEND_JMP_NULL:
2213 			opline->op2.opline_num = opnum_target;
2214 			break;
2215 		EMPTY_SWITCH_DEFAULT_CASE()
2216 	}
2217 }
2218 /* }}} */
2219 
zend_update_jump_target_to_next(uint32_t opnum_jump)2220 static inline void zend_update_jump_target_to_next(uint32_t opnum_jump) /* {{{ */
2221 {
2222 	zend_update_jump_target(opnum_jump, get_next_op_number());
2223 }
2224 /* }}} */
2225 
zend_delayed_emit_op(znode * result,zend_uchar opcode,znode * op1,znode * op2)2226 static inline zend_op *zend_delayed_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2) /* {{{ */
2227 {
2228 	zend_op tmp_opline;
2229 
2230 	init_op(&tmp_opline);
2231 
2232 	tmp_opline.opcode = opcode;
2233 	if (op1 != NULL) {
2234 		SET_NODE(tmp_opline.op1, op1);
2235 	}
2236 	if (op2 != NULL) {
2237 		SET_NODE(tmp_opline.op2, op2);
2238 	}
2239 	if (result) {
2240 		zend_make_var_result(result, &tmp_opline);
2241 	}
2242 
2243 	zend_stack_push(&CG(delayed_oplines_stack), &tmp_opline);
2244 	return zend_stack_top(&CG(delayed_oplines_stack));
2245 }
2246 /* }}} */
2247 
zend_delayed_compile_begin(void)2248 static inline uint32_t zend_delayed_compile_begin(void) /* {{{ */
2249 {
2250 	return zend_stack_count(&CG(delayed_oplines_stack));
2251 }
2252 /* }}} */
2253 
zend_delayed_compile_end(uint32_t offset)2254 static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */
2255 {
2256 	zend_op *opline = NULL, *oplines = zend_stack_base(&CG(delayed_oplines_stack));
2257 	uint32_t i, count = zend_stack_count(&CG(delayed_oplines_stack));
2258 
2259 	ZEND_ASSERT(count >= offset);
2260 	for (i = offset; i < count; ++i) {
2261 		opline = get_next_op();
2262 		memcpy(opline, &oplines[i], sizeof(zend_op));
2263 		if (opline->opcode == ZEND_JMP_NULL) {
2264 			uint32_t opnum = get_next_op_number() - 1;
2265 			zend_stack_push(&CG(short_circuiting_opnums), &opnum);
2266 		}
2267 	}
2268 
2269 	CG(delayed_oplines_stack).top = offset;
2270 	return opline;
2271 }
2272 /* }}} */
2273 
zend_ast_kind_is_short_circuited(zend_ast_kind ast_kind)2274 static bool zend_ast_kind_is_short_circuited(zend_ast_kind ast_kind)
2275 {
2276 	switch (ast_kind) {
2277 		case ZEND_AST_DIM:
2278 		case ZEND_AST_PROP:
2279 		case ZEND_AST_NULLSAFE_PROP:
2280 		case ZEND_AST_STATIC_PROP:
2281 		case ZEND_AST_METHOD_CALL:
2282 		case ZEND_AST_NULLSAFE_METHOD_CALL:
2283 		case ZEND_AST_STATIC_CALL:
2284 			return 1;
2285 		default:
2286 			return 0;
2287 	}
2288 }
2289 
zend_ast_is_short_circuited(const zend_ast * ast)2290 static bool zend_ast_is_short_circuited(const zend_ast *ast)
2291 {
2292 	switch (ast->kind) {
2293 		case ZEND_AST_DIM:
2294 		case ZEND_AST_PROP:
2295 		case ZEND_AST_STATIC_PROP:
2296 		case ZEND_AST_METHOD_CALL:
2297 		case ZEND_AST_STATIC_CALL:
2298 			return zend_ast_is_short_circuited(ast->child[0]);
2299 		case ZEND_AST_NULLSAFE_PROP:
2300 		case ZEND_AST_NULLSAFE_METHOD_CALL:
2301 			return 1;
2302 		default:
2303 			return 0;
2304 	}
2305 }
2306 
2307 /* Mark nodes that are an inner part of a short-circuiting chain.
2308  * We should not perform a "commit" on them, as it will be performed by the outer-most node.
2309  * We do this to avoid passing down an argument in various compile functions. */
2310 
2311 #define ZEND_SHORT_CIRCUITING_INNER 0x8000
2312 
zend_short_circuiting_mark_inner(zend_ast * ast)2313 static void zend_short_circuiting_mark_inner(zend_ast *ast) {
2314 	if (zend_ast_kind_is_short_circuited(ast->kind)) {
2315 		ast->attr |= ZEND_SHORT_CIRCUITING_INNER;
2316 	}
2317 }
2318 
zend_short_circuiting_checkpoint(void)2319 static uint32_t zend_short_circuiting_checkpoint(void)
2320 {
2321 	return zend_stack_count(&CG(short_circuiting_opnums));
2322 }
2323 
zend_short_circuiting_commit(uint32_t checkpoint,znode * result,zend_ast * ast)2324 static void zend_short_circuiting_commit(uint32_t checkpoint, znode *result, zend_ast *ast)
2325 {
2326 	bool is_short_circuited = zend_ast_kind_is_short_circuited(ast->kind)
2327 		|| ast->kind == ZEND_AST_ISSET || ast->kind == ZEND_AST_EMPTY;
2328 	if (!is_short_circuited) {
2329 		ZEND_ASSERT(zend_stack_count(&CG(short_circuiting_opnums)) == checkpoint
2330 			&& "Short circuiting stack should be empty");
2331 		return;
2332 	}
2333 
2334 	if (ast->attr & ZEND_SHORT_CIRCUITING_INNER) {
2335 		/* Outer-most node will commit. */
2336 		return;
2337 	}
2338 
2339 	while (zend_stack_count(&CG(short_circuiting_opnums)) != checkpoint) {
2340 		uint32_t opnum = *(uint32_t *) zend_stack_top(&CG(short_circuiting_opnums));
2341 		zend_op *opline = &CG(active_op_array)->opcodes[opnum];
2342 		opline->op2.opline_num = get_next_op_number();
2343 		SET_NODE(opline->result, result);
2344 		opline->extended_value =
2345 			ast->kind == ZEND_AST_ISSET ? ZEND_SHORT_CIRCUITING_CHAIN_ISSET :
2346 			ast->kind == ZEND_AST_EMPTY ? ZEND_SHORT_CIRCUITING_CHAIN_EMPTY :
2347 			                              ZEND_SHORT_CIRCUITING_CHAIN_EXPR;
2348 		zend_stack_del_top(&CG(short_circuiting_opnums));
2349 	}
2350 }
2351 
zend_emit_jmp_null(znode * obj_node)2352 static void zend_emit_jmp_null(znode *obj_node)
2353 {
2354 	uint32_t jmp_null_opnum = get_next_op_number();
2355 	zend_op *opline = zend_emit_op(NULL, ZEND_JMP_NULL, obj_node, NULL);
2356 	if (opline->op1_type == IS_CONST) {
2357 		Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
2358 	}
2359 	zend_stack_push(&CG(short_circuiting_opnums), &jmp_null_opnum);
2360 }
2361 
2362 #define ZEND_MEMOIZE_NONE 0
2363 #define ZEND_MEMOIZE_COMPILE 1
2364 #define ZEND_MEMOIZE_FETCH 2
2365 
zend_compile_memoized_expr(znode * result,zend_ast * expr)2366 static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */
2367 {
2368 	int memoize_mode = CG(memoize_mode);
2369 	if (memoize_mode == ZEND_MEMOIZE_COMPILE) {
2370 		znode memoized_result;
2371 
2372 		/* Go through normal compilation */
2373 		CG(memoize_mode) = ZEND_MEMOIZE_NONE;
2374 		zend_compile_expr(result, expr);
2375 		CG(memoize_mode) = ZEND_MEMOIZE_COMPILE;
2376 
2377 		if (result->op_type == IS_VAR) {
2378 			zend_emit_op(&memoized_result, ZEND_COPY_TMP, result, NULL);
2379 		} else if (result->op_type == IS_TMP_VAR) {
2380 			zend_emit_op_tmp(&memoized_result, ZEND_COPY_TMP, result, NULL);
2381 		} else {
2382 			if (result->op_type == IS_CONST) {
2383 				Z_TRY_ADDREF(result->u.constant);
2384 			}
2385 			memoized_result = *result;
2386 		}
2387 
2388 		zend_hash_index_update_mem(
2389 			CG(memoized_exprs), (uintptr_t) expr, &memoized_result, sizeof(znode));
2390 	} else if (memoize_mode == ZEND_MEMOIZE_FETCH) {
2391 		znode *memoized_result = zend_hash_index_find_ptr(CG(memoized_exprs), (uintptr_t) expr);
2392 		*result = *memoized_result;
2393 		if (result->op_type == IS_CONST) {
2394 			Z_TRY_ADDREF(result->u.constant);
2395 		}
2396 	} else {
2397 		ZEND_UNREACHABLE();
2398 	}
2399 }
2400 /* }}} */
2401 
zend_type_get_num_classes(zend_type type)2402 static size_t zend_type_get_num_classes(zend_type type) {
2403 	if (!ZEND_TYPE_IS_COMPLEX(type)) {
2404 		return 0;
2405 	}
2406 	if (ZEND_TYPE_HAS_LIST(type)) {
2407 		return ZEND_TYPE_LIST(type)->num_types;
2408 	}
2409 	return 1;
2410 }
2411 
zend_emit_return_type_check(znode * expr,zend_arg_info * return_info,bool implicit)2412 static void zend_emit_return_type_check(
2413 		znode *expr, zend_arg_info *return_info, bool implicit) /* {{{ */
2414 {
2415 	zend_type type = return_info->type;
2416 	if (ZEND_TYPE_IS_SET(type)) {
2417 		zend_op *opline;
2418 
2419 		/* `return ...;` is illegal in a void function (but `return;` isn't) */
2420 		if (ZEND_TYPE_CONTAINS_CODE(type, IS_VOID)) {
2421 			if (expr) {
2422 				if (expr->op_type == IS_CONST && Z_TYPE(expr->u.constant) == IS_NULL) {
2423 					zend_error_noreturn(E_COMPILE_ERROR,
2424 						"A void function must not return a value "
2425 						"(did you mean \"return;\" instead of \"return null;\"?)");
2426 				} else {
2427 					zend_error_noreturn(E_COMPILE_ERROR, "A void function must not return a value");
2428 				}
2429 			}
2430 			/* we don't need run-time check */
2431 			return;
2432 		}
2433 
2434 		/* `return` is illegal in a never-returning function */
2435 		if (ZEND_TYPE_CONTAINS_CODE(type, IS_NEVER)) {
2436 			/* Implicit case handled separately using VERIFY_NEVER_TYPE opcode. */
2437 			ZEND_ASSERT(!implicit);
2438 			zend_error_noreturn(E_COMPILE_ERROR, "A never-returning function must not return");
2439 			return;
2440 		}
2441 
2442 		if (!expr && !implicit) {
2443 			if (ZEND_TYPE_ALLOW_NULL(type)) {
2444 				zend_error_noreturn(E_COMPILE_ERROR,
2445 					"A function with return type must return a value "
2446 					"(did you mean \"return null;\" instead of \"return;\"?)");
2447 			} else {
2448 				zend_error_noreturn(E_COMPILE_ERROR,
2449 					"A function with return type must return a value");
2450 			}
2451 		}
2452 
2453 		if (expr && ZEND_TYPE_PURE_MASK(type) == MAY_BE_ANY) {
2454 			/* we don't need run-time check for mixed return type */
2455 			return;
2456 		}
2457 
2458 		if (expr && expr->op_type == IS_CONST && ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(expr->u.constant))) {
2459 			/* we don't need run-time check */
2460 			return;
2461 		}
2462 
2463 		opline = zend_emit_op(NULL, ZEND_VERIFY_RETURN_TYPE, expr, NULL);
2464 		if (expr && expr->op_type == IS_CONST) {
2465 			opline->result_type = expr->op_type = IS_TMP_VAR;
2466 			opline->result.var = expr->u.op.var = get_temporary_variable();
2467 		}
2468 
2469 		opline->op2.num = zend_alloc_cache_slots(zend_type_get_num_classes(return_info->type));
2470 	}
2471 }
2472 /* }}} */
2473 
zend_emit_final_return(bool return_one)2474 void zend_emit_final_return(bool return_one) /* {{{ */
2475 {
2476 	znode zn;
2477 	zend_op *ret;
2478 	bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
2479 
2480 	if ((CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)
2481 			&& !(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR)) {
2482 		zend_arg_info *return_info = CG(active_op_array)->arg_info - 1;
2483 
2484 		if (ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_NEVER)) {
2485 			zend_emit_op(NULL, ZEND_VERIFY_NEVER_TYPE, NULL, NULL);
2486 			return;
2487 		}
2488 
2489 		zend_emit_return_type_check(NULL, return_info, 1);
2490 	}
2491 
2492 	zn.op_type = IS_CONST;
2493 	if (return_one) {
2494 		ZVAL_LONG(&zn.u.constant, 1);
2495 	} else {
2496 		ZVAL_NULL(&zn.u.constant);
2497 	}
2498 
2499 	ret = zend_emit_op(NULL, returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN, &zn, NULL);
2500 	ret->extended_value = -1;
2501 }
2502 /* }}} */
2503 
zend_is_variable(zend_ast * ast)2504 static inline bool zend_is_variable(zend_ast *ast) /* {{{ */
2505 {
2506 	return ast->kind == ZEND_AST_VAR
2507 		|| ast->kind == ZEND_AST_DIM
2508 		|| ast->kind == ZEND_AST_PROP
2509 		|| ast->kind == ZEND_AST_NULLSAFE_PROP
2510 		|| ast->kind == ZEND_AST_STATIC_PROP;
2511 }
2512 /* }}} */
2513 
zend_is_call(zend_ast * ast)2514 static inline bool zend_is_call(zend_ast *ast) /* {{{ */
2515 {
2516 	return ast->kind == ZEND_AST_CALL
2517 		|| ast->kind == ZEND_AST_METHOD_CALL
2518 		|| ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL
2519 		|| ast->kind == ZEND_AST_STATIC_CALL;
2520 }
2521 /* }}} */
2522 
zend_is_variable_or_call(zend_ast * ast)2523 static inline bool zend_is_variable_or_call(zend_ast *ast) /* {{{ */
2524 {
2525 	return zend_is_variable(ast) || zend_is_call(ast);
2526 }
2527 /* }}} */
2528 
zend_is_unticked_stmt(zend_ast * ast)2529 static inline bool zend_is_unticked_stmt(zend_ast *ast) /* {{{ */
2530 {
2531 	return ast->kind == ZEND_AST_STMT_LIST || ast->kind == ZEND_AST_LABEL
2532 		|| ast->kind == ZEND_AST_PROP_DECL || ast->kind == ZEND_AST_CLASS_CONST_GROUP
2533 		|| ast->kind == ZEND_AST_USE_TRAIT || ast->kind == ZEND_AST_METHOD;
2534 }
2535 /* }}} */
2536 
zend_can_write_to_variable(zend_ast * ast)2537 static inline bool zend_can_write_to_variable(zend_ast *ast) /* {{{ */
2538 {
2539 	while (
2540 		ast->kind == ZEND_AST_DIM
2541 		|| ast->kind == ZEND_AST_PROP
2542 	) {
2543 		ast = ast->child[0];
2544 	}
2545 
2546 	return zend_is_variable_or_call(ast) && !zend_ast_is_short_circuited(ast);
2547 }
2548 /* }}} */
2549 
zend_is_const_default_class_ref(zend_ast * name_ast)2550 static inline bool zend_is_const_default_class_ref(zend_ast *name_ast) /* {{{ */
2551 {
2552 	if (name_ast->kind != ZEND_AST_ZVAL) {
2553 		return 0;
2554 	}
2555 
2556 	return ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type_ast(name_ast);
2557 }
2558 /* }}} */
2559 
zend_handle_numeric_op(znode * node)2560 static inline void zend_handle_numeric_op(znode *node) /* {{{ */
2561 {
2562 	if (node->op_type == IS_CONST && Z_TYPE(node->u.constant) == IS_STRING) {
2563 		zend_ulong index;
2564 
2565 		if (ZEND_HANDLE_NUMERIC(Z_STR(node->u.constant), index)) {
2566 			zval_ptr_dtor(&node->u.constant);
2567 			ZVAL_LONG(&node->u.constant, index);
2568 		}
2569 	}
2570 }
2571 /* }}} */
2572 
zend_handle_numeric_dim(zend_op * opline,znode * dim_node)2573 static inline void zend_handle_numeric_dim(zend_op *opline, znode *dim_node) /* {{{ */
2574 {
2575 	if (Z_TYPE(dim_node->u.constant) == IS_STRING) {
2576 		zend_ulong index;
2577 
2578 		if (ZEND_HANDLE_NUMERIC(Z_STR(dim_node->u.constant), index)) {
2579 			/* For numeric indexes we also keep the original value to use by ArrayAccess
2580 			 * See bug #63217
2581 			 */
2582 			int c = zend_add_literal(&dim_node->u.constant);
2583 			ZEND_ASSERT(opline->op2.constant + 1 == c);
2584 			ZVAL_LONG(CT_CONSTANT(opline->op2), index);
2585 			Z_EXTRA_P(CT_CONSTANT(opline->op2)) = ZEND_EXTRA_VALUE;
2586 			return;
2587 		}
2588 	}
2589 }
2590 /* }}} */
2591 
zend_set_class_name_op1(zend_op * opline,znode * class_node)2592 static inline void zend_set_class_name_op1(zend_op *opline, znode *class_node) /* {{{ */
2593 {
2594 	if (class_node->op_type == IS_CONST) {
2595 		opline->op1_type = IS_CONST;
2596 		opline->op1.constant = zend_add_class_name_literal(
2597 			Z_STR(class_node->u.constant));
2598 	} else {
2599 		SET_NODE(opline->op1, class_node);
2600 	}
2601 }
2602 /* }}} */
2603 
zend_compile_class_ref(znode * result,zend_ast * name_ast,uint32_t fetch_flags)2604 static void zend_compile_class_ref(znode *result, zend_ast *name_ast, uint32_t fetch_flags) /* {{{ */
2605 {
2606 	uint32_t fetch_type;
2607 
2608 	if (name_ast->kind != ZEND_AST_ZVAL) {
2609 		znode name_node;
2610 
2611 		zend_compile_expr(&name_node, name_ast);
2612 
2613 		if (name_node.op_type == IS_CONST) {
2614 			zend_string *name;
2615 
2616 			if (Z_TYPE(name_node.u.constant) != IS_STRING) {
2617 				zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
2618 			}
2619 
2620 			name = Z_STR(name_node.u.constant);
2621 			fetch_type = zend_get_class_fetch_type(name);
2622 
2623 			if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
2624 				result->op_type = IS_CONST;
2625 				ZVAL_STR(&result->u.constant, zend_resolve_class_name(name, ZEND_NAME_FQ));
2626 			} else {
2627 				zend_ensure_valid_class_fetch_type(fetch_type);
2628 				result->op_type = IS_UNUSED;
2629 				result->u.op.num = fetch_type | fetch_flags;
2630 			}
2631 
2632 			zend_string_release_ex(name, 0);
2633 		} else {
2634 			zend_op *opline = zend_emit_op(result, ZEND_FETCH_CLASS, NULL, &name_node);
2635 			opline->op1.num = ZEND_FETCH_CLASS_DEFAULT | fetch_flags;
2636 		}
2637 		return;
2638 	}
2639 
2640 	/* Fully qualified names are always default refs */
2641 	if (name_ast->attr == ZEND_NAME_FQ) {
2642 		result->op_type = IS_CONST;
2643 		ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast));
2644 		return;
2645 	}
2646 
2647 	fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
2648 	if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
2649 		result->op_type = IS_CONST;
2650 		ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast));
2651 	} else {
2652 		zend_ensure_valid_class_fetch_type(fetch_type);
2653 		result->op_type = IS_UNUSED;
2654 		result->u.op.num = fetch_type | fetch_flags;
2655 	}
2656 }
2657 /* }}} */
2658 
zend_try_compile_cv(znode * result,zend_ast * ast)2659 static zend_result zend_try_compile_cv(znode *result, zend_ast *ast) /* {{{ */
2660 {
2661 	zend_ast *name_ast = ast->child[0];
2662 	if (name_ast->kind == ZEND_AST_ZVAL) {
2663 		zval *zv = zend_ast_get_zval(name_ast);
2664 		zend_string *name;
2665 
2666 		if (EXPECTED(Z_TYPE_P(zv) == IS_STRING)) {
2667 			name = zval_make_interned_string(zv);
2668 		} else {
2669 			name = zend_new_interned_string(zval_get_string_func(zv));
2670 		}
2671 
2672 		if (zend_is_auto_global(name)) {
2673 			return FAILURE;
2674 		}
2675 
2676 		result->op_type = IS_CV;
2677 		result->u.op.var = lookup_cv(name);
2678 
2679 		if (UNEXPECTED(Z_TYPE_P(zv) != IS_STRING)) {
2680 			zend_string_release_ex(name, 0);
2681 		}
2682 
2683 		return SUCCESS;
2684 	}
2685 
2686 	return FAILURE;
2687 }
2688 /* }}} */
2689 
zend_compile_simple_var_no_cv(znode * result,zend_ast * ast,uint32_t type,bool delayed)2690 static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint32_t type, bool delayed) /* {{{ */
2691 {
2692 	zend_ast *name_ast = ast->child[0];
2693 	znode name_node;
2694 	zend_op *opline;
2695 
2696 	zend_compile_expr(&name_node, name_ast);
2697 	if (name_node.op_type == IS_CONST) {
2698 		convert_to_string(&name_node.u.constant);
2699 	}
2700 
2701 	if (delayed) {
2702 		opline = zend_delayed_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
2703 	} else {
2704 		opline = zend_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
2705 	}
2706 
2707 	if (name_node.op_type == IS_CONST &&
2708 	    zend_is_auto_global(Z_STR(name_node.u.constant))) {
2709 
2710 		opline->extended_value = ZEND_FETCH_GLOBAL;
2711 	} else {
2712 		opline->extended_value = ZEND_FETCH_LOCAL;
2713 	}
2714 
2715 	zend_adjust_for_fetch_type(opline, result, type);
2716 	return opline;
2717 }
2718 /* }}} */
2719 
is_this_fetch(zend_ast * ast)2720 static bool is_this_fetch(zend_ast *ast) /* {{{ */
2721 {
2722 	if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) {
2723 		zval *name = zend_ast_get_zval(ast->child[0]);
2724 		return Z_TYPE_P(name) == IS_STRING && zend_string_equals_literal(Z_STR_P(name), "this");
2725 	}
2726 
2727 	return 0;
2728 }
2729 /* }}} */
2730 
is_globals_fetch(const zend_ast * ast)2731 static bool is_globals_fetch(const zend_ast *ast)
2732 {
2733 	if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) {
2734 		zval *name = zend_ast_get_zval(ast->child[0]);
2735 		return Z_TYPE_P(name) == IS_STRING && zend_string_equals_literal(Z_STR_P(name), "GLOBALS");
2736 	}
2737 
2738 	return 0;
2739 }
2740 
is_global_var_fetch(zend_ast * ast)2741 static bool is_global_var_fetch(zend_ast *ast)
2742 {
2743 	return ast->kind == ZEND_AST_DIM && is_globals_fetch(ast->child[0]);
2744 }
2745 
this_guaranteed_exists(void)2746 static bool this_guaranteed_exists(void) /* {{{ */
2747 {
2748 	zend_op_array *op_array = CG(active_op_array);
2749 	/* Instance methods always have a $this.
2750 	 * This also includes closures that have a scope and use $this. */
2751 	return op_array->scope != NULL
2752 		&& (op_array->fn_flags & ZEND_ACC_STATIC) == 0;
2753 }
2754 /* }}} */
2755 
zend_compile_simple_var(znode * result,zend_ast * ast,uint32_t type,bool delayed)2756 static zend_op *zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type, bool delayed) /* {{{ */
2757 {
2758 	if (is_this_fetch(ast)) {
2759 		zend_op *opline = zend_emit_op(result, ZEND_FETCH_THIS, NULL, NULL);
2760 		if ((type == BP_VAR_R) || (type == BP_VAR_IS)) {
2761 			opline->result_type = IS_TMP_VAR;
2762 			result->op_type = IS_TMP_VAR;
2763 		}
2764 		CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
2765 		return opline;
2766 	} else if (is_globals_fetch(ast)) {
2767 		zend_op *opline = zend_emit_op(result, ZEND_FETCH_GLOBALS, NULL, NULL);
2768 		if (type == BP_VAR_R || type == BP_VAR_IS) {
2769 			opline->result_type = IS_TMP_VAR;
2770 			result->op_type = IS_TMP_VAR;
2771 		}
2772 		return opline;
2773 	} else if (zend_try_compile_cv(result, ast) == FAILURE) {
2774 		return zend_compile_simple_var_no_cv(result, ast, type, delayed);
2775 	}
2776 	return NULL;
2777 }
2778 /* }}} */
2779 
zend_separate_if_call_and_write(znode * node,zend_ast * ast,uint32_t type)2780 static void zend_separate_if_call_and_write(znode *node, zend_ast *ast, uint32_t type) /* {{{ */
2781 {
2782 	if (type != BP_VAR_R && type != BP_VAR_IS && zend_is_call(ast)) {
2783 		if (node->op_type == IS_VAR) {
2784 			zend_op *opline = zend_emit_op(NULL, ZEND_SEPARATE, node, NULL);
2785 			opline->result_type = IS_VAR;
2786 			opline->result.var = opline->op1.var;
2787 		} else {
2788 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context");
2789 		}
2790 	}
2791 }
2792 /* }}} */
2793 
zend_emit_assign_znode(zend_ast * var_ast,znode * value_node)2794 static inline void zend_emit_assign_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
2795 {
2796 	znode dummy_node;
2797 	zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN, var_ast,
2798 		zend_ast_create_znode(value_node));
2799 	zend_compile_expr(&dummy_node, assign_ast);
2800 	zend_do_free(&dummy_node);
2801 }
2802 /* }}} */
2803 
zend_delayed_compile_dim(znode * result,zend_ast * ast,uint32_t type)2804 static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2805 {
2806 	if (ast->attr == ZEND_DIM_ALTERNATIVE_SYNTAX) {
2807 		zend_error(E_COMPILE_ERROR, "Array and string offset access syntax with curly braces is no longer supported");
2808 	}
2809 	zend_ast *var_ast = ast->child[0];
2810 	zend_ast *dim_ast = ast->child[1];
2811 	zend_op *opline;
2812 
2813 	znode var_node, dim_node;
2814 
2815 	if (is_globals_fetch(var_ast)) {
2816 		if (dim_ast == NULL) {
2817 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot append to $GLOBALS");
2818 		}
2819 
2820 		zend_compile_expr(&dim_node, dim_ast);
2821 		if (dim_node.op_type == IS_CONST) {
2822 			convert_to_string(&dim_node.u.constant);
2823 		}
2824 
2825 		opline = zend_delayed_emit_op(result, ZEND_FETCH_R, &dim_node, NULL);
2826 		opline->extended_value = ZEND_FETCH_GLOBAL;
2827 		zend_adjust_for_fetch_type(opline, result, type);
2828 		return opline;
2829 	} else {
2830 		zend_short_circuiting_mark_inner(var_ast);
2831 		opline = zend_delayed_compile_var(&var_node, var_ast, type, 0);
2832 		if (opline && type == BP_VAR_W && (opline->opcode == ZEND_FETCH_STATIC_PROP_W || opline->opcode == ZEND_FETCH_OBJ_W)) {
2833 			opline->extended_value |= ZEND_FETCH_DIM_WRITE;
2834 		}
2835 	}
2836 
2837 	zend_separate_if_call_and_write(&var_node, var_ast, type);
2838 
2839 	if (dim_ast == NULL) {
2840 		if (type == BP_VAR_R || type == BP_VAR_IS) {
2841 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
2842 		}
2843 		if (type == BP_VAR_UNSET) {
2844 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting");
2845 		}
2846 		dim_node.op_type = IS_UNUSED;
2847 	} else {
2848 		zend_compile_expr(&dim_node, dim_ast);
2849 	}
2850 
2851 	opline = zend_delayed_emit_op(result, ZEND_FETCH_DIM_R, &var_node, &dim_node);
2852 	zend_adjust_for_fetch_type(opline, result, type);
2853 
2854 	if (dim_node.op_type == IS_CONST) {
2855 		zend_handle_numeric_dim(opline, &dim_node);
2856 	}
2857 	return opline;
2858 }
2859 /* }}} */
2860 
zend_compile_dim(znode * result,zend_ast * ast,uint32_t type)2861 static zend_op *zend_compile_dim(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2862 {
2863 	uint32_t offset = zend_delayed_compile_begin();
2864 	zend_delayed_compile_dim(result, ast, type);
2865 	return zend_delayed_compile_end(offset);
2866 }
2867 /* }}} */
2868 
zend_delayed_compile_prop(znode * result,zend_ast * ast,uint32_t type)2869 static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2870 {
2871 	zend_ast *obj_ast = ast->child[0];
2872 	zend_ast *prop_ast = ast->child[1];
2873 
2874 	znode obj_node, prop_node;
2875 	zend_op *opline;
2876 	bool nullsafe = ast->kind == ZEND_AST_NULLSAFE_PROP;
2877 
2878 	if (is_this_fetch(obj_ast)) {
2879 		if (this_guaranteed_exists()) {
2880 			obj_node.op_type = IS_UNUSED;
2881 		} else {
2882 			zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL);
2883 		}
2884 		CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
2885 
2886 		/* We will throw if $this doesn't exist, so there's no need to emit a JMP_NULL
2887 		 * check for a nullsafe access. */
2888 	} else {
2889 		zend_short_circuiting_mark_inner(obj_ast);
2890 		opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0);
2891 		zend_separate_if_call_and_write(&obj_node, obj_ast, type);
2892 		if (nullsafe) {
2893 			/* We will push to the short_circuiting_opnums stack in zend_delayed_compile_end(). */
2894 			opline = zend_delayed_emit_op(NULL, ZEND_JMP_NULL, &obj_node, NULL);
2895 			if (opline->op1_type == IS_CONST) {
2896 				Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
2897 			}
2898 		}
2899 	}
2900 
2901 	zend_compile_expr(&prop_node, prop_ast);
2902 
2903 	opline = zend_delayed_emit_op(result, ZEND_FETCH_OBJ_R, &obj_node, &prop_node);
2904 	if (opline->op2_type == IS_CONST) {
2905 		convert_to_string(CT_CONSTANT(opline->op2));
2906 		opline->extended_value = zend_alloc_cache_slots(3);
2907 	}
2908 
2909 	zend_adjust_for_fetch_type(opline, result, type);
2910 
2911 	return opline;
2912 }
2913 /* }}} */
2914 
zend_compile_prop(znode * result,zend_ast * ast,uint32_t type,bool by_ref)2915 static zend_op *zend_compile_prop(znode *result, zend_ast *ast, uint32_t type, bool by_ref) /* {{{ */
2916 {
2917 	uint32_t offset = zend_delayed_compile_begin();
2918 	zend_op *opline = zend_delayed_compile_prop(result, ast, type);
2919 	if (by_ref) { /* shared with cache_slot */
2920 		opline->extended_value |= ZEND_FETCH_REF;
2921 	}
2922 	return zend_delayed_compile_end(offset);
2923 }
2924 /* }}} */
2925 
zend_compile_static_prop(znode * result,zend_ast * ast,uint32_t type,bool by_ref,bool delayed)2926 static zend_op *zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, bool by_ref, bool delayed) /* {{{ */
2927 {
2928 	zend_ast *class_ast = ast->child[0];
2929 	zend_ast *prop_ast = ast->child[1];
2930 
2931 	znode class_node, prop_node;
2932 	zend_op *opline;
2933 
2934 	zend_short_circuiting_mark_inner(class_ast);
2935 	zend_compile_class_ref(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
2936 
2937 	zend_compile_expr(&prop_node, prop_ast);
2938 
2939 	if (delayed) {
2940 		opline = zend_delayed_emit_op(result, ZEND_FETCH_STATIC_PROP_R, &prop_node, NULL);
2941 	} else {
2942 		opline = zend_emit_op(result, ZEND_FETCH_STATIC_PROP_R, &prop_node, NULL);
2943 	}
2944 	if (opline->op1_type == IS_CONST) {
2945 		convert_to_string(CT_CONSTANT(opline->op1));
2946 		opline->extended_value = zend_alloc_cache_slots(3);
2947 	}
2948 	if (class_node.op_type == IS_CONST) {
2949 		opline->op2_type = IS_CONST;
2950 		opline->op2.constant = zend_add_class_name_literal(
2951 			Z_STR(class_node.u.constant));
2952 		if (opline->op1_type != IS_CONST) {
2953 			opline->extended_value = zend_alloc_cache_slot();
2954 		}
2955 	} else {
2956 		SET_NODE(opline->op2, &class_node);
2957 	}
2958 
2959 	if (by_ref && (type == BP_VAR_W || type == BP_VAR_FUNC_ARG)) { /* shared with cache_slot */
2960 		opline->extended_value |= ZEND_FETCH_REF;
2961 	}
2962 
2963 	zend_adjust_for_fetch_type(opline, result, type);
2964 	return opline;
2965 }
2966 /* }}} */
2967 
zend_verify_list_assign_target(zend_ast * var_ast,zend_ast_attr array_style)2968 static void zend_verify_list_assign_target(zend_ast *var_ast, zend_ast_attr array_style) /* {{{ */ {
2969 	if (var_ast->kind == ZEND_AST_ARRAY) {
2970 		if (var_ast->attr == ZEND_ARRAY_SYNTAX_LONG) {
2971 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot assign to array(), use [] instead");
2972 		}
2973 		if (array_style != var_ast->attr) {
2974 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix [] and list()");
2975 		}
2976 	} else if (!zend_can_write_to_variable(var_ast)) {
2977 		zend_error_noreturn(E_COMPILE_ERROR, "Assignments can only happen to writable values");
2978 	}
2979 }
2980 /* }}} */
2981 
2982 static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node);
2983 
2984 /* Propagate refs used on leaf elements to the surrounding list() structures. */
zend_propagate_list_refs(zend_ast * ast)2985 static bool zend_propagate_list_refs(zend_ast *ast) { /* {{{ */
2986 	zend_ast_list *list = zend_ast_get_list(ast);
2987 	bool has_refs = 0;
2988 	uint32_t i;
2989 
2990 	for (i = 0; i < list->children; ++i) {
2991 		zend_ast *elem_ast = list->child[i];
2992 
2993 		if (elem_ast) {
2994 			zend_ast *var_ast = elem_ast->child[0];
2995 			if (var_ast->kind == ZEND_AST_ARRAY) {
2996 				elem_ast->attr = zend_propagate_list_refs(var_ast);
2997 			}
2998 			has_refs |= elem_ast->attr;
2999 		}
3000 	}
3001 
3002 	return has_refs;
3003 }
3004 /* }}} */
3005 
list_is_keyed(zend_ast_list * list)3006 static bool list_is_keyed(zend_ast_list *list)
3007 {
3008 	for (uint32_t i = 0; i < list->children; i++) {
3009 		zend_ast *child = list->child[i];
3010 		if (child) {
3011 			return child->kind == ZEND_AST_ARRAY_ELEM && child->child[1] != NULL;
3012 		}
3013 	}
3014 	return false;
3015 }
3016 
zend_compile_list_assign(znode * result,zend_ast * ast,znode * expr_node,zend_ast_attr array_style)3017 static void zend_compile_list_assign(
3018 		znode *result, zend_ast *ast, znode *expr_node, zend_ast_attr array_style) /* {{{ */
3019 {
3020 	zend_ast_list *list = zend_ast_get_list(ast);
3021 	uint32_t i;
3022 	bool has_elems = 0;
3023 	bool is_keyed = list_is_keyed(list);
3024 
3025 	if (list->children && expr_node->op_type == IS_CONST && Z_TYPE(expr_node->u.constant) == IS_STRING) {
3026 		zval_make_interned_string(&expr_node->u.constant);
3027 	}
3028 
3029 	for (i = 0; i < list->children; ++i) {
3030 		zend_ast *elem_ast = list->child[i];
3031 		zend_ast *var_ast, *key_ast;
3032 		znode fetch_result, dim_node;
3033 		zend_op *opline;
3034 
3035 		if (elem_ast == NULL) {
3036 			if (is_keyed) {
3037 				zend_error(E_COMPILE_ERROR,
3038 					"Cannot use empty array entries in keyed array assignment");
3039 			} else {
3040 				continue;
3041 			}
3042 		}
3043 
3044 		if (elem_ast->kind == ZEND_AST_UNPACK) {
3045 			zend_error(E_COMPILE_ERROR,
3046 					"Spread operator is not supported in assignments");
3047 		}
3048 
3049 		var_ast = elem_ast->child[0];
3050 		key_ast = elem_ast->child[1];
3051 		has_elems = 1;
3052 
3053 		if (is_keyed) {
3054 			if (key_ast == NULL) {
3055 				zend_error(E_COMPILE_ERROR,
3056 					"Cannot mix keyed and unkeyed array entries in assignments");
3057 			}
3058 
3059 			zend_compile_expr(&dim_node, key_ast);
3060 		} else {
3061 			if (key_ast != NULL) {
3062 				zend_error(E_COMPILE_ERROR,
3063 					"Cannot mix keyed and unkeyed array entries in assignments");
3064 			}
3065 
3066 			dim_node.op_type = IS_CONST;
3067 			ZVAL_LONG(&dim_node.u.constant, i);
3068 		}
3069 
3070 		if (expr_node->op_type == IS_CONST) {
3071 			Z_TRY_ADDREF(expr_node->u.constant);
3072 		}
3073 
3074 		zend_verify_list_assign_target(var_ast, array_style);
3075 
3076 		opline = zend_emit_op(&fetch_result,
3077 			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);
3078 
3079 		if (dim_node.op_type == IS_CONST) {
3080 			zend_handle_numeric_dim(opline, &dim_node);
3081 		}
3082 
3083 		if (elem_ast->attr) {
3084 			zend_emit_op(&fetch_result, ZEND_MAKE_REF, &fetch_result, NULL);
3085 		}
3086 		if (var_ast->kind == ZEND_AST_ARRAY) {
3087 			zend_compile_list_assign(NULL, var_ast, &fetch_result, var_ast->attr);
3088 		} else if (elem_ast->attr) {
3089 			zend_emit_assign_ref_znode(var_ast, &fetch_result);
3090 		} else {
3091 			zend_emit_assign_znode(var_ast, &fetch_result);
3092 		}
3093 	}
3094 
3095 	if (has_elems == 0) {
3096 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list");
3097 	}
3098 
3099 	if (result) {
3100 		*result = *expr_node;
3101 	} else {
3102 		zend_do_free(expr_node);
3103 	}
3104 }
3105 /* }}} */
3106 
zend_ensure_writable_variable(const zend_ast * ast)3107 static void zend_ensure_writable_variable(const zend_ast *ast) /* {{{ */
3108 {
3109 	if (ast->kind == ZEND_AST_CALL) {
3110 		zend_error_noreturn(E_COMPILE_ERROR, "Can't use function return value in write context");
3111 	}
3112 	if (
3113 		ast->kind == ZEND_AST_METHOD_CALL
3114 		|| ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL
3115 		|| ast->kind == ZEND_AST_STATIC_CALL
3116 	) {
3117 		zend_error_noreturn(E_COMPILE_ERROR, "Can't use method return value in write context");
3118 	}
3119 	if (zend_ast_is_short_circuited(ast)) {
3120 		zend_error_noreturn(E_COMPILE_ERROR, "Can't use nullsafe operator in write context");
3121 	}
3122 	if (is_globals_fetch(ast)) {
3123 		zend_error_noreturn(E_COMPILE_ERROR,
3124 			"$GLOBALS can only be modified using the $GLOBALS[$name] = $value syntax");
3125 	}
3126 }
3127 /* }}} */
3128 
3129 /* Detects $a... = $a pattern */
zend_is_assign_to_self(zend_ast * var_ast,zend_ast * expr_ast)3130 static bool zend_is_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast) /* {{{ */
3131 {
3132 	if (expr_ast->kind != ZEND_AST_VAR || expr_ast->child[0]->kind != ZEND_AST_ZVAL) {
3133 		return 0;
3134 	}
3135 
3136 	while (zend_is_variable(var_ast) && var_ast->kind != ZEND_AST_VAR) {
3137 		var_ast = var_ast->child[0];
3138 	}
3139 
3140 	if (var_ast->kind != ZEND_AST_VAR || var_ast->child[0]->kind != ZEND_AST_ZVAL) {
3141 		return 0;
3142 	}
3143 
3144 	{
3145 		zend_string *name1 = zval_get_string(zend_ast_get_zval(var_ast->child[0]));
3146 		zend_string *name2 = zval_get_string(zend_ast_get_zval(expr_ast->child[0]));
3147 		bool result = zend_string_equals(name1, name2);
3148 		zend_string_release_ex(name1, 0);
3149 		zend_string_release_ex(name2, 0);
3150 		return result;
3151 	}
3152 }
3153 /* }}} */
3154 
zend_compile_expr_with_potential_assign_to_self(znode * expr_node,zend_ast * expr_ast,zend_ast * var_ast)3155 static void zend_compile_expr_with_potential_assign_to_self(
3156 		znode *expr_node, zend_ast *expr_ast, zend_ast *var_ast) {
3157 	if (zend_is_assign_to_self(var_ast, expr_ast) && !is_this_fetch(expr_ast)) {
3158 		/* $a[0] = $a should evaluate the right $a first */
3159 		znode cv_node;
3160 
3161 		if (zend_try_compile_cv(&cv_node, expr_ast) == FAILURE) {
3162 			zend_compile_simple_var_no_cv(expr_node, expr_ast, BP_VAR_R, 0);
3163 		} else {
3164 			zend_emit_op_tmp(expr_node, ZEND_QM_ASSIGN, &cv_node, NULL);
3165 		}
3166 	} else {
3167 		zend_compile_expr(expr_node, expr_ast);
3168 	}
3169 }
3170 
zend_compile_assign(znode * result,zend_ast * ast)3171 static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
3172 {
3173 	zend_ast *var_ast = ast->child[0];
3174 	zend_ast *expr_ast = ast->child[1];
3175 
3176 	znode var_node, expr_node;
3177 	zend_op *opline;
3178 	uint32_t offset;
3179 	if (is_this_fetch(var_ast)) {
3180 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
3181 	}
3182 
3183 	zend_ensure_writable_variable(var_ast);
3184 
3185 	/* Treat $GLOBALS['x'] assignment like assignment to variable. */
3186 	zend_ast_kind kind = is_global_var_fetch(var_ast) ? ZEND_AST_VAR : var_ast->kind;
3187 	switch (kind) {
3188 		case ZEND_AST_VAR:
3189 			offset = zend_delayed_compile_begin();
3190 			zend_delayed_compile_var(&var_node, var_ast, BP_VAR_W, 0);
3191 			zend_compile_expr(&expr_node, expr_ast);
3192 			zend_delayed_compile_end(offset);
3193 			CG(zend_lineno) = zend_ast_get_lineno(var_ast);
3194 			zend_emit_op_tmp(result, ZEND_ASSIGN, &var_node, &expr_node);
3195 			return;
3196 		case ZEND_AST_STATIC_PROP:
3197 			offset = zend_delayed_compile_begin();
3198 			zend_delayed_compile_var(result, var_ast, BP_VAR_W, 0);
3199 			zend_compile_expr(&expr_node, expr_ast);
3200 
3201 			opline = zend_delayed_compile_end(offset);
3202 			opline->opcode = ZEND_ASSIGN_STATIC_PROP;
3203 			opline->result_type = IS_TMP_VAR;
3204 			result->op_type = IS_TMP_VAR;
3205 
3206 			zend_emit_op_data(&expr_node);
3207 			return;
3208 		case ZEND_AST_DIM:
3209 			offset = zend_delayed_compile_begin();
3210 			zend_delayed_compile_dim(result, var_ast, BP_VAR_W);
3211 			zend_compile_expr_with_potential_assign_to_self(&expr_node, expr_ast, var_ast);
3212 
3213 			opline = zend_delayed_compile_end(offset);
3214 			opline->opcode = ZEND_ASSIGN_DIM;
3215 			opline->result_type = IS_TMP_VAR;
3216 			result->op_type = IS_TMP_VAR;
3217 
3218 			opline = zend_emit_op_data(&expr_node);
3219 			return;
3220 		case ZEND_AST_PROP:
3221 		case ZEND_AST_NULLSAFE_PROP:
3222 			offset = zend_delayed_compile_begin();
3223 			zend_delayed_compile_prop(result, var_ast, BP_VAR_W);
3224 			zend_compile_expr(&expr_node, expr_ast);
3225 
3226 			opline = zend_delayed_compile_end(offset);
3227 			opline->opcode = ZEND_ASSIGN_OBJ;
3228 			opline->result_type = IS_TMP_VAR;
3229 			result->op_type = IS_TMP_VAR;
3230 
3231 			zend_emit_op_data(&expr_node);
3232 			return;
3233 		case ZEND_AST_ARRAY:
3234 			if (zend_propagate_list_refs(var_ast)) {
3235 				if (!zend_is_variable_or_call(expr_ast)) {
3236 					zend_error_noreturn(E_COMPILE_ERROR,
3237 						"Cannot assign reference to non referenceable value");
3238 				}
3239 
3240 				zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1);
3241 				/* MAKE_REF is usually not necessary for CVs. However, if there are
3242 				 * self-assignments, this forces the RHS to evaluate first. */
3243 				zend_emit_op(&expr_node, ZEND_MAKE_REF, &expr_node, NULL);
3244 			} else {
3245 				if (expr_ast->kind == ZEND_AST_VAR) {
3246 					/* list($a, $b) = $a should evaluate the right $a first */
3247 					znode cv_node;
3248 
3249 					if (zend_try_compile_cv(&cv_node, expr_ast) == FAILURE) {
3250 						zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, 0);
3251 					} else {
3252 						zend_emit_op_tmp(&expr_node, ZEND_QM_ASSIGN, &cv_node, NULL);
3253 					}
3254 				} else {
3255 					zend_compile_expr(&expr_node, expr_ast);
3256 				}
3257 			}
3258 
3259 			zend_compile_list_assign(result, var_ast, &expr_node, var_ast->attr);
3260 			return;
3261 		EMPTY_SWITCH_DEFAULT_CASE();
3262 	}
3263 }
3264 /* }}} */
3265 
zend_compile_assign_ref(znode * result,zend_ast * ast)3266 static void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
3267 {
3268 	zend_ast *target_ast = ast->child[0];
3269 	zend_ast *source_ast = ast->child[1];
3270 
3271 	znode target_node, source_node;
3272 	zend_op *opline;
3273 	uint32_t offset, flags;
3274 
3275 	if (is_this_fetch(target_ast)) {
3276 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
3277 	}
3278 	zend_ensure_writable_variable(target_ast);
3279 	if (zend_ast_is_short_circuited(source_ast)) {
3280 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot take reference of a nullsafe chain");
3281 	}
3282 	if (is_globals_fetch(source_ast)) {
3283 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot acquire reference to $GLOBALS");
3284 	}
3285 
3286 	offset = zend_delayed_compile_begin();
3287 	zend_delayed_compile_var(&target_node, target_ast, BP_VAR_W, 1);
3288 	zend_compile_var(&source_node, source_ast, BP_VAR_W, 1);
3289 
3290 	if ((target_ast->kind != ZEND_AST_VAR
3291 	  || target_ast->child[0]->kind != ZEND_AST_ZVAL)
3292 	 && source_ast->kind != ZEND_AST_ZNODE
3293 	 && source_node.op_type != IS_CV) {
3294 		/* Both LHS and RHS expressions may modify the same data structure,
3295 		 * and the modification during RHS evaluation may dangle the pointer
3296 		 * to the result of the LHS evaluation.
3297 		 * Use MAKE_REF instruction to replace direct pointer with REFERENCE.
3298 		 * See: Bug #71539
3299 		 */
3300 		zend_emit_op(&source_node, ZEND_MAKE_REF, &source_node, NULL);
3301 	}
3302 
3303 	opline = zend_delayed_compile_end(offset);
3304 
3305 	if (source_node.op_type != IS_VAR && zend_is_call(source_ast)) {
3306 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context");
3307 	}
3308 
3309 	flags = zend_is_call(source_ast) ? ZEND_RETURNS_FUNCTION : 0;
3310 
3311 	if (opline && opline->opcode == ZEND_FETCH_OBJ_W) {
3312 		opline->opcode = ZEND_ASSIGN_OBJ_REF;
3313 		opline->extended_value &= ~ZEND_FETCH_REF;
3314 		opline->extended_value |= flags;
3315 		zend_emit_op_data(&source_node);
3316 		*result = target_node;
3317 	} else if (opline && opline->opcode == ZEND_FETCH_STATIC_PROP_W) {
3318 		opline->opcode = ZEND_ASSIGN_STATIC_PROP_REF;
3319 		opline->extended_value &= ~ZEND_FETCH_REF;
3320 		opline->extended_value |= flags;
3321 		zend_emit_op_data(&source_node);
3322 		*result = target_node;
3323 	} else {
3324 		opline = zend_emit_op(result, ZEND_ASSIGN_REF, &target_node, &source_node);
3325 		opline->extended_value = flags;
3326 	}
3327 }
3328 /* }}} */
3329 
zend_emit_assign_ref_znode(zend_ast * var_ast,znode * value_node)3330 static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
3331 {
3332 	znode dummy_node;
3333 	zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN_REF, var_ast,
3334 		zend_ast_create_znode(value_node));
3335 	zend_compile_expr(&dummy_node, assign_ast);
3336 	zend_do_free(&dummy_node);
3337 }
3338 /* }}} */
3339 
zend_compile_compound_assign(znode * result,zend_ast * ast)3340 static void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
3341 {
3342 	zend_ast *var_ast = ast->child[0];
3343 	zend_ast *expr_ast = ast->child[1];
3344 	uint32_t opcode = ast->attr;
3345 
3346 	znode var_node, expr_node;
3347 	zend_op *opline;
3348 	uint32_t offset, cache_slot;
3349 
3350 	zend_ensure_writable_variable(var_ast);
3351 
3352 	/* Treat $GLOBALS['x'] assignment like assignment to variable. */
3353 	zend_ast_kind kind = is_global_var_fetch(var_ast) ? ZEND_AST_VAR : var_ast->kind;
3354 	switch (kind) {
3355 		case ZEND_AST_VAR:
3356 			offset = zend_delayed_compile_begin();
3357 			zend_delayed_compile_var(&var_node, var_ast, BP_VAR_RW, 0);
3358 			zend_compile_expr(&expr_node, expr_ast);
3359 			zend_delayed_compile_end(offset);
3360 			opline = zend_emit_op_tmp(result, ZEND_ASSIGN_OP, &var_node, &expr_node);
3361 			opline->extended_value = opcode;
3362 			return;
3363 		case ZEND_AST_STATIC_PROP:
3364 			offset = zend_delayed_compile_begin();
3365 			zend_delayed_compile_var(result, var_ast, BP_VAR_RW, 0);
3366 			zend_compile_expr(&expr_node, expr_ast);
3367 
3368 			opline = zend_delayed_compile_end(offset);
3369 			cache_slot = opline->extended_value;
3370 			opline->opcode = ZEND_ASSIGN_STATIC_PROP_OP;
3371 			opline->extended_value = opcode;
3372 			opline->result_type = IS_TMP_VAR;
3373 			result->op_type = IS_TMP_VAR;
3374 
3375 			opline = zend_emit_op_data(&expr_node);
3376 			opline->extended_value = cache_slot;
3377 			return;
3378 		case ZEND_AST_DIM:
3379 			offset = zend_delayed_compile_begin();
3380 			zend_delayed_compile_dim(result, var_ast, BP_VAR_RW);
3381 			zend_compile_expr_with_potential_assign_to_self(&expr_node, expr_ast, var_ast);
3382 
3383 			opline = zend_delayed_compile_end(offset);
3384 			opline->opcode = ZEND_ASSIGN_DIM_OP;
3385 			opline->extended_value = opcode;
3386 			opline->result_type = IS_TMP_VAR;
3387 			result->op_type = IS_TMP_VAR;
3388 
3389 			zend_emit_op_data(&expr_node);
3390 			return;
3391 		case ZEND_AST_PROP:
3392 		case ZEND_AST_NULLSAFE_PROP:
3393 			offset = zend_delayed_compile_begin();
3394 			zend_delayed_compile_prop(result, var_ast, BP_VAR_RW);
3395 			zend_compile_expr(&expr_node, expr_ast);
3396 
3397 			opline = zend_delayed_compile_end(offset);
3398 			cache_slot = opline->extended_value;
3399 			opline->opcode = ZEND_ASSIGN_OBJ_OP;
3400 			opline->extended_value = opcode;
3401 			opline->result_type = IS_TMP_VAR;
3402 			result->op_type = IS_TMP_VAR;
3403 
3404 			opline = zend_emit_op_data(&expr_node);
3405 			opline->extended_value = cache_slot;
3406 			return;
3407 		EMPTY_SWITCH_DEFAULT_CASE()
3408 	}
3409 }
3410 /* }}} */
3411 
zend_get_arg_num(zend_function * fn,zend_string * arg_name)3412 static uint32_t zend_get_arg_num(zend_function *fn, zend_string *arg_name) {
3413 	// TODO: Caching?
3414 	if (fn->type == ZEND_USER_FUNCTION) {
3415 		for (uint32_t i = 0; i < fn->common.num_args; i++) {
3416 			zend_arg_info *arg_info = &fn->op_array.arg_info[i];
3417 			if (zend_string_equals(arg_info->name, arg_name)) {
3418 				return i + 1;
3419 			}
3420 		}
3421 	} else {
3422 		for (uint32_t i = 0; i < fn->common.num_args; i++) {
3423 			zend_internal_arg_info *arg_info = &fn->internal_function.arg_info[i];
3424 			size_t len = strlen(arg_info->name);
3425 			if (len == ZSTR_LEN(arg_name) && !memcmp(arg_info->name, ZSTR_VAL(arg_name), len)) {
3426 				return i + 1;
3427 			}
3428 		}
3429 	}
3430 
3431 	/* Either an invalid argument name, or collected into a variadic argument. */
3432 	return (uint32_t) -1;
3433 }
3434 
zend_compile_args(zend_ast * ast,zend_function * fbc,bool * may_have_extra_named_args)3435 static uint32_t zend_compile_args(
3436 		zend_ast *ast, zend_function *fbc, bool *may_have_extra_named_args) /* {{{ */
3437 {
3438 	zend_ast_list *args = zend_ast_get_list(ast);
3439 	uint32_t i;
3440 	bool uses_arg_unpack = 0;
3441 	uint32_t arg_count = 0; /* number of arguments not including unpacks */
3442 
3443 	/* Whether named arguments are used syntactically, to enforce language level limitations.
3444 	 * May not actually use named argument passing. */
3445 	bool uses_named_args = 0;
3446 	/* Whether there may be any undef arguments due to the use of named arguments. */
3447 	bool may_have_undef = 0;
3448 	/* Whether there may be any extra named arguments collected into a variadic. */
3449 	*may_have_extra_named_args = 0;
3450 
3451 	for (i = 0; i < args->children; ++i) {
3452 		zend_ast *arg = args->child[i];
3453 		zend_string *arg_name = NULL;
3454 		uint32_t arg_num = i + 1;
3455 
3456 		znode arg_node;
3457 		zend_op *opline;
3458 		zend_uchar opcode;
3459 
3460 		if (arg->kind == ZEND_AST_UNPACK) {
3461 			if (uses_named_args) {
3462 				zend_error_noreturn(E_COMPILE_ERROR,
3463 					"Cannot use argument unpacking after named arguments");
3464 			}
3465 
3466 			uses_arg_unpack = 1;
3467 			fbc = NULL;
3468 
3469 			zend_compile_expr(&arg_node, arg->child[0]);
3470 			opline = zend_emit_op(NULL, ZEND_SEND_UNPACK, &arg_node, NULL);
3471 			opline->op2.num = arg_count;
3472 			opline->result.var = EX_NUM_TO_VAR(arg_count - 1);
3473 
3474 			/* Unpack may contain named arguments. */
3475 			may_have_undef = 1;
3476 			if (!fbc || (fbc->common.fn_flags & ZEND_ACC_VARIADIC)) {
3477 				*may_have_extra_named_args = 1;
3478 			}
3479 			continue;
3480 		}
3481 
3482 		if (arg->kind == ZEND_AST_NAMED_ARG) {
3483 			uses_named_args = 1;
3484 			arg_name = zval_make_interned_string(zend_ast_get_zval(arg->child[0]));
3485 			arg = arg->child[1];
3486 
3487 			if (fbc && !uses_arg_unpack) {
3488 				arg_num = zend_get_arg_num(fbc, arg_name);
3489 				if (arg_num == arg_count + 1 && !may_have_undef) {
3490 					/* Using named arguments, but passing in order. */
3491 					arg_name = NULL;
3492 					arg_count++;
3493 				} else {
3494 					// TODO: We could track which arguments were passed, even if out of order.
3495 					may_have_undef = 1;
3496 					if (arg_num == (uint32_t) -1 && (fbc->common.fn_flags & ZEND_ACC_VARIADIC)) {
3497 						*may_have_extra_named_args = 1;
3498 					}
3499 				}
3500 			} else {
3501 				arg_num = (uint32_t) -1;
3502 				may_have_undef = 1;
3503 				*may_have_extra_named_args = 1;
3504 			}
3505 		} else {
3506 			if (uses_arg_unpack) {
3507 				zend_error_noreturn(E_COMPILE_ERROR,
3508 					"Cannot use positional argument after argument unpacking");
3509 			}
3510 
3511 			if (uses_named_args) {
3512 				zend_error_noreturn(E_COMPILE_ERROR,
3513 					"Cannot use positional argument after named argument");
3514 			}
3515 
3516 			arg_count++;
3517 		}
3518 
3519 		/* Treat passing of $GLOBALS the same as passing a call.
3520 		 * This will error at runtime if the argument is by-ref. */
3521 		if (zend_is_call(arg) || is_globals_fetch(arg)) {
3522 			zend_compile_var(&arg_node, arg, BP_VAR_R, 0);
3523 			if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) {
3524 				/* Function call was converted into builtin instruction */
3525 				if (!fbc || ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3526 					opcode = ZEND_SEND_VAL_EX;
3527 				} else {
3528 					opcode = ZEND_SEND_VAL;
3529 				}
3530 			} else {
3531 				if (fbc && arg_num != (uint32_t) -1) {
3532 					if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3533 						opcode = ZEND_SEND_VAR_NO_REF;
3534 					} else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) {
3535 						opcode = ZEND_SEND_VAL;
3536 					} else {
3537 						opcode = ZEND_SEND_VAR;
3538 					}
3539 				} else {
3540 					opcode = ZEND_SEND_VAR_NO_REF_EX;
3541 				}
3542 			}
3543 		} else if (zend_is_variable(arg) && !zend_ast_is_short_circuited(arg)) {
3544 			if (fbc && arg_num != (uint32_t) -1) {
3545 				if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) {
3546 					zend_compile_var(&arg_node, arg, BP_VAR_W, 1);
3547 					opcode = ZEND_SEND_REF;
3548 				} else {
3549 					zend_compile_var(&arg_node, arg, BP_VAR_R, 0);
3550 					opcode = (arg_node.op_type == IS_TMP_VAR) ? ZEND_SEND_VAL : ZEND_SEND_VAR;
3551 				}
3552 			} else {
3553 				do {
3554 					if (arg->kind == ZEND_AST_VAR) {
3555 						CG(zend_lineno) = zend_ast_get_lineno(ast);
3556 						if (is_this_fetch(arg)) {
3557 							zend_emit_op(&arg_node, ZEND_FETCH_THIS, NULL, NULL);
3558 							opcode = ZEND_SEND_VAR_EX;
3559 							CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
3560 							break;
3561 						} else if (zend_try_compile_cv(&arg_node, arg) == SUCCESS) {
3562 							opcode = ZEND_SEND_VAR_EX;
3563 							break;
3564 						}
3565 					}
3566 					opline = zend_emit_op(NULL, ZEND_CHECK_FUNC_ARG, NULL, NULL);
3567 					if (arg_name) {
3568 						opline->op2_type = IS_CONST;
3569 						zend_string_addref(arg_name);
3570 						opline->op2.constant = zend_add_literal_string(&arg_name);
3571 						opline->result.num = zend_alloc_cache_slots(2);
3572 					} else {
3573 						opline->op2.num = arg_num;
3574 					}
3575 					zend_compile_var(&arg_node, arg, BP_VAR_FUNC_ARG, 1);
3576 					opcode = ZEND_SEND_FUNC_ARG;
3577 				} while (0);
3578 			}
3579 		} else {
3580 			zend_compile_expr(&arg_node, arg);
3581 			if (arg_node.op_type == IS_VAR) {
3582 				/* pass ++$a or something similar */
3583 				if (fbc && arg_num != (uint32_t) -1) {
3584 					if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3585 						opcode = ZEND_SEND_VAR_NO_REF;
3586 					} else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) {
3587 						opcode = ZEND_SEND_VAL;
3588 					} else {
3589 						opcode = ZEND_SEND_VAR;
3590 					}
3591 				} else {
3592 					opcode = ZEND_SEND_VAR_NO_REF_EX;
3593 				}
3594 			} else if (arg_node.op_type == IS_CV) {
3595 				if (fbc && arg_num != (uint32_t) -1) {
3596 					if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) {
3597 						opcode = ZEND_SEND_REF;
3598 					} else {
3599 						opcode = ZEND_SEND_VAR;
3600 					}
3601 				} else {
3602 					opcode = ZEND_SEND_VAR_EX;
3603 				}
3604 			} else {
3605 				/* Delay "Only variables can be passed by reference" error to execution */
3606 				if (fbc && arg_num != (uint32_t) -1 && !ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3607 					opcode = ZEND_SEND_VAL;
3608 				} else {
3609 					opcode = ZEND_SEND_VAL_EX;
3610 				}
3611 			}
3612 		}
3613 
3614 		opline = zend_emit_op(NULL, opcode, &arg_node, NULL);
3615 		if (arg_name) {
3616 			opline->op2_type = IS_CONST;
3617 			zend_string_addref(arg_name);
3618 			opline->op2.constant = zend_add_literal_string(&arg_name);
3619 			opline->result.num = zend_alloc_cache_slots(2);
3620 		} else {
3621 			opline->op2.opline_num = arg_num;
3622 			opline->result.var = EX_NUM_TO_VAR(arg_num - 1);
3623 		}
3624 	}
3625 
3626 	if (may_have_undef) {
3627 		zend_emit_op(NULL, ZEND_CHECK_UNDEF_ARGS, NULL, NULL);
3628 	}
3629 
3630 	return arg_count;
3631 }
3632 /* }}} */
3633 
zend_get_call_op(const zend_op * init_op,zend_function * fbc)3634 ZEND_API zend_uchar zend_get_call_op(const zend_op *init_op, zend_function *fbc) /* {{{ */
3635 {
3636 	if (fbc) {
3637 		if (fbc->type == ZEND_INTERNAL_FUNCTION && !(CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS)) {
3638 			if (init_op->opcode == ZEND_INIT_FCALL && !zend_execute_internal) {
3639 				if (!(fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED))) {
3640 					return ZEND_DO_ICALL;
3641 				} else {
3642 					return ZEND_DO_FCALL_BY_NAME;
3643 				}
3644 			}
3645 		} else if (!(CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS)){
3646 			if (zend_execute_ex == execute_ex && !(fbc->common.fn_flags & ZEND_ACC_ABSTRACT)) {
3647 				return ZEND_DO_UCALL;
3648 			}
3649 		}
3650 	} else if (zend_execute_ex == execute_ex &&
3651 	           !zend_execute_internal &&
3652 	           (init_op->opcode == ZEND_INIT_FCALL_BY_NAME ||
3653 	            init_op->opcode == ZEND_INIT_NS_FCALL_BY_NAME)) {
3654 		return ZEND_DO_FCALL_BY_NAME;
3655 	}
3656 	return ZEND_DO_FCALL;
3657 }
3658 /* }}} */
3659 
zend_compile_call_common(znode * result,zend_ast * args_ast,zend_function * fbc)3660 static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc) /* {{{ */
3661 {
3662 	zend_op *opline;
3663 	uint32_t opnum_init = get_next_op_number() - 1;
3664 
3665 	if (args_ast->kind == ZEND_AST_CALLABLE_CONVERT) {
3666 		opline = &CG(active_op_array)->opcodes[opnum_init];
3667 		opline->extended_value = 0;
3668 
3669 		if (opline->opcode == ZEND_NEW) {
3670 		    zend_error_noreturn(E_COMPILE_ERROR, "Cannot create Closure for new expression");
3671 		}
3672 
3673 		if (opline->opcode == ZEND_INIT_FCALL) {
3674 			opline->op1.num = zend_vm_calc_used_stack(0, fbc);
3675 		}
3676 
3677 		zend_emit_op_tmp(result, ZEND_CALLABLE_CONVERT, NULL, NULL);
3678 		return true;
3679 	}
3680 
3681 	bool may_have_extra_named_args;
3682 	uint32_t arg_count = zend_compile_args(args_ast, fbc, &may_have_extra_named_args);
3683 
3684 	zend_do_extended_fcall_begin();
3685 
3686 	opline = &CG(active_op_array)->opcodes[opnum_init];
3687 	opline->extended_value = arg_count;
3688 
3689 	if (opline->opcode == ZEND_INIT_FCALL) {
3690 		opline->op1.num = zend_vm_calc_used_stack(arg_count, fbc);
3691 	}
3692 
3693 	opline = zend_emit_op(result, zend_get_call_op(opline, fbc), NULL, NULL);
3694 	if (may_have_extra_named_args) {
3695 		opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS;
3696 	}
3697 	zend_do_extended_fcall_end();
3698 	return false;
3699 }
3700 /* }}} */
3701 
zend_compile_function_name(znode * name_node,zend_ast * name_ast)3702 static bool zend_compile_function_name(znode *name_node, zend_ast *name_ast) /* {{{ */
3703 {
3704 	zend_string *orig_name = zend_ast_get_str(name_ast);
3705 	bool is_fully_qualified;
3706 
3707 	name_node->op_type = IS_CONST;
3708 	ZVAL_STR(&name_node->u.constant, zend_resolve_function_name(
3709 		orig_name, name_ast->attr, &is_fully_qualified));
3710 
3711 	return !is_fully_qualified && FC(current_namespace);
3712 }
3713 /* }}} */
3714 
zend_compile_ns_call(znode * result,znode * name_node,zend_ast * args_ast)3715 static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */
3716 {
3717 	zend_op *opline = get_next_op();
3718 	opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
3719 	opline->op2_type = IS_CONST;
3720 	opline->op2.constant = zend_add_ns_func_name_literal(
3721 		Z_STR(name_node->u.constant));
3722 	opline->result.num = zend_alloc_cache_slot();
3723 
3724 	zend_compile_call_common(result, args_ast, NULL);
3725 }
3726 /* }}} */
3727 
zend_compile_dynamic_call(znode * result,znode * name_node,zend_ast * args_ast)3728 static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */
3729 {
3730 	if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) {
3731 		const char *colon;
3732 		zend_string *str = Z_STR(name_node->u.constant);
3733 		if ((colon = zend_memrchr(ZSTR_VAL(str), ':', ZSTR_LEN(str))) != NULL && colon > ZSTR_VAL(str) && *(colon - 1) == ':') {
3734 			zend_string *class = zend_string_init(ZSTR_VAL(str), colon - ZSTR_VAL(str) - 1, 0);
3735 			zend_string *method = zend_string_init(colon + 1, ZSTR_LEN(str) - (colon - ZSTR_VAL(str)) - 1, 0);
3736 			zend_op *opline = get_next_op();
3737 
3738 			opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
3739 			opline->op1_type = IS_CONST;
3740 			opline->op1.constant = zend_add_class_name_literal(class);
3741 			opline->op2_type = IS_CONST;
3742 			opline->op2.constant = zend_add_func_name_literal(method);
3743 			/* 2 slots, for class and method */
3744 			opline->result.num = zend_alloc_cache_slots(2);
3745 			zval_ptr_dtor(&name_node->u.constant);
3746 		} else {
3747 			zend_op *opline = get_next_op();
3748 
3749 			opline->opcode = ZEND_INIT_FCALL_BY_NAME;
3750 			opline->op2_type = IS_CONST;
3751 			opline->op2.constant = zend_add_func_name_literal(str);
3752 			opline->result.num = zend_alloc_cache_slot();
3753 		}
3754 	} else {
3755 		zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, name_node);
3756 	}
3757 
3758 	zend_compile_call_common(result, args_ast, NULL);
3759 }
3760 /* }}} */
3761 
zend_args_contain_unpack_or_named(zend_ast_list * args)3762 static inline bool zend_args_contain_unpack_or_named(zend_ast_list *args) /* {{{ */
3763 {
3764 	uint32_t i;
3765 	for (i = 0; i < args->children; ++i) {
3766 		zend_ast *arg = args->child[i];
3767 		if (arg->kind == ZEND_AST_UNPACK || arg->kind == ZEND_AST_NAMED_ARG) {
3768 			return 1;
3769 		}
3770 	}
3771 	return 0;
3772 }
3773 /* }}} */
3774 
zend_compile_func_strlen(znode * result,zend_ast_list * args)3775 static zend_result zend_compile_func_strlen(znode *result, zend_ast_list *args) /* {{{ */
3776 {
3777 	znode arg_node;
3778 
3779 	if (args->children != 1) {
3780 		return FAILURE;
3781 	}
3782 
3783 	zend_compile_expr(&arg_node, args->child[0]);
3784 	if (arg_node.op_type == IS_CONST && Z_TYPE(arg_node.u.constant) == IS_STRING) {
3785 		result->op_type = IS_CONST;
3786 		ZVAL_LONG(&result->u.constant, Z_STRLEN(arg_node.u.constant));
3787 		zval_ptr_dtor_str(&arg_node.u.constant);
3788 	} else {
3789 		zend_emit_op_tmp(result, ZEND_STRLEN, &arg_node, NULL);
3790 	}
3791 	return SUCCESS;
3792 }
3793 /* }}} */
3794 
zend_compile_func_typecheck(znode * result,zend_ast_list * args,uint32_t type)3795 static zend_result zend_compile_func_typecheck(znode *result, zend_ast_list *args, uint32_t type) /* {{{ */
3796 {
3797 	znode arg_node;
3798 	zend_op *opline;
3799 
3800 	if (args->children != 1) {
3801 		return FAILURE;
3802 	}
3803 
3804 	zend_compile_expr(&arg_node, args->child[0]);
3805 	opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL);
3806 	if (type != _IS_BOOL) {
3807 		opline->extended_value = (1 << type);
3808 	} else {
3809 		opline->extended_value = (1 << IS_FALSE) | (1 << IS_TRUE);
3810 	}
3811 	return SUCCESS;
3812 }
3813 /* }}} */
3814 
zend_compile_func_is_scalar(znode * result,zend_ast_list * args)3815 static zend_result zend_compile_func_is_scalar(znode *result, zend_ast_list *args) /* {{{ */
3816 {
3817 	znode arg_node;
3818 	zend_op *opline;
3819 
3820 	if (args->children != 1) {
3821 		return FAILURE;
3822 	}
3823 
3824 	zend_compile_expr(&arg_node, args->child[0]);
3825 	opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL);
3826 	opline->extended_value = (1 << IS_FALSE | 1 << IS_TRUE | 1 << IS_DOUBLE | 1 << IS_LONG | 1 << IS_STRING);
3827 	return SUCCESS;
3828 }
3829 
zend_compile_func_cast(znode * result,zend_ast_list * args,uint32_t type)3830 static zend_result zend_compile_func_cast(znode *result, zend_ast_list *args, uint32_t type) /* {{{ */
3831 {
3832 	znode arg_node;
3833 	zend_op *opline;
3834 
3835 	if (args->children != 1) {
3836 		return FAILURE;
3837 	}
3838 
3839 	zend_compile_expr(&arg_node, args->child[0]);
3840 	if (type == _IS_BOOL) {
3841 		opline = zend_emit_op_tmp(result, ZEND_BOOL, &arg_node, NULL);
3842 	} else {
3843 		opline = zend_emit_op_tmp(result, ZEND_CAST, &arg_node, NULL);
3844 		opline->extended_value = type;
3845 	}
3846 	return SUCCESS;
3847 }
3848 /* }}} */
3849 
zend_compile_func_defined(znode * result,zend_ast_list * args)3850 static zend_result zend_compile_func_defined(znode *result, zend_ast_list *args) /* {{{ */
3851 {
3852 	zend_string *name;
3853 	zend_op *opline;
3854 
3855 	if (args->children != 1 || args->child[0]->kind != ZEND_AST_ZVAL) {
3856 		return FAILURE;
3857 	}
3858 
3859 	name = zval_get_string(zend_ast_get_zval(args->child[0]));
3860 	if (zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name)) || zend_memrchr(ZSTR_VAL(name), ':', ZSTR_LEN(name))) {
3861 		zend_string_release_ex(name, 0);
3862 		return FAILURE;
3863 	}
3864 
3865 	if (zend_try_ct_eval_const(&result->u.constant, name, 0)) {
3866 		zend_string_release_ex(name, 0);
3867 		zval_ptr_dtor(&result->u.constant);
3868 		ZVAL_TRUE(&result->u.constant);
3869 		result->op_type = IS_CONST;
3870 		return SUCCESS;
3871 	}
3872 
3873 	opline = zend_emit_op_tmp(result, ZEND_DEFINED, NULL, NULL);
3874 	opline->op1_type = IS_CONST;
3875 	LITERAL_STR(opline->op1, name);
3876 	opline->extended_value = zend_alloc_cache_slot();
3877 
3878 	return SUCCESS;
3879 }
3880 /* }}} */
3881 
zend_compile_func_chr(znode * result,zend_ast_list * args)3882 static zend_result zend_compile_func_chr(znode *result, zend_ast_list *args) /* {{{ */
3883 {
3884 
3885 	if (args->children == 1 &&
3886 	    args->child[0]->kind == ZEND_AST_ZVAL &&
3887 	    Z_TYPE_P(zend_ast_get_zval(args->child[0])) == IS_LONG) {
3888 
3889 		zend_long c = Z_LVAL_P(zend_ast_get_zval(args->child[0])) & 0xff;
3890 
3891 		result->op_type = IS_CONST;
3892 		ZVAL_CHAR(&result->u.constant, c);
3893 		return SUCCESS;
3894 	} else {
3895 		return FAILURE;
3896 	}
3897 }
3898 /* }}} */
3899 
zend_compile_func_ord(znode * result,zend_ast_list * args)3900 static zend_result zend_compile_func_ord(znode *result, zend_ast_list *args) /* {{{ */
3901 {
3902 	if (args->children == 1 &&
3903 	    args->child[0]->kind == ZEND_AST_ZVAL &&
3904 	    Z_TYPE_P(zend_ast_get_zval(args->child[0])) == IS_STRING) {
3905 
3906 		result->op_type = IS_CONST;
3907 		ZVAL_LONG(&result->u.constant, (unsigned char)Z_STRVAL_P(zend_ast_get_zval(args->child[0]))[0]);
3908 		return SUCCESS;
3909 	} else {
3910 		return FAILURE;
3911 	}
3912 }
3913 /* }}} */
3914 
3915 /* We can only calculate the stack size for functions that have been fully compiled, otherwise
3916  * additional CV or TMP slots may still be added. This prevents the use of INIT_FCALL for
3917  * directly or indirectly recursive function calls. */
fbc_is_finalized(zend_function * fbc)3918 static bool fbc_is_finalized(zend_function *fbc) {
3919 	return !ZEND_USER_CODE(fbc->type) || (fbc->common.fn_flags & ZEND_ACC_DONE_PASS_TWO);
3920 }
3921 
zend_try_compile_ct_bound_init_user_func(zend_ast * name_ast,uint32_t num_args)3922 static zend_result zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t num_args) /* {{{ */
3923 {
3924 	zend_string *name, *lcname;
3925 	zend_function *fbc;
3926 	zend_op *opline;
3927 
3928 	if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
3929 		return FAILURE;
3930 	}
3931 
3932 	name = zend_ast_get_str(name_ast);
3933 	lcname = zend_string_tolower(name);
3934 
3935 	fbc = zend_hash_find_ptr(CG(function_table), lcname);
3936 	if (!fbc || !fbc_is_finalized(fbc)
3937 	 || (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
3938 	 || (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS))
3939 	 || (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && fbc->op_array.filename != CG(active_op_array)->filename)
3940 	) {
3941 		zend_string_release_ex(lcname, 0);
3942 		return FAILURE;
3943 	}
3944 
3945 	opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, NULL);
3946 	opline->extended_value = num_args;
3947 	opline->op1.num = zend_vm_calc_used_stack(num_args, fbc);
3948 	opline->op2_type = IS_CONST;
3949 	LITERAL_STR(opline->op2, lcname);
3950 	opline->result.num = zend_alloc_cache_slot();
3951 
3952 	return SUCCESS;
3953 }
3954 /* }}} */
3955 
zend_compile_init_user_func(zend_ast * name_ast,uint32_t num_args,zend_string * orig_func_name)3956 static void zend_compile_init_user_func(zend_ast *name_ast, uint32_t num_args, zend_string *orig_func_name) /* {{{ */
3957 {
3958 	zend_op *opline;
3959 	znode name_node;
3960 
3961 	if (zend_try_compile_ct_bound_init_user_func(name_ast, num_args) == SUCCESS) {
3962 		return;
3963 	}
3964 
3965 	zend_compile_expr(&name_node, name_ast);
3966 
3967 	opline = zend_emit_op(NULL, ZEND_INIT_USER_CALL, NULL, &name_node);
3968 	opline->op1_type = IS_CONST;
3969 	LITERAL_STR(opline->op1, zend_string_copy(orig_func_name));
3970 	opline->extended_value = num_args;
3971 }
3972 /* }}} */
3973 
3974 /* cufa = call_user_func_array */
zend_compile_func_cufa(znode * result,zend_ast_list * args,zend_string * lcname)3975 static zend_result zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
3976 {
3977 	znode arg_node;
3978 
3979 	if (args->children != 2) {
3980 		return FAILURE;
3981 	}
3982 
3983 	zend_compile_init_user_func(args->child[0], 0, lcname);
3984 	if (args->child[1]->kind == ZEND_AST_CALL
3985 	 && args->child[1]->child[0]->kind == ZEND_AST_ZVAL
3986 	 && Z_TYPE_P(zend_ast_get_zval(args->child[1]->child[0])) == IS_STRING
3987 	 && args->child[1]->child[1]->kind == ZEND_AST_ARG_LIST) {
3988 		zend_string *orig_name = zend_ast_get_str(args->child[1]->child[0]);
3989 		zend_ast_list *list = zend_ast_get_list(args->child[1]->child[1]);
3990 		bool is_fully_qualified;
3991 		zend_string *name = zend_resolve_function_name(orig_name, args->child[1]->child[0]->attr, &is_fully_qualified);
3992 
3993 		if (zend_string_equals_literal_ci(name, "array_slice")
3994 	     && !zend_args_contain_unpack_or_named(list)
3995 		 && list->children == 3
3996 		 && list->child[1]->kind == ZEND_AST_ZVAL) {
3997 			zval *zv = zend_ast_get_zval(list->child[1]);
3998 
3999 			if (Z_TYPE_P(zv) == IS_LONG
4000 			 && Z_LVAL_P(zv) >= 0
4001 			 && Z_LVAL_P(zv) <= 0x7fffffff) {
4002 				zend_op *opline;
4003 				znode len_node;
4004 
4005 				zend_compile_expr(&arg_node, list->child[0]);
4006 				zend_compile_expr(&len_node, list->child[2]);
4007 				opline = zend_emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, &len_node);
4008 				opline->extended_value = Z_LVAL_P(zv);
4009 				zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
4010 				zend_string_release_ex(name, 0);
4011 				return SUCCESS;
4012 			}
4013 		}
4014 		zend_string_release_ex(name, 0);
4015 	}
4016 	zend_compile_expr(&arg_node, args->child[1]);
4017 	zend_emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, NULL);
4018 	zend_emit_op(NULL, ZEND_CHECK_UNDEF_ARGS, NULL, NULL);
4019 	zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
4020 
4021 	return SUCCESS;
4022 }
4023 /* }}} */
4024 
4025 /* cuf = call_user_func */
zend_compile_func_cuf(znode * result,zend_ast_list * args,zend_string * lcname)4026 static zend_result zend_compile_func_cuf(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
4027 {
4028 	uint32_t i;
4029 
4030 	if (args->children < 1) {
4031 		return FAILURE;
4032 	}
4033 
4034 	zend_compile_init_user_func(args->child[0], args->children - 1, lcname);
4035 	for (i = 1; i < args->children; ++i) {
4036 		zend_ast *arg_ast = args->child[i];
4037 		znode arg_node;
4038 		zend_op *opline;
4039 
4040 		zend_compile_expr(&arg_node, arg_ast);
4041 
4042 		opline = zend_emit_op(NULL, ZEND_SEND_USER, &arg_node, NULL);
4043 		opline->op2.num = i;
4044 		opline->result.var = EX_NUM_TO_VAR(i - 1);
4045 	}
4046 	zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
4047 
4048 	return SUCCESS;
4049 }
4050 /* }}} */
4051 
zend_compile_assert(znode * result,zend_ast_list * args,zend_string * name,zend_function * fbc)4052 static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, zend_function *fbc) /* {{{ */
4053 {
4054 	if (EG(assertions) >= 0) {
4055 		znode name_node;
4056 		zend_op *opline;
4057 		uint32_t check_op_number = get_next_op_number();
4058 
4059 		zend_emit_op(NULL, ZEND_ASSERT_CHECK, NULL, NULL);
4060 
4061 		if (fbc && fbc_is_finalized(fbc)) {
4062 			name_node.op_type = IS_CONST;
4063 			ZVAL_STR_COPY(&name_node.u.constant, name);
4064 
4065 			opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
4066 		} else {
4067 			opline = zend_emit_op(NULL, ZEND_INIT_NS_FCALL_BY_NAME, NULL, NULL);
4068 			opline->op2_type = IS_CONST;
4069 			opline->op2.constant = zend_add_ns_func_name_literal(name);
4070 		}
4071 		opline->result.num = zend_alloc_cache_slot();
4072 
4073 		if (args->children == 1) {
4074 			/* add "assert(condition) as assertion message */
4075 			zend_ast *arg = zend_ast_create_zval_from_str(
4076 				zend_ast_export("assert(", args->child[0], ")"));
4077 			if (args->child[0]->kind == ZEND_AST_NAMED_ARG) {
4078 				/* If the original argument was named, add the new argument as named as well,
4079 				 * as mixing named and positional is not allowed. */
4080 				zend_ast *name = zend_ast_create_zval_from_str(
4081 					zend_string_init("description", sizeof("description") - 1, 0));
4082 				arg = zend_ast_create(ZEND_AST_NAMED_ARG, name, arg);
4083 			}
4084 			zend_ast_list_add((zend_ast *) args, arg);
4085 		}
4086 
4087 		zend_compile_call_common(result, (zend_ast*)args, fbc);
4088 
4089 		opline = &CG(active_op_array)->opcodes[check_op_number];
4090 		opline->op2.opline_num = get_next_op_number();
4091 		SET_NODE(opline->result, result);
4092 	} else {
4093 		if (!fbc) {
4094 			zend_string_release_ex(name, 0);
4095 		}
4096 		result->op_type = IS_CONST;
4097 		ZVAL_TRUE(&result->u.constant);
4098 	}
4099 }
4100 /* }}} */
4101 
zend_compile_func_in_array(znode * result,zend_ast_list * args)4102 static zend_result zend_compile_func_in_array(znode *result, zend_ast_list *args) /* {{{ */
4103 {
4104 	bool strict = 0;
4105 	znode array, needly;
4106 	zend_op *opline;
4107 
4108 	if (args->children == 3) {
4109 		if (args->child[2]->kind == ZEND_AST_ZVAL) {
4110 			strict = zend_is_true(zend_ast_get_zval(args->child[2]));
4111 		} else if (args->child[2]->kind == ZEND_AST_CONST) {
4112 			zval value;
4113 			zend_ast *name_ast = args->child[2]->child[0];
4114 			bool is_fully_qualified;
4115 			zend_string *resolved_name = zend_resolve_const_name(
4116 				zend_ast_get_str(name_ast), name_ast->attr, &is_fully_qualified);
4117 
4118 			if (!zend_try_ct_eval_const(&value, resolved_name, is_fully_qualified)) {
4119 				zend_string_release_ex(resolved_name, 0);
4120 				return FAILURE;
4121 			}
4122 
4123 			zend_string_release_ex(resolved_name, 0);
4124 			strict = zend_is_true(&value);
4125 			zval_ptr_dtor(&value);
4126 		} else {
4127 			return FAILURE;
4128 		}
4129 	} else if (args->children != 2) {
4130 		return FAILURE;
4131 	}
4132 
4133 	if (args->child[1]->kind != ZEND_AST_ARRAY
4134 	 || !zend_try_ct_eval_array(&array.u.constant, args->child[1])) {
4135 		return FAILURE;
4136 	}
4137 
4138 	if (zend_hash_num_elements(Z_ARRVAL(array.u.constant)) > 0) {
4139 		bool ok = 1;
4140 		zval *val, tmp;
4141 		HashTable *src = Z_ARRVAL(array.u.constant);
4142 		HashTable *dst = zend_new_array(zend_hash_num_elements(src));
4143 
4144 		ZVAL_TRUE(&tmp);
4145 
4146 		if (strict) {
4147 			ZEND_HASH_FOREACH_VAL(src, val) {
4148 				if (Z_TYPE_P(val) == IS_STRING) {
4149 					zend_hash_add(dst, Z_STR_P(val), &tmp);
4150 				} else if (Z_TYPE_P(val) == IS_LONG) {
4151 					zend_hash_index_add(dst, Z_LVAL_P(val), &tmp);
4152 				} else {
4153 					zend_array_destroy(dst);
4154 					ok = 0;
4155 					break;
4156 				}
4157 			} ZEND_HASH_FOREACH_END();
4158 		} else {
4159 			ZEND_HASH_FOREACH_VAL(src, val) {
4160 				if (Z_TYPE_P(val) != IS_STRING
4161 				 || is_numeric_string(Z_STRVAL_P(val), Z_STRLEN_P(val), NULL, NULL, 0)) {
4162 					zend_array_destroy(dst);
4163 					ok = 0;
4164 					break;
4165 				}
4166 				zend_hash_add(dst, Z_STR_P(val), &tmp);
4167 			} ZEND_HASH_FOREACH_END();
4168 		}
4169 
4170 		zend_array_destroy(src);
4171 		if (!ok) {
4172 			return FAILURE;
4173 		}
4174 		Z_ARRVAL(array.u.constant) = dst;
4175 	}
4176 	array.op_type = IS_CONST;
4177 
4178 	zend_compile_expr(&needly, args->child[0]);
4179 
4180 	opline = zend_emit_op_tmp(result, ZEND_IN_ARRAY, &needly, &array);
4181 	opline->extended_value = strict;
4182 
4183 	return SUCCESS;
4184 }
4185 /* }}} */
4186 
zend_compile_func_count(znode * result,zend_ast_list * args,zend_string * lcname)4187 static zend_result zend_compile_func_count(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
4188 {
4189 	znode arg_node;
4190 	zend_op *opline;
4191 
4192 	if (args->children != 1) {
4193 		return FAILURE;
4194 	}
4195 
4196 	zend_compile_expr(&arg_node, args->child[0]);
4197 	opline = zend_emit_op_tmp(result, ZEND_COUNT, &arg_node, NULL);
4198 	opline->extended_value = zend_string_equals_literal(lcname, "sizeof");
4199 
4200 	return SUCCESS;
4201 }
4202 /* }}} */
4203 
zend_compile_func_get_class(znode * result,zend_ast_list * args)4204 static zend_result zend_compile_func_get_class(znode *result, zend_ast_list *args) /* {{{ */
4205 {
4206 	if (args->children == 0) {
4207 		zend_emit_op_tmp(result, ZEND_GET_CLASS, NULL, NULL);
4208 	} else {
4209 		znode arg_node;
4210 
4211 		if (args->children != 1) {
4212 			return FAILURE;
4213 		}
4214 
4215 		zend_compile_expr(&arg_node, args->child[0]);
4216 		zend_emit_op_tmp(result, ZEND_GET_CLASS, &arg_node, NULL);
4217 	}
4218 	return SUCCESS;
4219 }
4220 /* }}} */
4221 
zend_compile_func_get_called_class(znode * result,zend_ast_list * args)4222 static zend_result zend_compile_func_get_called_class(znode *result, zend_ast_list *args) /* {{{ */
4223 {
4224 	if (args->children != 0) {
4225 		return FAILURE;
4226 	}
4227 
4228 	zend_emit_op_tmp(result, ZEND_GET_CALLED_CLASS, NULL, NULL);
4229 	return SUCCESS;
4230 }
4231 /* }}} */
4232 
zend_compile_func_gettype(znode * result,zend_ast_list * args)4233 static zend_result zend_compile_func_gettype(znode *result, zend_ast_list *args) /* {{{ */
4234 {
4235 	znode arg_node;
4236 
4237 	if (args->children != 1) {
4238 		return FAILURE;
4239 	}
4240 
4241 	zend_compile_expr(&arg_node, args->child[0]);
4242 	zend_emit_op_tmp(result, ZEND_GET_TYPE, &arg_node, NULL);
4243 	return SUCCESS;
4244 }
4245 /* }}} */
4246 
zend_compile_func_num_args(znode * result,zend_ast_list * args)4247 static zend_result zend_compile_func_num_args(znode *result, zend_ast_list *args) /* {{{ */
4248 {
4249 	if (CG(active_op_array)->function_name && args->children == 0) {
4250 		zend_emit_op_tmp(result, ZEND_FUNC_NUM_ARGS, NULL, NULL);
4251 		return SUCCESS;
4252 	} else {
4253 		return FAILURE;
4254 	}
4255 }
4256 /* }}} */
4257 
zend_compile_func_get_args(znode * result,zend_ast_list * args)4258 static zend_result zend_compile_func_get_args(znode *result, zend_ast_list *args) /* {{{ */
4259 {
4260 	if (CG(active_op_array)->function_name && args->children == 0) {
4261 		zend_emit_op_tmp(result, ZEND_FUNC_GET_ARGS, NULL, NULL);
4262 		return SUCCESS;
4263 	} else {
4264 		return FAILURE;
4265 	}
4266 }
4267 /* }}} */
4268 
zend_compile_func_array_key_exists(znode * result,zend_ast_list * args)4269 static zend_result zend_compile_func_array_key_exists(znode *result, zend_ast_list *args) /* {{{ */
4270 {
4271 	znode subject, needle;
4272 
4273 	if (args->children != 2) {
4274 		return FAILURE;
4275 	}
4276 
4277 	zend_compile_expr(&needle, args->child[0]);
4278 	zend_compile_expr(&subject, args->child[1]);
4279 
4280 	zend_emit_op_tmp(result, ZEND_ARRAY_KEY_EXISTS, &needle, &subject);
4281 	return SUCCESS;
4282 }
4283 /* }}} */
4284 
zend_compile_func_array_slice(znode * result,zend_ast_list * args)4285 static zend_result zend_compile_func_array_slice(znode *result, zend_ast_list *args) /* {{{ */
4286 {
4287 	if (CG(active_op_array)->function_name
4288 	 && args->children == 2
4289 	 && args->child[0]->kind == ZEND_AST_CALL
4290 	 && args->child[0]->child[0]->kind == ZEND_AST_ZVAL
4291 	 && Z_TYPE_P(zend_ast_get_zval(args->child[0]->child[0])) == IS_STRING
4292 	 && args->child[0]->child[1]->kind == ZEND_AST_ARG_LIST
4293 	 && args->child[1]->kind == ZEND_AST_ZVAL) {
4294 
4295 		zend_string *orig_name = zend_ast_get_str(args->child[0]->child[0]);
4296 		bool is_fully_qualified;
4297 		zend_string *name = zend_resolve_function_name(orig_name, args->child[0]->child[0]->attr, &is_fully_qualified);
4298 		zend_ast_list *list = zend_ast_get_list(args->child[0]->child[1]);
4299 		zval *zv = zend_ast_get_zval(args->child[1]);
4300 		znode first;
4301 
4302 		if (zend_string_equals_literal_ci(name, "func_get_args")
4303 		 && list->children == 0
4304 		 && Z_TYPE_P(zv) == IS_LONG
4305 		 && Z_LVAL_P(zv) >= 0) {
4306 			first.op_type = IS_CONST;
4307 			ZVAL_LONG(&first.u.constant, Z_LVAL_P(zv));
4308 			zend_emit_op_tmp(result, ZEND_FUNC_GET_ARGS, &first, NULL);
4309 			zend_string_release_ex(name, 0);
4310 			return SUCCESS;
4311 		}
4312 		zend_string_release_ex(name, 0);
4313 	}
4314 	return FAILURE;
4315 }
4316 /* }}} */
4317 
zend_try_compile_special_func(znode * result,zend_string * lcname,zend_ast_list * args,zend_function * fbc,uint32_t type)4318 static zend_result zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */
4319 {
4320 	if (CG(compiler_options) & ZEND_COMPILE_NO_BUILTINS) {
4321 		return FAILURE;
4322 	}
4323 
4324 	if (fbc->type != ZEND_INTERNAL_FUNCTION) {
4325 		/* If the function is part of disabled_functions, it may be redeclared as a userland
4326 		 * function with a different implementation. Don't use the VM builtin in that case. */
4327 		return FAILURE;
4328 	}
4329 
4330 	if (zend_args_contain_unpack_or_named(args)) {
4331 		return FAILURE;
4332 	}
4333 
4334 	if (zend_string_equals_literal(lcname, "strlen")) {
4335 		return zend_compile_func_strlen(result, args);
4336 	} else if (zend_string_equals_literal(lcname, "is_null")) {
4337 		return zend_compile_func_typecheck(result, args, IS_NULL);
4338 	} else if (zend_string_equals_literal(lcname, "is_bool")) {
4339 		return zend_compile_func_typecheck(result, args, _IS_BOOL);
4340 	} else if (zend_string_equals_literal(lcname, "is_long")
4341 		|| zend_string_equals_literal(lcname, "is_int")
4342 		|| zend_string_equals_literal(lcname, "is_integer")
4343 	) {
4344 		return zend_compile_func_typecheck(result, args, IS_LONG);
4345 	} else if (zend_string_equals_literal(lcname, "is_float")
4346 		|| zend_string_equals_literal(lcname, "is_double")
4347 	) {
4348 		return zend_compile_func_typecheck(result, args, IS_DOUBLE);
4349 	} else if (zend_string_equals_literal(lcname, "is_string")) {
4350 		return zend_compile_func_typecheck(result, args, IS_STRING);
4351 	} else if (zend_string_equals_literal(lcname, "is_array")) {
4352 		return zend_compile_func_typecheck(result, args, IS_ARRAY);
4353 	} else if (zend_string_equals_literal(lcname, "is_object")) {
4354 		return zend_compile_func_typecheck(result, args, IS_OBJECT);
4355 	} else if (zend_string_equals_literal(lcname, "is_resource")) {
4356 		return zend_compile_func_typecheck(result, args, IS_RESOURCE);
4357 	} else if (zend_string_equals_literal(lcname, "is_scalar")) {
4358 		return zend_compile_func_is_scalar(result, args);
4359 	} else if (zend_string_equals_literal(lcname, "boolval")) {
4360 		return zend_compile_func_cast(result, args, _IS_BOOL);
4361 	} else if (zend_string_equals_literal(lcname, "intval")) {
4362 		return zend_compile_func_cast(result, args, IS_LONG);
4363 	} else if (zend_string_equals_literal(lcname, "floatval")
4364 		|| zend_string_equals_literal(lcname, "doubleval")
4365 	) {
4366 		return zend_compile_func_cast(result, args, IS_DOUBLE);
4367 	} else if (zend_string_equals_literal(lcname, "strval")) {
4368 		return zend_compile_func_cast(result, args, IS_STRING);
4369 	} else if (zend_string_equals_literal(lcname, "defined")) {
4370 		return zend_compile_func_defined(result, args);
4371 	} else if (zend_string_equals_literal(lcname, "chr") && type == BP_VAR_R) {
4372 		return zend_compile_func_chr(result, args);
4373 	} else if (zend_string_equals_literal(lcname, "ord") && type == BP_VAR_R) {
4374 		return zend_compile_func_ord(result, args);
4375 	} else if (zend_string_equals_literal(lcname, "call_user_func_array")) {
4376 		return zend_compile_func_cufa(result, args, lcname);
4377 	} else if (zend_string_equals_literal(lcname, "call_user_func")) {
4378 		return zend_compile_func_cuf(result, args, lcname);
4379 	} else if (zend_string_equals_literal(lcname, "in_array")) {
4380 		return zend_compile_func_in_array(result, args);
4381 	} else if (zend_string_equals_literal(lcname, "count")
4382 			|| zend_string_equals_literal(lcname, "sizeof")) {
4383 		return zend_compile_func_count(result, args, lcname);
4384 	} else if (zend_string_equals_literal(lcname, "get_class")) {
4385 		return zend_compile_func_get_class(result, args);
4386 	} else if (zend_string_equals_literal(lcname, "get_called_class")) {
4387 		return zend_compile_func_get_called_class(result, args);
4388 	} else if (zend_string_equals_literal(lcname, "gettype")) {
4389 		return zend_compile_func_gettype(result, args);
4390 	} else if (zend_string_equals_literal(lcname, "func_num_args")) {
4391 		return zend_compile_func_num_args(result, args);
4392 	} else if (zend_string_equals_literal(lcname, "func_get_args")) {
4393 		return zend_compile_func_get_args(result, args);
4394 	} else if (zend_string_equals_literal(lcname, "array_slice")) {
4395 		return zend_compile_func_array_slice(result, args);
4396 	} else if (zend_string_equals_literal(lcname, "array_key_exists")) {
4397 		return zend_compile_func_array_key_exists(result, args);
4398 	} else {
4399 		return FAILURE;
4400 	}
4401 }
4402 /* }}} */
4403 
zend_compile_call(znode * result,zend_ast * ast,uint32_t type)4404 static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
4405 {
4406 	zend_ast *name_ast = ast->child[0];
4407 	zend_ast *args_ast = ast->child[1];
4408 	bool is_callable_convert = args_ast->kind == ZEND_AST_CALLABLE_CONVERT;
4409 
4410 	znode name_node;
4411 
4412 	if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
4413 		zend_compile_expr(&name_node, name_ast);
4414 		zend_compile_dynamic_call(result, &name_node, args_ast);
4415 		return;
4416 	}
4417 
4418 	{
4419 		bool runtime_resolution = zend_compile_function_name(&name_node, name_ast);
4420 		if (runtime_resolution) {
4421 			if (zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "assert")
4422 					&& !is_callable_convert) {
4423 				zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL);
4424 			} else {
4425 				zend_compile_ns_call(result, &name_node, args_ast);
4426 			}
4427 			return;
4428 		}
4429 	}
4430 
4431 	{
4432 		zval *name = &name_node.u.constant;
4433 		zend_string *lcname;
4434 		zend_function *fbc;
4435 		zend_op *opline;
4436 
4437 		lcname = zend_string_tolower(Z_STR_P(name));
4438 		fbc = zend_hash_find_ptr(CG(function_table), lcname);
4439 
4440 		/* Special assert() handling should apply independently of compiler flags. */
4441 		if (fbc && zend_string_equals_literal(lcname, "assert") && !is_callable_convert) {
4442 			zend_compile_assert(result, zend_ast_get_list(args_ast), lcname, fbc);
4443 			zend_string_release(lcname);
4444 			zval_ptr_dtor(&name_node.u.constant);
4445 			return;
4446 		}
4447 
4448 		if (!fbc || !fbc_is_finalized(fbc)
4449 		 || (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
4450 		 || (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS))
4451 		 || (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && fbc->op_array.filename != CG(active_op_array)->filename)
4452 		) {
4453 			zend_string_release_ex(lcname, 0);
4454 			zend_compile_dynamic_call(result, &name_node, args_ast);
4455 			return;
4456 		}
4457 
4458 		if (!is_callable_convert &&
4459 		    zend_try_compile_special_func(result, lcname,
4460 				zend_ast_get_list(args_ast), fbc, type) == SUCCESS
4461 		) {
4462 			zend_string_release_ex(lcname, 0);
4463 			zval_ptr_dtor(&name_node.u.constant);
4464 			return;
4465 		}
4466 
4467 		zval_ptr_dtor(&name_node.u.constant);
4468 		ZVAL_NEW_STR(&name_node.u.constant, lcname);
4469 
4470 		opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
4471 		opline->result.num = zend_alloc_cache_slot();
4472 
4473 		zend_compile_call_common(result, args_ast, fbc);
4474 	}
4475 }
4476 /* }}} */
4477 
zend_compile_method_call(znode * result,zend_ast * ast,uint32_t type)4478 static void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
4479 {
4480 	zend_ast *obj_ast = ast->child[0];
4481 	zend_ast *method_ast = ast->child[1];
4482 	zend_ast *args_ast = ast->child[2];
4483 
4484 	znode obj_node, method_node;
4485 	zend_op *opline;
4486 	zend_function *fbc = NULL;
4487 	bool nullsafe = ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL;
4488 	uint32_t short_circuiting_checkpoint = zend_short_circuiting_checkpoint();
4489 
4490 	if (is_this_fetch(obj_ast)) {
4491 		if (this_guaranteed_exists()) {
4492 			obj_node.op_type = IS_UNUSED;
4493 		} else {
4494 			zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL);
4495 		}
4496 		CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
4497 
4498 		/* We will throw if $this doesn't exist, so there's no need to emit a JMP_NULL
4499 		 * check for a nullsafe access. */
4500 	} else {
4501 		zend_short_circuiting_mark_inner(obj_ast);
4502 		zend_compile_expr(&obj_node, obj_ast);
4503 		if (nullsafe) {
4504 			zend_emit_jmp_null(&obj_node);
4505 		}
4506 	}
4507 
4508 	zend_compile_expr(&method_node, method_ast);
4509 	opline = zend_emit_op(NULL, ZEND_INIT_METHOD_CALL, &obj_node, NULL);
4510 
4511 	if (method_node.op_type == IS_CONST) {
4512 		if (Z_TYPE(method_node.u.constant) != IS_STRING) {
4513 			zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
4514 		}
4515 
4516 		opline->op2_type = IS_CONST;
4517 		opline->op2.constant = zend_add_func_name_literal(
4518 			Z_STR(method_node.u.constant));
4519 		opline->result.num = zend_alloc_cache_slots(2);
4520 	} else {
4521 		SET_NODE(opline->op2, &method_node);
4522 	}
4523 
4524 	/* Check if this calls a known method on $this */
4525 	if (opline->op1_type == IS_UNUSED && opline->op2_type == IS_CONST &&
4526 			CG(active_class_entry) && zend_is_scope_known()) {
4527 		zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op2) + 1);
4528 		fbc = zend_hash_find_ptr(&CG(active_class_entry)->function_table, lcname);
4529 
4530 		/* We only know the exact method that is being called if it is either private or final.
4531 		 * Otherwise an overriding method in a child class may be called. */
4532 		if (fbc && !(fbc->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_FINAL))) {
4533 			fbc = NULL;
4534 		}
4535 	}
4536 
4537 	if (zend_compile_call_common(result, args_ast, fbc)) {
4538 		if (short_circuiting_checkpoint != zend_short_circuiting_checkpoint()) {
4539 			zend_error_noreturn(E_COMPILE_ERROR,
4540 				"Cannot combine nullsafe operator with Closure creation");
4541 		}
4542 	}
4543 }
4544 /* }}} */
4545 
zend_is_constructor(zend_string * name)4546 static bool zend_is_constructor(zend_string *name) /* {{{ */
4547 {
4548 	return zend_string_equals_literal_ci(name, ZEND_CONSTRUCTOR_FUNC_NAME);
4549 }
4550 /* }}} */
4551 
zend_get_compatible_func_or_null(zend_class_entry * ce,zend_string * lcname)4552 static zend_function *zend_get_compatible_func_or_null(zend_class_entry *ce, zend_string *lcname) /* {{{ */
4553 {
4554 	zend_function *fbc = zend_hash_find_ptr(&ce->function_table, lcname);
4555 	if (!fbc || (fbc->common.fn_flags & ZEND_ACC_PUBLIC) || ce == CG(active_class_entry)) {
4556 		return fbc;
4557 	}
4558 
4559 	if (!(fbc->common.fn_flags & ZEND_ACC_PRIVATE)
4560 		&& (fbc->common.scope->ce_flags & ZEND_ACC_LINKED)
4561 		&& (!CG(active_class_entry) || (CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED))
4562 		&& zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry))) {
4563 		return fbc;
4564 	}
4565 
4566 	return NULL;
4567 }
4568 /* }}} */
4569 
zend_compile_static_call(znode * result,zend_ast * ast,uint32_t type)4570 static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
4571 {
4572 	zend_ast *class_ast = ast->child[0];
4573 	zend_ast *method_ast = ast->child[1];
4574 	zend_ast *args_ast = ast->child[2];
4575 
4576 	znode class_node, method_node;
4577 	zend_op *opline;
4578 	zend_function *fbc = NULL;
4579 
4580 	zend_short_circuiting_mark_inner(class_ast);
4581 	zend_compile_class_ref(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
4582 
4583 	zend_compile_expr(&method_node, method_ast);
4584 
4585 	if (method_node.op_type == IS_CONST) {
4586 		zval *name = &method_node.u.constant;
4587 		if (Z_TYPE_P(name) != IS_STRING) {
4588 			zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
4589 		}
4590 		if (zend_is_constructor(Z_STR_P(name))) {
4591 			zval_ptr_dtor(name);
4592 			method_node.op_type = IS_UNUSED;
4593 		}
4594 	}
4595 
4596 	opline = get_next_op();
4597 	opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
4598 
4599 	zend_set_class_name_op1(opline, &class_node);
4600 
4601 	if (method_node.op_type == IS_CONST) {
4602 		opline->op2_type = IS_CONST;
4603 		opline->op2.constant = zend_add_func_name_literal(
4604 			Z_STR(method_node.u.constant));
4605 		opline->result.num = zend_alloc_cache_slots(2);
4606 	} else {
4607 		if (opline->op1_type == IS_CONST) {
4608 			opline->result.num = zend_alloc_cache_slot();
4609 		}
4610 		SET_NODE(opline->op2, &method_node);
4611 	}
4612 
4613 	/* Check if we already know which method we're calling */
4614 	if (opline->op2_type == IS_CONST) {
4615 		zend_class_entry *ce = NULL;
4616 		if (opline->op1_type == IS_CONST) {
4617 			zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op1) + 1);
4618 			ce = zend_hash_find_ptr(CG(class_table), lcname);
4619 			if (!ce && CG(active_class_entry)
4620 					&& zend_string_equals_ci(CG(active_class_entry)->name, lcname)) {
4621 				ce = CG(active_class_entry);
4622 			}
4623 		} else if (opline->op1_type == IS_UNUSED
4624 				&& (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF
4625 				&& zend_is_scope_known()) {
4626 			ce = CG(active_class_entry);
4627 		}
4628 		if (ce) {
4629 			zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op2) + 1);
4630 			fbc = zend_get_compatible_func_or_null(ce, lcname);
4631 		}
4632 	}
4633 
4634 	zend_compile_call_common(result, args_ast, fbc);
4635 }
4636 /* }}} */
4637 
4638 static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel);
4639 
zend_compile_new(znode * result,zend_ast * ast)4640 static void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
4641 {
4642 	zend_ast *class_ast = ast->child[0];
4643 	zend_ast *args_ast = ast->child[1];
4644 
4645 	znode class_node, ctor_result;
4646 	zend_op *opline;
4647 
4648 	if (class_ast->kind == ZEND_AST_CLASS) {
4649 		/* anon class declaration */
4650 		zend_compile_class_decl(&class_node, class_ast, 0);
4651 	} else {
4652 		zend_compile_class_ref(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
4653 	}
4654 
4655 	opline = zend_emit_op(result, ZEND_NEW, NULL, NULL);
4656 
4657 	if (class_node.op_type == IS_CONST) {
4658 		opline->op1_type = IS_CONST;
4659 		opline->op1.constant = zend_add_class_name_literal(
4660 			Z_STR(class_node.u.constant));
4661 		opline->op2.num = zend_alloc_cache_slot();
4662 	} else {
4663 		SET_NODE(opline->op1, &class_node);
4664 	}
4665 
4666 	zend_compile_call_common(&ctor_result, args_ast, NULL);
4667 	zend_do_free(&ctor_result);
4668 }
4669 /* }}} */
4670 
zend_compile_clone(znode * result,zend_ast * ast)4671 static void zend_compile_clone(znode *result, zend_ast *ast) /* {{{ */
4672 {
4673 	zend_ast *obj_ast = ast->child[0];
4674 
4675 	znode obj_node;
4676 	zend_compile_expr(&obj_node, obj_ast);
4677 
4678 	zend_emit_op_tmp(result, ZEND_CLONE, &obj_node, NULL);
4679 }
4680 /* }}} */
4681 
zend_compile_global_var(zend_ast * ast)4682 static void zend_compile_global_var(zend_ast *ast) /* {{{ */
4683 {
4684 	zend_ast *var_ast = ast->child[0];
4685 	zend_ast *name_ast = var_ast->child[0];
4686 
4687 	znode name_node, result;
4688 
4689 	zend_compile_expr(&name_node, name_ast);
4690 	if (name_node.op_type == IS_CONST) {
4691 		convert_to_string(&name_node.u.constant);
4692 	}
4693 
4694 	// TODO(GLOBALS) Forbid "global $GLOBALS"?
4695 	if (is_this_fetch(var_ast)) {
4696 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as global variable");
4697 	} else if (zend_try_compile_cv(&result, var_ast) == SUCCESS) {
4698 		zend_op *opline = zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node);
4699 		opline->extended_value = zend_alloc_cache_slot();
4700 	} else {
4701 		/* name_ast should be evaluated only. FETCH_GLOBAL_LOCK instructs FETCH_W
4702 		 * to not free the name_node operand, so it can be reused in the following
4703 		 * ASSIGN_REF, which then frees it. */
4704 		zend_op *opline = zend_emit_op(&result, ZEND_FETCH_W, &name_node, NULL);
4705 		opline->extended_value = ZEND_FETCH_GLOBAL_LOCK;
4706 
4707 		if (name_node.op_type == IS_CONST) {
4708 			zend_string_addref(Z_STR(name_node.u.constant));
4709 		}
4710 
4711 		zend_emit_assign_ref_znode(
4712 			zend_ast_create(ZEND_AST_VAR, zend_ast_create_znode(&name_node)),
4713 			&result
4714 		);
4715 	}
4716 }
4717 /* }}} */
4718 
zend_compile_static_var_common(zend_string * var_name,zval * value,uint32_t mode)4719 static void zend_compile_static_var_common(zend_string *var_name, zval *value, uint32_t mode) /* {{{ */
4720 {
4721 	zend_op *opline;
4722 	if (!CG(active_op_array)->static_variables) {
4723 		if (CG(active_op_array)->scope) {
4724 			CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
4725 		}
4726 		CG(active_op_array)->static_variables = zend_new_array(8);
4727 	}
4728 
4729 	value = zend_hash_update(CG(active_op_array)->static_variables, var_name, value);
4730 
4731 	if (zend_string_equals_literal(var_name, "this")) {
4732 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as static variable");
4733 	}
4734 
4735 	opline = zend_emit_op(NULL, ZEND_BIND_STATIC, NULL, NULL);
4736 	opline->op1_type = IS_CV;
4737 	opline->op1.var = lookup_cv(var_name);
4738 	opline->extended_value = (uint32_t)((char*)value - (char*)CG(active_op_array)->static_variables->arData) | mode;
4739 }
4740 /* }}} */
4741 
zend_compile_static_var(zend_ast * ast)4742 static void zend_compile_static_var(zend_ast *ast) /* {{{ */
4743 {
4744 	zend_ast *var_ast = ast->child[0];
4745 	zend_ast **value_ast_ptr = &ast->child[1];
4746 	zval value_zv;
4747 
4748 	if (*value_ast_ptr) {
4749 		zend_const_expr_to_zval(&value_zv, value_ast_ptr, /* allow_dynamic */ true);
4750 	} else {
4751 		ZVAL_NULL(&value_zv);
4752 	}
4753 
4754 	zend_compile_static_var_common(zend_ast_get_str(var_ast), &value_zv, ZEND_BIND_REF);
4755 }
4756 /* }}} */
4757 
zend_compile_unset(zend_ast * ast)4758 static void zend_compile_unset(zend_ast *ast) /* {{{ */
4759 {
4760 	zend_ast *var_ast = ast->child[0];
4761 	znode var_node;
4762 	zend_op *opline;
4763 
4764 	zend_ensure_writable_variable(var_ast);
4765 
4766 	if (is_global_var_fetch(var_ast)) {
4767 		if (!var_ast->child[1]) {
4768 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting");
4769 		}
4770 
4771 		zend_compile_expr(&var_node, var_ast->child[1]);
4772 		if (var_node.op_type == IS_CONST) {
4773 			convert_to_string(&var_node.u.constant);
4774 		}
4775 
4776 		opline = zend_emit_op(NULL, ZEND_UNSET_VAR, &var_node, NULL);
4777 		opline->extended_value = ZEND_FETCH_GLOBAL;
4778 		return;
4779 	}
4780 
4781 	switch (var_ast->kind) {
4782 		case ZEND_AST_VAR:
4783 			if (is_this_fetch(var_ast)) {
4784 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot unset $this");
4785 			} else if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) {
4786 				opline = zend_emit_op(NULL, ZEND_UNSET_CV, &var_node, NULL);
4787 			} else {
4788 				opline = zend_compile_simple_var_no_cv(NULL, var_ast, BP_VAR_UNSET, 0);
4789 				opline->opcode = ZEND_UNSET_VAR;
4790 			}
4791 			return;
4792 		case ZEND_AST_DIM:
4793 			opline = zend_compile_dim(NULL, var_ast, BP_VAR_UNSET);
4794 			opline->opcode = ZEND_UNSET_DIM;
4795 			return;
4796 		case ZEND_AST_PROP:
4797 		case ZEND_AST_NULLSAFE_PROP:
4798 			opline = zend_compile_prop(NULL, var_ast, BP_VAR_UNSET, 0);
4799 			opline->opcode = ZEND_UNSET_OBJ;
4800 			return;
4801 		case ZEND_AST_STATIC_PROP:
4802 			opline = zend_compile_static_prop(NULL, var_ast, BP_VAR_UNSET, 0, 0);
4803 			opline->opcode = ZEND_UNSET_STATIC_PROP;
4804 			return;
4805 		EMPTY_SWITCH_DEFAULT_CASE()
4806 	}
4807 }
4808 /* }}} */
4809 
zend_handle_loops_and_finally_ex(zend_long depth,znode * return_value)4810 static bool zend_handle_loops_and_finally_ex(zend_long depth, znode *return_value) /* {{{ */
4811 {
4812 	zend_loop_var *base;
4813 	zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack));
4814 
4815 	if (!loop_var) {
4816 		return 1;
4817 	}
4818 	base = zend_stack_base(&CG(loop_var_stack));
4819 	for (; loop_var >= base; loop_var--) {
4820 		if (loop_var->opcode == ZEND_FAST_CALL) {
4821 			zend_op *opline = get_next_op();
4822 
4823 			opline->opcode = ZEND_FAST_CALL;
4824 			opline->result_type = IS_TMP_VAR;
4825 			opline->result.var = loop_var->var_num;
4826 			if (return_value) {
4827 				SET_NODE(opline->op2, return_value);
4828 			}
4829 			opline->op1.num = loop_var->try_catch_offset;
4830 		} else if (loop_var->opcode == ZEND_DISCARD_EXCEPTION) {
4831 			zend_op *opline = get_next_op();
4832 			opline->opcode = ZEND_DISCARD_EXCEPTION;
4833 			opline->op1_type = IS_TMP_VAR;
4834 			opline->op1.var = loop_var->var_num;
4835 		} else if (loop_var->opcode == ZEND_RETURN) {
4836 			/* Stack separator */
4837 			break;
4838 		} else if (depth <= 1) {
4839 			return 1;
4840 		} else if (loop_var->opcode == ZEND_NOP) {
4841 			/* Loop doesn't have freeable variable */
4842 			depth--;
4843 		} else {
4844 			zend_op *opline;
4845 
4846 			ZEND_ASSERT(loop_var->var_type & (IS_VAR|IS_TMP_VAR));
4847 			opline = get_next_op();
4848 			opline->opcode = loop_var->opcode;
4849 			opline->op1_type = loop_var->var_type;
4850 			opline->op1.var = loop_var->var_num;
4851 			opline->extended_value = ZEND_FREE_ON_RETURN;
4852 			depth--;
4853 	    }
4854 	}
4855 	return (depth == 0);
4856 }
4857 /* }}} */
4858 
zend_handle_loops_and_finally(znode * return_value)4859 static bool zend_handle_loops_and_finally(znode *return_value) /* {{{ */
4860 {
4861 	return zend_handle_loops_and_finally_ex(zend_stack_count(&CG(loop_var_stack)) + 1, return_value);
4862 }
4863 /* }}} */
4864 
zend_has_finally_ex(zend_long depth)4865 static bool zend_has_finally_ex(zend_long depth) /* {{{ */
4866 {
4867 	zend_loop_var *base;
4868 	zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack));
4869 
4870 	if (!loop_var) {
4871 		return 0;
4872 	}
4873 	base = zend_stack_base(&CG(loop_var_stack));
4874 	for (; loop_var >= base; loop_var--) {
4875 		if (loop_var->opcode == ZEND_FAST_CALL) {
4876 			return 1;
4877 		} else if (loop_var->opcode == ZEND_DISCARD_EXCEPTION) {
4878 		} else if (loop_var->opcode == ZEND_RETURN) {
4879 			/* Stack separator */
4880 			return 0;
4881 		} else if (depth <= 1) {
4882 			return 0;
4883 		} else {
4884 			depth--;
4885 	    }
4886 	}
4887 	return 0;
4888 }
4889 /* }}} */
4890 
zend_has_finally(void)4891 static bool zend_has_finally(void) /* {{{ */
4892 {
4893 	return zend_has_finally_ex(zend_stack_count(&CG(loop_var_stack)) + 1);
4894 }
4895 /* }}} */
4896 
zend_compile_return(zend_ast * ast)4897 static void zend_compile_return(zend_ast *ast) /* {{{ */
4898 {
4899 	zend_ast *expr_ast = ast->child[0];
4900 	bool is_generator = (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0;
4901 	bool by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
4902 
4903 	znode expr_node;
4904 	zend_op *opline;
4905 
4906 	if (is_generator) {
4907 		/* For generators the by-ref flag refers to yields, not returns */
4908 		by_ref = 0;
4909 	}
4910 
4911 	if (!expr_ast) {
4912 		expr_node.op_type = IS_CONST;
4913 		ZVAL_NULL(&expr_node.u.constant);
4914 	} else if (by_ref && zend_is_variable(expr_ast)) {
4915 		if (zend_ast_is_short_circuited(expr_ast)) {
4916 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot take reference of a nullsafe chain");
4917 		}
4918 
4919 		zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1);
4920 	} else {
4921 		zend_compile_expr(&expr_node, expr_ast);
4922 	}
4923 
4924 	if ((CG(active_op_array)->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)
4925 	 && (expr_node.op_type == IS_CV || (by_ref && expr_node.op_type == IS_VAR))
4926 	 && zend_has_finally()) {
4927 		/* Copy return value into temporary VAR to avoid modification in finally code */
4928 		if (by_ref) {
4929 			zend_emit_op(&expr_node, ZEND_MAKE_REF, &expr_node, NULL);
4930 		} else {
4931 			zend_emit_op_tmp(&expr_node, ZEND_QM_ASSIGN, &expr_node, NULL);
4932 		}
4933 	}
4934 
4935 	/* Generator return types are handled separately */
4936 	if (!is_generator && (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
4937 		zend_emit_return_type_check(
4938 			expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1, 0);
4939 	}
4940 
4941 	zend_handle_loops_and_finally((expr_node.op_type & (IS_TMP_VAR | IS_VAR)) ? &expr_node : NULL);
4942 
4943 	opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN,
4944 		&expr_node, NULL);
4945 
4946 	if (by_ref && expr_ast) {
4947 		if (zend_is_call(expr_ast)) {
4948 			opline->extended_value = ZEND_RETURNS_FUNCTION;
4949 		} else if (!zend_is_variable(expr_ast) || zend_ast_is_short_circuited(expr_ast)) {
4950 			opline->extended_value = ZEND_RETURNS_VALUE;
4951 		}
4952 	}
4953 }
4954 /* }}} */
4955 
zend_compile_echo(zend_ast * ast)4956 static void zend_compile_echo(zend_ast *ast) /* {{{ */
4957 {
4958 	zend_op *opline;
4959 	zend_ast *expr_ast = ast->child[0];
4960 
4961 	znode expr_node;
4962 	zend_compile_expr(&expr_node, expr_ast);
4963 
4964 	opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL);
4965 	opline->extended_value = 0;
4966 }
4967 /* }}} */
4968 
zend_compile_throw(znode * result,zend_ast * ast)4969 static void zend_compile_throw(znode *result, zend_ast *ast) /* {{{ */
4970 {
4971 	zend_ast *expr_ast = ast->child[0];
4972 
4973 	znode expr_node;
4974 	zend_compile_expr(&expr_node, expr_ast);
4975 
4976 	zend_op *opline = zend_emit_op(NULL, ZEND_THROW, &expr_node, NULL);
4977 	if (result) {
4978 		/* Mark this as an "expression throw" for opcache. */
4979 		opline->extended_value = ZEND_THROW_IS_EXPR;
4980 		result->op_type = IS_CONST;
4981 		ZVAL_TRUE(&result->u.constant);
4982 	}
4983 }
4984 /* }}} */
4985 
zend_compile_break_continue(zend_ast * ast)4986 static void zend_compile_break_continue(zend_ast *ast) /* {{{ */
4987 {
4988 	zend_ast *depth_ast = ast->child[0];
4989 
4990 	zend_op *opline;
4991 	zend_long depth;
4992 
4993 	ZEND_ASSERT(ast->kind == ZEND_AST_BREAK || ast->kind == ZEND_AST_CONTINUE);
4994 
4995 	if (depth_ast) {
4996 		zval *depth_zv;
4997 		if (depth_ast->kind != ZEND_AST_ZVAL) {
4998 			zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-integer operand "
4999 				"is no longer supported", ast->kind == ZEND_AST_BREAK ? "break" : "continue");
5000 		}
5001 
5002 		depth_zv = zend_ast_get_zval(depth_ast);
5003 		if (Z_TYPE_P(depth_zv) != IS_LONG || Z_LVAL_P(depth_zv) < 1) {
5004 			zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive integers",
5005 				ast->kind == ZEND_AST_BREAK ? "break" : "continue");
5006 		}
5007 
5008 		depth = Z_LVAL_P(depth_zv);
5009 	} else {
5010 		depth = 1;
5011 	}
5012 
5013 	if (CG(context).current_brk_cont == -1) {
5014 		zend_error_noreturn(E_COMPILE_ERROR, "'%s' not in the 'loop' or 'switch' context",
5015 			ast->kind == ZEND_AST_BREAK ? "break" : "continue");
5016 	} else {
5017 		if (!zend_handle_loops_and_finally_ex(depth, NULL)) {
5018 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot '%s' " ZEND_LONG_FMT " level%s",
5019 				ast->kind == ZEND_AST_BREAK ? "break" : "continue",
5020 				depth, depth == 1 ? "" : "s");
5021 		}
5022 	}
5023 
5024 	if (ast->kind == ZEND_AST_CONTINUE) {
5025 		int d, cur = CG(context).current_brk_cont;
5026 		for (d = depth - 1; d > 0; d--) {
5027 			cur = CG(context).brk_cont_array[cur].parent;
5028 			ZEND_ASSERT(cur != -1);
5029 		}
5030 
5031 		if (CG(context).brk_cont_array[cur].is_switch) {
5032 			if (depth == 1) {
5033 				if (CG(context).brk_cont_array[cur].parent == -1) {
5034 					zend_error(E_WARNING,
5035 						"\"continue\" targeting switch is equivalent to \"break\"");
5036 				} else {
5037 					zend_error(E_WARNING,
5038 						"\"continue\" targeting switch is equivalent to \"break\". " \
5039 						"Did you mean to use \"continue " ZEND_LONG_FMT "\"?",
5040 						depth + 1);
5041 				}
5042 			} else {
5043 				if (CG(context).brk_cont_array[cur].parent == -1) {
5044 					zend_error(E_WARNING,
5045 						"\"continue " ZEND_LONG_FMT "\" targeting switch is equivalent to \"break " ZEND_LONG_FMT "\"",
5046 						depth, depth);
5047 				} else {
5048 					zend_error(E_WARNING,
5049 						"\"continue " ZEND_LONG_FMT "\" targeting switch is equivalent to \"break " ZEND_LONG_FMT "\". " \
5050 						"Did you mean to use \"continue " ZEND_LONG_FMT "\"?",
5051 						depth, depth, depth + 1);
5052 				}
5053 			}
5054 		}
5055 	}
5056 
5057 	opline = zend_emit_op(NULL, ast->kind == ZEND_AST_BREAK ? ZEND_BRK : ZEND_CONT, NULL, NULL);
5058 	opline->op1.num = CG(context).current_brk_cont;
5059 	opline->op2.num = depth;
5060 }
5061 /* }}} */
5062 
zend_resolve_goto_label(zend_op_array * op_array,zend_op * opline)5063 void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline) /* {{{ */
5064 {
5065 	zend_label *dest;
5066 	int current, remove_oplines = opline->op1.num;
5067 	zval *label;
5068 	uint32_t opnum = opline - op_array->opcodes;
5069 
5070 	label = CT_CONSTANT_EX(op_array, opline->op2.constant);
5071 	if (CG(context).labels == NULL ||
5072 	    (dest = zend_hash_find_ptr(CG(context).labels, Z_STR_P(label))) == NULL
5073 	) {
5074 		CG(in_compilation) = 1;
5075 		CG(active_op_array) = op_array;
5076 		CG(zend_lineno) = opline->lineno;
5077 		zend_error_noreturn(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL_P(label));
5078 	}
5079 
5080 	zval_ptr_dtor_str(label);
5081 	ZVAL_NULL(label);
5082 
5083 	current = opline->extended_value;
5084 	for (; current != dest->brk_cont; current = CG(context).brk_cont_array[current].parent) {
5085 		if (current == -1) {
5086 			CG(in_compilation) = 1;
5087 			CG(active_op_array) = op_array;
5088 			CG(zend_lineno) = opline->lineno;
5089 			zend_error_noreturn(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
5090 		}
5091 		if (CG(context).brk_cont_array[current].start >= 0) {
5092 			remove_oplines--;
5093 		}
5094 	}
5095 
5096 	for (current = 0; current < op_array->last_try_catch; ++current) {
5097 		zend_try_catch_element *elem = &op_array->try_catch_array[current];
5098 		if (elem->try_op > opnum) {
5099 			break;
5100 		}
5101 		if (elem->finally_op && opnum < elem->finally_op - 1
5102 			&& (dest->opline_num > elem->finally_end || dest->opline_num < elem->try_op)
5103 		) {
5104 			remove_oplines--;
5105 		}
5106 	}
5107 
5108 	opline->opcode = ZEND_JMP;
5109 	opline->op1.opline_num = dest->opline_num;
5110 	opline->extended_value = 0;
5111 	SET_UNUSED(opline->op1);
5112 	SET_UNUSED(opline->op2);
5113 	SET_UNUSED(opline->result);
5114 
5115 	ZEND_ASSERT(remove_oplines >= 0);
5116 	while (remove_oplines--) {
5117 		opline--;
5118 		MAKE_NOP(opline);
5119 		ZEND_VM_SET_OPCODE_HANDLER(opline);
5120 	}
5121 }
5122 /* }}} */
5123 
zend_compile_goto(zend_ast * ast)5124 static void zend_compile_goto(zend_ast *ast) /* {{{ */
5125 {
5126 	zend_ast *label_ast = ast->child[0];
5127 	znode label_node;
5128 	zend_op *opline;
5129 	uint32_t opnum_start = get_next_op_number();
5130 
5131 	zend_compile_expr(&label_node, label_ast);
5132 
5133 	/* Label resolution and unwinding adjustments happen in pass two. */
5134 	zend_handle_loops_and_finally(NULL);
5135 	opline = zend_emit_op(NULL, ZEND_GOTO, NULL, &label_node);
5136 	opline->op1.num = get_next_op_number() - opnum_start - 1;
5137 	opline->extended_value = CG(context).current_brk_cont;
5138 }
5139 /* }}} */
5140 
zend_compile_label(zend_ast * ast)5141 static void zend_compile_label(zend_ast *ast) /* {{{ */
5142 {
5143 	zend_string *label = zend_ast_get_str(ast->child[0]);
5144 	zend_label dest;
5145 
5146 	if (!CG(context).labels) {
5147 		ALLOC_HASHTABLE(CG(context).labels);
5148 		zend_hash_init(CG(context).labels, 8, NULL, label_ptr_dtor, 0);
5149 	}
5150 
5151 	dest.brk_cont = CG(context).current_brk_cont;
5152 	dest.opline_num = get_next_op_number();
5153 
5154 	if (!zend_hash_add_mem(CG(context).labels, label, &dest, sizeof(zend_label))) {
5155 		zend_error_noreturn(E_COMPILE_ERROR, "Label '%s' already defined", ZSTR_VAL(label));
5156 	}
5157 }
5158 /* }}} */
5159 
zend_compile_while(zend_ast * ast)5160 static void zend_compile_while(zend_ast *ast) /* {{{ */
5161 {
5162 	zend_ast *cond_ast = ast->child[0];
5163 	zend_ast *stmt_ast = ast->child[1];
5164 	znode cond_node;
5165 	uint32_t opnum_start, opnum_jmp, opnum_cond;
5166 
5167 	opnum_jmp = zend_emit_jump(0);
5168 
5169 	zend_begin_loop(ZEND_NOP, NULL, 0);
5170 
5171 	opnum_start = get_next_op_number();
5172 	zend_compile_stmt(stmt_ast);
5173 
5174 	opnum_cond = get_next_op_number();
5175 	zend_update_jump_target(opnum_jmp, opnum_cond);
5176 	zend_compile_expr(&cond_node, cond_ast);
5177 
5178 	zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
5179 
5180 	zend_end_loop(opnum_cond, NULL);
5181 }
5182 /* }}} */
5183 
zend_compile_do_while(zend_ast * ast)5184 static void zend_compile_do_while(zend_ast *ast) /* {{{ */
5185 {
5186 	zend_ast *stmt_ast = ast->child[0];
5187 	zend_ast *cond_ast = ast->child[1];
5188 
5189 	znode cond_node;
5190 	uint32_t opnum_start, opnum_cond;
5191 
5192 	zend_begin_loop(ZEND_NOP, NULL, 0);
5193 
5194 	opnum_start = get_next_op_number();
5195 	zend_compile_stmt(stmt_ast);
5196 
5197 	opnum_cond = get_next_op_number();
5198 	zend_compile_expr(&cond_node, cond_ast);
5199 
5200 	zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
5201 
5202 	zend_end_loop(opnum_cond, NULL);
5203 }
5204 /* }}} */
5205 
zend_compile_expr_list(znode * result,zend_ast * ast)5206 static void zend_compile_expr_list(znode *result, zend_ast *ast) /* {{{ */
5207 {
5208 	zend_ast_list *list;
5209 	uint32_t i;
5210 
5211 	result->op_type = IS_CONST;
5212 	ZVAL_TRUE(&result->u.constant);
5213 
5214 	if (!ast) {
5215 		return;
5216 	}
5217 
5218 	list = zend_ast_get_list(ast);
5219 	for (i = 0; i < list->children; ++i) {
5220 		zend_ast *expr_ast = list->child[i];
5221 
5222 		zend_do_free(result);
5223 		zend_compile_expr(result, expr_ast);
5224 	}
5225 }
5226 /* }}} */
5227 
zend_compile_for(zend_ast * ast)5228 static void zend_compile_for(zend_ast *ast) /* {{{ */
5229 {
5230 	zend_ast *init_ast = ast->child[0];
5231 	zend_ast *cond_ast = ast->child[1];
5232 	zend_ast *loop_ast = ast->child[2];
5233 	zend_ast *stmt_ast = ast->child[3];
5234 
5235 	znode result;
5236 	uint32_t opnum_start, opnum_jmp, opnum_loop;
5237 
5238 	zend_compile_expr_list(&result, init_ast);
5239 	zend_do_free(&result);
5240 
5241 	opnum_jmp = zend_emit_jump(0);
5242 
5243 	zend_begin_loop(ZEND_NOP, NULL, 0);
5244 
5245 	opnum_start = get_next_op_number();
5246 	zend_compile_stmt(stmt_ast);
5247 
5248 	opnum_loop = get_next_op_number();
5249 	zend_compile_expr_list(&result, loop_ast);
5250 	zend_do_free(&result);
5251 
5252 	zend_update_jump_target_to_next(opnum_jmp);
5253 	zend_compile_expr_list(&result, cond_ast);
5254 	zend_do_extended_stmt();
5255 
5256 	zend_emit_cond_jump(ZEND_JMPNZ, &result, opnum_start);
5257 
5258 	zend_end_loop(opnum_loop, NULL);
5259 }
5260 /* }}} */
5261 
zend_compile_foreach(zend_ast * ast)5262 static void zend_compile_foreach(zend_ast *ast) /* {{{ */
5263 {
5264 	zend_ast *expr_ast = ast->child[0];
5265 	zend_ast *value_ast = ast->child[1];
5266 	zend_ast *key_ast = ast->child[2];
5267 	zend_ast *stmt_ast = ast->child[3];
5268 	bool by_ref = value_ast->kind == ZEND_AST_REF;
5269 	bool is_variable = zend_is_variable(expr_ast) && zend_can_write_to_variable(expr_ast);
5270 
5271 	znode expr_node, reset_node, value_node, key_node;
5272 	zend_op *opline;
5273 	uint32_t opnum_reset, opnum_fetch;
5274 
5275 	if (key_ast) {
5276 		if (key_ast->kind == ZEND_AST_REF) {
5277 			zend_error_noreturn(E_COMPILE_ERROR, "Key element cannot be a reference");
5278 		}
5279 		if (key_ast->kind == ZEND_AST_ARRAY) {
5280 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use list as key element");
5281 		}
5282 	}
5283 
5284 	if (by_ref) {
5285 		value_ast = value_ast->child[0];
5286 	}
5287 
5288 	if (value_ast->kind == ZEND_AST_ARRAY && zend_propagate_list_refs(value_ast)) {
5289 		by_ref = 1;
5290 	}
5291 
5292 	if (by_ref && is_variable) {
5293 		zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1);
5294 	} else {
5295 		zend_compile_expr(&expr_node, expr_ast);
5296 	}
5297 
5298 	if (by_ref) {
5299 		zend_separate_if_call_and_write(&expr_node, expr_ast, BP_VAR_W);
5300 	}
5301 
5302 	opnum_reset = get_next_op_number();
5303 	opline = zend_emit_op(&reset_node, by_ref ? ZEND_FE_RESET_RW : ZEND_FE_RESET_R, &expr_node, NULL);
5304 
5305 	zend_begin_loop(ZEND_FE_FREE, &reset_node, 0);
5306 
5307 	opnum_fetch = get_next_op_number();
5308 	opline = zend_emit_op(NULL, by_ref ? ZEND_FE_FETCH_RW : ZEND_FE_FETCH_R, &reset_node, NULL);
5309 
5310 	if (is_this_fetch(value_ast)) {
5311 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
5312 	} else if (value_ast->kind == ZEND_AST_VAR &&
5313 		zend_try_compile_cv(&value_node, value_ast) == SUCCESS) {
5314 		SET_NODE(opline->op2, &value_node);
5315 	} else {
5316 		opline->op2_type = IS_VAR;
5317 		opline->op2.var = get_temporary_variable();
5318 		GET_NODE(&value_node, opline->op2);
5319 		if (value_ast->kind == ZEND_AST_ARRAY) {
5320 			zend_compile_list_assign(NULL, value_ast, &value_node, value_ast->attr);
5321 		} else if (by_ref) {
5322 			zend_emit_assign_ref_znode(value_ast, &value_node);
5323 		} else {
5324 			zend_emit_assign_znode(value_ast, &value_node);
5325 		}
5326 	}
5327 
5328 	if (key_ast) {
5329 		opline = &CG(active_op_array)->opcodes[opnum_fetch];
5330 		zend_make_tmp_result(&key_node, opline);
5331 		zend_emit_assign_znode(key_ast, &key_node);
5332 	}
5333 
5334 	zend_compile_stmt(stmt_ast);
5335 
5336 	/* Place JMP and FE_FREE on the line where foreach starts. It would be
5337 	 * better to use the end line, but this information is not available
5338 	 * currently. */
5339 	CG(zend_lineno) = ast->lineno;
5340 	zend_emit_jump(opnum_fetch);
5341 
5342 	opline = &CG(active_op_array)->opcodes[opnum_reset];
5343 	opline->op2.opline_num = get_next_op_number();
5344 
5345 	opline = &CG(active_op_array)->opcodes[opnum_fetch];
5346 	opline->extended_value = get_next_op_number();
5347 
5348 	zend_end_loop(opnum_fetch, &reset_node);
5349 
5350 	opline = zend_emit_op(NULL, ZEND_FE_FREE, &reset_node, NULL);
5351 }
5352 /* }}} */
5353 
zend_compile_if(zend_ast * ast)5354 static void zend_compile_if(zend_ast *ast) /* {{{ */
5355 {
5356 	zend_ast_list *list = zend_ast_get_list(ast);
5357 	uint32_t i;
5358 	uint32_t *jmp_opnums = NULL;
5359 
5360 	if (list->children > 1) {
5361 		jmp_opnums = safe_emalloc(sizeof(uint32_t), list->children - 1, 0);
5362 	}
5363 
5364 	for (i = 0; i < list->children; ++i) {
5365 		zend_ast *elem_ast = list->child[i];
5366 		zend_ast *cond_ast = elem_ast->child[0];
5367 		zend_ast *stmt_ast = elem_ast->child[1];
5368 
5369 		if (cond_ast) {
5370 			znode cond_node;
5371 			uint32_t opnum_jmpz;
5372 			zend_compile_expr(&cond_node, cond_ast);
5373 			opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
5374 
5375 			zend_compile_stmt(stmt_ast);
5376 
5377 			if (i != list->children - 1) {
5378 				jmp_opnums[i] = zend_emit_jump(0);
5379 			}
5380 			zend_update_jump_target_to_next(opnum_jmpz);
5381 		} else {
5382 			/* "else" can only occur as last element. */
5383 			ZEND_ASSERT(i == list->children - 1);
5384 			zend_compile_stmt(stmt_ast);
5385 		}
5386 	}
5387 
5388 	if (list->children > 1) {
5389 		for (i = 0; i < list->children - 1; ++i) {
5390 			zend_update_jump_target_to_next(jmp_opnums[i]);
5391 		}
5392 		efree(jmp_opnums);
5393 	}
5394 }
5395 /* }}} */
5396 
determine_switch_jumptable_type(zend_ast_list * cases)5397 static zend_uchar determine_switch_jumptable_type(zend_ast_list *cases) {
5398 	uint32_t i;
5399 	zend_uchar common_type = IS_UNDEF;
5400 	for (i = 0; i < cases->children; i++) {
5401 		zend_ast *case_ast = cases->child[i];
5402 		zend_ast **cond_ast = &case_ast->child[0];
5403 		zval *cond_zv;
5404 		if (!case_ast->child[0]) {
5405 			/* Skip default clause */
5406 			continue;
5407 		}
5408 
5409 		zend_eval_const_expr(cond_ast);
5410 		if ((*cond_ast)->kind != ZEND_AST_ZVAL) {
5411 			/* Non-constant case */
5412 			return IS_UNDEF;
5413 		}
5414 
5415 		cond_zv = zend_ast_get_zval(case_ast->child[0]);
5416 		if (Z_TYPE_P(cond_zv) != IS_LONG && Z_TYPE_P(cond_zv) != IS_STRING) {
5417 			/* We only optimize switched on integers and strings */
5418 			return IS_UNDEF;
5419 		}
5420 
5421 		if (common_type == IS_UNDEF) {
5422 			common_type = Z_TYPE_P(cond_zv);
5423 		} else if (common_type != Z_TYPE_P(cond_zv)) {
5424 			/* Non-uniform case types */
5425 			return IS_UNDEF;
5426 		}
5427 
5428 		if (Z_TYPE_P(cond_zv) == IS_STRING
5429 				&& is_numeric_string(Z_STRVAL_P(cond_zv), Z_STRLEN_P(cond_zv), NULL, NULL, 0)) {
5430 			/* Numeric strings cannot be compared with a simple hash lookup */
5431 			return IS_UNDEF;
5432 		}
5433 	}
5434 
5435 	return common_type;
5436 }
5437 
should_use_jumptable(zend_ast_list * cases,zend_uchar jumptable_type)5438 static bool should_use_jumptable(zend_ast_list *cases, zend_uchar jumptable_type) {
5439 	if (CG(compiler_options) & ZEND_COMPILE_NO_JUMPTABLES) {
5440 		return 0;
5441 	}
5442 
5443 	/* Thresholds are chosen based on when the average switch time for equidistributed
5444 	 * input becomes smaller when using the jumptable optimization. */
5445 	if (jumptable_type == IS_LONG) {
5446 		return cases->children >= 5;
5447 	} else {
5448 		ZEND_ASSERT(jumptable_type == IS_STRING);
5449 		return cases->children >= 2;
5450 	}
5451 }
5452 
zend_compile_switch(zend_ast * ast)5453 static void zend_compile_switch(zend_ast *ast) /* {{{ */
5454 {
5455 	zend_ast *expr_ast = ast->child[0];
5456 	zend_ast_list *cases = zend_ast_get_list(ast->child[1]);
5457 
5458 	uint32_t i;
5459 	bool has_default_case = 0;
5460 
5461 	znode expr_node, case_node;
5462 	zend_op *opline;
5463 	uint32_t *jmpnz_opnums, opnum_default_jmp, opnum_switch = (uint32_t)-1;
5464 	zend_uchar jumptable_type;
5465 	HashTable *jumptable = NULL;
5466 
5467 	zend_compile_expr(&expr_node, expr_ast);
5468 
5469 	zend_begin_loop(ZEND_FREE, &expr_node, 1);
5470 
5471 	case_node.op_type = IS_TMP_VAR;
5472 	case_node.u.op.var = get_temporary_variable();
5473 
5474 	jumptable_type = determine_switch_jumptable_type(cases);
5475 	if (jumptable_type != IS_UNDEF && should_use_jumptable(cases, jumptable_type)) {
5476 		znode jumptable_op;
5477 
5478 		ALLOC_HASHTABLE(jumptable);
5479 		zend_hash_init(jumptable, cases->children, NULL, NULL, 0);
5480 		jumptable_op.op_type = IS_CONST;
5481 		ZVAL_ARR(&jumptable_op.u.constant, jumptable);
5482 
5483 		opline = zend_emit_op(NULL,
5484 			jumptable_type == IS_LONG ? ZEND_SWITCH_LONG : ZEND_SWITCH_STRING,
5485 			&expr_node, &jumptable_op);
5486 		if (opline->op1_type == IS_CONST) {
5487 			Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
5488 		}
5489 		opnum_switch = opline - CG(active_op_array)->opcodes;
5490 	}
5491 
5492 	jmpnz_opnums = safe_emalloc(sizeof(uint32_t), cases->children, 0);
5493 	for (i = 0; i < cases->children; ++i) {
5494 		zend_ast *case_ast = cases->child[i];
5495 		zend_ast *cond_ast = case_ast->child[0];
5496 		znode cond_node;
5497 
5498 		if (!cond_ast) {
5499 			if (has_default_case) {
5500 				CG(zend_lineno) = case_ast->lineno;
5501 				zend_error_noreturn(E_COMPILE_ERROR,
5502 					"Switch statements may only contain one default clause");
5503 			}
5504 			has_default_case = 1;
5505 			continue;
5506 		}
5507 
5508 		zend_compile_expr(&cond_node, cond_ast);
5509 
5510 		if (expr_node.op_type == IS_CONST
5511 			&& Z_TYPE(expr_node.u.constant) == IS_FALSE) {
5512 			jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
5513 		} else if (expr_node.op_type == IS_CONST
5514 			&& Z_TYPE(expr_node.u.constant) == IS_TRUE) {
5515 			jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, 0);
5516 		} else {
5517 			opline = zend_emit_op(NULL,
5518 				(expr_node.op_type & (IS_VAR|IS_TMP_VAR)) ? ZEND_CASE : ZEND_IS_EQUAL,
5519 				&expr_node, &cond_node);
5520 			SET_NODE(opline->result, &case_node);
5521 			if (opline->op1_type == IS_CONST) {
5522 				Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
5523 			}
5524 
5525 			jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0);
5526 		}
5527 	}
5528 
5529 	opnum_default_jmp = zend_emit_jump(0);
5530 
5531 	for (i = 0; i < cases->children; ++i) {
5532 		zend_ast *case_ast = cases->child[i];
5533 		zend_ast *cond_ast = case_ast->child[0];
5534 		zend_ast *stmt_ast = case_ast->child[1];
5535 
5536 		if (cond_ast) {
5537 			zend_update_jump_target_to_next(jmpnz_opnums[i]);
5538 
5539 			if (jumptable) {
5540 				zval *cond_zv = zend_ast_get_zval(cond_ast);
5541 				zval jmp_target;
5542 				ZVAL_LONG(&jmp_target, get_next_op_number());
5543 
5544 				ZEND_ASSERT(Z_TYPE_P(cond_zv) == jumptable_type);
5545 				if (Z_TYPE_P(cond_zv) == IS_LONG) {
5546 					zend_hash_index_add(jumptable, Z_LVAL_P(cond_zv), &jmp_target);
5547 				} else {
5548 					ZEND_ASSERT(Z_TYPE_P(cond_zv) == IS_STRING);
5549 					zend_hash_add(jumptable, Z_STR_P(cond_zv), &jmp_target);
5550 				}
5551 			}
5552 		} else {
5553 			zend_update_jump_target_to_next(opnum_default_jmp);
5554 
5555 			if (jumptable) {
5556 				ZEND_ASSERT(opnum_switch != (uint32_t)-1);
5557 				opline = &CG(active_op_array)->opcodes[opnum_switch];
5558 				opline->extended_value = get_next_op_number();
5559 			}
5560 		}
5561 
5562 		zend_compile_stmt(stmt_ast);
5563 	}
5564 
5565 	if (!has_default_case) {
5566 		zend_update_jump_target_to_next(opnum_default_jmp);
5567 
5568 		if (jumptable) {
5569 			opline = &CG(active_op_array)->opcodes[opnum_switch];
5570 			opline->extended_value = get_next_op_number();
5571 		}
5572 	}
5573 
5574 	zend_end_loop(get_next_op_number(), &expr_node);
5575 
5576 	if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) {
5577 		opline = zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
5578 		opline->extended_value = ZEND_FREE_SWITCH;
5579 	} else if (expr_node.op_type == IS_CONST) {
5580 		zval_ptr_dtor_nogc(&expr_node.u.constant);
5581 	}
5582 
5583 	efree(jmpnz_opnums);
5584 }
5585 /* }}} */
5586 
count_match_conds(zend_ast_list * arms)5587 static uint32_t count_match_conds(zend_ast_list *arms)
5588 {
5589 	uint32_t num_conds = 0;
5590 
5591 	for (uint32_t i = 0; i < arms->children; i++) {
5592 		zend_ast *arm_ast = arms->child[i];
5593 		if (arm_ast->child[0] == NULL) {
5594 			continue;
5595 		}
5596 
5597 		zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
5598 		num_conds += conds->children;
5599 	}
5600 
5601 	return num_conds;
5602 }
5603 
can_match_use_jumptable(zend_ast_list * arms)5604 static bool can_match_use_jumptable(zend_ast_list *arms) {
5605 	for (uint32_t i = 0; i < arms->children; i++) {
5606 		zend_ast *arm_ast = arms->child[i];
5607 		if (!arm_ast->child[0]) {
5608 			/* Skip default arm */
5609 			continue;
5610 		}
5611 
5612 		zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
5613 		for (uint32_t j = 0; j < conds->children; j++) {
5614 			zend_ast **cond_ast = &conds->child[j];
5615 
5616 			zend_eval_const_expr(cond_ast);
5617 			if ((*cond_ast)->kind != ZEND_AST_ZVAL) {
5618 				return 0;
5619 			}
5620 
5621 			zval *cond_zv = zend_ast_get_zval(*cond_ast);
5622 			if (Z_TYPE_P(cond_zv) != IS_LONG && Z_TYPE_P(cond_zv) != IS_STRING) {
5623 				return 0;
5624 			}
5625 		}
5626 	}
5627 
5628 	return 1;
5629 }
5630 
zend_compile_match(znode * result,zend_ast * ast)5631 static void zend_compile_match(znode *result, zend_ast *ast)
5632 {
5633 	zend_ast *expr_ast = ast->child[0];
5634 	zend_ast_list *arms = zend_ast_get_list(ast->child[1]);
5635 	bool has_default_arm = 0;
5636 	uint32_t opnum_match = (uint32_t)-1;
5637 
5638 	znode expr_node;
5639 	zend_compile_expr(&expr_node, expr_ast);
5640 
5641 	znode case_node;
5642 	case_node.op_type = IS_TMP_VAR;
5643 	case_node.u.op.var = get_temporary_variable();
5644 
5645 	uint32_t num_conds = count_match_conds(arms);
5646 	zend_uchar can_use_jumptable = can_match_use_jumptable(arms);
5647 	bool uses_jumptable = can_use_jumptable && num_conds >= 2;
5648 	HashTable *jumptable = NULL;
5649 	uint32_t *jmpnz_opnums = NULL;
5650 
5651 	for (uint32_t i = 0; i < arms->children; ++i) {
5652 		zend_ast *arm_ast = arms->child[i];
5653 
5654 		if (!arm_ast->child[0]) {
5655 			if (has_default_arm) {
5656 				CG(zend_lineno) = arm_ast->lineno;
5657 				zend_error_noreturn(E_COMPILE_ERROR,
5658 					"Match expressions may only contain one default arm");
5659 			}
5660 			has_default_arm = 1;
5661 		}
5662 	}
5663 
5664 	if (uses_jumptable) {
5665 		znode jumptable_op;
5666 
5667 		ALLOC_HASHTABLE(jumptable);
5668 		zend_hash_init(jumptable, num_conds, NULL, NULL, 0);
5669 		jumptable_op.op_type = IS_CONST;
5670 		ZVAL_ARR(&jumptable_op.u.constant, jumptable);
5671 
5672 		zend_op *opline = zend_emit_op(NULL, ZEND_MATCH, &expr_node, &jumptable_op);
5673 		if (opline->op1_type == IS_CONST) {
5674 			Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
5675 		}
5676 		opnum_match = opline - CG(active_op_array)->opcodes;
5677 	} else {
5678 		jmpnz_opnums = safe_emalloc(sizeof(uint32_t), num_conds, 0);
5679 		uint32_t cond_count = 0;
5680 		for (uint32_t i = 0; i < arms->children; ++i) {
5681 			zend_ast *arm_ast = arms->child[i];
5682 
5683 			if (!arm_ast->child[0]) {
5684 				continue;
5685 			}
5686 
5687 			zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
5688 			for (uint32_t j = 0; j < conds->children; j++) {
5689 				zend_ast *cond_ast = conds->child[j];
5690 
5691 				znode cond_node;
5692 				zend_compile_expr(&cond_node, cond_ast);
5693 
5694 				uint32_t opcode = (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) ? ZEND_CASE_STRICT : ZEND_IS_IDENTICAL;
5695 				zend_op *opline = zend_emit_op(NULL, opcode, &expr_node, &cond_node);
5696 				SET_NODE(opline->result, &case_node);
5697 				if (opline->op1_type == IS_CONST) {
5698 					Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
5699 				}
5700 
5701 				jmpnz_opnums[cond_count] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0);
5702 
5703 				cond_count++;
5704 			}
5705 		}
5706 	}
5707 
5708 	uint32_t opnum_default_jmp = 0;
5709 	if (!uses_jumptable) {
5710 		opnum_default_jmp = zend_emit_jump(0);
5711 	}
5712 
5713 	bool is_first_case = 1;
5714 	uint32_t cond_count = 0;
5715 	uint32_t *jmp_end_opnums = safe_emalloc(sizeof(uint32_t), arms->children, 0);
5716 
5717 	// The generated default arm is emitted first to avoid live range issues where the tmpvar
5718 	// for the arm result is freed even though it has not been initialized yet.
5719 	if (!has_default_arm) {
5720 		if (!uses_jumptable) {
5721 			zend_update_jump_target_to_next(opnum_default_jmp);
5722 		}
5723 
5724 		if (jumptable) {
5725 			zend_op *opline = &CG(active_op_array)->opcodes[opnum_match];
5726 			opline->extended_value = get_next_op_number();
5727 		}
5728 
5729 		zend_op *opline = zend_emit_op(NULL, ZEND_MATCH_ERROR, &expr_node, NULL);
5730 		if (opline->op1_type == IS_CONST) {
5731 			Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
5732 		}
5733 	}
5734 
5735 	for (uint32_t i = 0; i < arms->children; ++i) {
5736 		zend_ast *arm_ast = arms->child[i];
5737 		zend_ast *body_ast = arm_ast->child[1];
5738 
5739 		if (arm_ast->child[0] != NULL) {
5740 			zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
5741 
5742 			for (uint32_t j = 0; j < conds->children; j++) {
5743 				zend_ast *cond_ast = conds->child[j];
5744 
5745 				if (jmpnz_opnums != NULL) {
5746 					zend_update_jump_target_to_next(jmpnz_opnums[cond_count]);
5747 				}
5748 
5749 				if (jumptable) {
5750 					zval *cond_zv = zend_ast_get_zval(cond_ast);
5751 					zval jmp_target;
5752 					ZVAL_LONG(&jmp_target, get_next_op_number());
5753 
5754 					if (Z_TYPE_P(cond_zv) == IS_LONG) {
5755 						zend_hash_index_add(jumptable, Z_LVAL_P(cond_zv), &jmp_target);
5756 					} else {
5757 						ZEND_ASSERT(Z_TYPE_P(cond_zv) == IS_STRING);
5758 						zend_hash_add(jumptable, Z_STR_P(cond_zv), &jmp_target);
5759 					}
5760 				}
5761 
5762 				cond_count++;
5763 			}
5764 		} else {
5765 			if (!uses_jumptable) {
5766 				zend_update_jump_target_to_next(opnum_default_jmp);
5767 			}
5768 
5769 			if (jumptable) {
5770 				ZEND_ASSERT(opnum_match != (uint32_t)-1);
5771 				zend_op *opline = &CG(active_op_array)->opcodes[opnum_match];
5772 				opline->extended_value = get_next_op_number();
5773 			}
5774 		}
5775 
5776 		znode body_node;
5777 		zend_compile_expr(&body_node, body_ast);
5778 
5779 		if (is_first_case) {
5780 			zend_emit_op_tmp(result, ZEND_QM_ASSIGN, &body_node, NULL);
5781 			is_first_case = 0;
5782 		} else {
5783 			zend_op *opline_qm_assign = zend_emit_op(NULL, ZEND_QM_ASSIGN, &body_node, NULL);
5784 			SET_NODE(opline_qm_assign->result, result);
5785 		}
5786 
5787 		jmp_end_opnums[i] = zend_emit_jump(0);
5788 	}
5789 
5790 	// Initialize result in case there is no arm
5791 	if (arms->children == 0) {
5792 		result->op_type = IS_CONST;
5793 		ZVAL_NULL(&result->u.constant);
5794 	}
5795 
5796 	for (uint32_t i = 0; i < arms->children; ++i) {
5797 		zend_update_jump_target_to_next(jmp_end_opnums[i]);
5798 	}
5799 
5800 	if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) {
5801 		zend_op *opline = zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
5802 		opline->extended_value = ZEND_FREE_SWITCH;
5803 	} else if (expr_node.op_type == IS_CONST) {
5804 		zval_ptr_dtor_nogc(&expr_node.u.constant);
5805 	}
5806 
5807 	if (jmpnz_opnums != NULL) {
5808 		efree(jmpnz_opnums);
5809 	}
5810 	efree(jmp_end_opnums);
5811 }
5812 
zend_compile_try(zend_ast * ast)5813 static void zend_compile_try(zend_ast *ast) /* {{{ */
5814 {
5815 	zend_ast *try_ast = ast->child[0];
5816 	zend_ast_list *catches = zend_ast_get_list(ast->child[1]);
5817 	zend_ast *finally_ast = ast->child[2];
5818 
5819 	uint32_t i, j;
5820 	zend_op *opline;
5821 	uint32_t try_catch_offset;
5822 	uint32_t *jmp_opnums = safe_emalloc(sizeof(uint32_t), catches->children, 0);
5823 	uint32_t orig_fast_call_var = CG(context).fast_call_var;
5824 	uint32_t orig_try_catch_offset = CG(context).try_catch_offset;
5825 
5826 	if (catches->children == 0 && !finally_ast) {
5827 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally");
5828 	}
5829 
5830 	/* label: try { } must not be equal to try { label: } */
5831 	if (CG(context).labels) {
5832 		zend_label *label;
5833 		ZEND_HASH_REVERSE_FOREACH_PTR(CG(context).labels, label) {
5834 			if (label->opline_num == get_next_op_number()) {
5835 				zend_emit_op(NULL, ZEND_NOP, NULL, NULL);
5836 			}
5837 			break;
5838 		} ZEND_HASH_FOREACH_END();
5839 	}
5840 
5841 	try_catch_offset = zend_add_try_element(get_next_op_number());
5842 
5843 	if (finally_ast) {
5844 		zend_loop_var fast_call;
5845 		if (!(CG(active_op_array)->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) {
5846 			CG(active_op_array)->fn_flags |= ZEND_ACC_HAS_FINALLY_BLOCK;
5847 		}
5848 		CG(context).fast_call_var = get_temporary_variable();
5849 
5850 		/* Push FAST_CALL on unwind stack */
5851 		fast_call.opcode = ZEND_FAST_CALL;
5852 		fast_call.var_type = IS_TMP_VAR;
5853 		fast_call.var_num = CG(context).fast_call_var;
5854 		fast_call.try_catch_offset = try_catch_offset;
5855 		zend_stack_push(&CG(loop_var_stack), &fast_call);
5856 	}
5857 
5858 	CG(context).try_catch_offset = try_catch_offset;
5859 
5860 	zend_compile_stmt(try_ast);
5861 
5862 	if (catches->children != 0) {
5863 		jmp_opnums[0] = zend_emit_jump(0);
5864 	}
5865 
5866 	for (i = 0; i < catches->children; ++i) {
5867 		zend_ast *catch_ast = catches->child[i];
5868 		zend_ast_list *classes = zend_ast_get_list(catch_ast->child[0]);
5869 		zend_ast *var_ast = catch_ast->child[1];
5870 		zend_ast *stmt_ast = catch_ast->child[2];
5871 		zend_string *var_name = var_ast ? zval_make_interned_string(zend_ast_get_zval(var_ast)) : NULL;
5872 		bool is_last_catch = (i + 1 == catches->children);
5873 
5874 		uint32_t *jmp_multicatch = safe_emalloc(sizeof(uint32_t), classes->children - 1, 0);
5875 		uint32_t opnum_catch = (uint32_t)-1;
5876 
5877 		CG(zend_lineno) = catch_ast->lineno;
5878 
5879 		for (j = 0; j < classes->children; j++) {
5880 			zend_ast *class_ast = classes->child[j];
5881 			bool is_last_class = (j + 1 == classes->children);
5882 
5883 			if (!zend_is_const_default_class_ref(class_ast)) {
5884 				zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement");
5885 			}
5886 
5887 			opnum_catch = get_next_op_number();
5888 			if (i == 0 && j == 0) {
5889 				CG(active_op_array)->try_catch_array[try_catch_offset].catch_op = opnum_catch;
5890 			}
5891 
5892 			opline = get_next_op();
5893 			opline->opcode = ZEND_CATCH;
5894 			opline->op1_type = IS_CONST;
5895 			opline->op1.constant = zend_add_class_name_literal(
5896 					zend_resolve_class_name_ast(class_ast));
5897 			opline->extended_value = zend_alloc_cache_slot();
5898 
5899 			if (var_name && zend_string_equals_literal(var_name, "this")) {
5900 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
5901 			}
5902 
5903 			opline->result_type = var_name ? IS_CV : IS_UNUSED;
5904 			opline->result.var = var_name ? lookup_cv(var_name) : -1;
5905 
5906 			if (is_last_catch && is_last_class) {
5907 				opline->extended_value |= ZEND_LAST_CATCH;
5908 			}
5909 
5910 			if (!is_last_class) {
5911 				jmp_multicatch[j] = zend_emit_jump(0);
5912 				opline = &CG(active_op_array)->opcodes[opnum_catch];
5913 				opline->op2.opline_num = get_next_op_number();
5914 			}
5915 		}
5916 
5917 		for (j = 0; j < classes->children - 1; j++) {
5918 			zend_update_jump_target_to_next(jmp_multicatch[j]);
5919 		}
5920 
5921 		efree(jmp_multicatch);
5922 
5923 		zend_compile_stmt(stmt_ast);
5924 
5925 		if (!is_last_catch) {
5926 			jmp_opnums[i + 1] = zend_emit_jump(0);
5927 		}
5928 
5929 		ZEND_ASSERT(opnum_catch != (uint32_t)-1 && "Should have at least one class");
5930 		opline = &CG(active_op_array)->opcodes[opnum_catch];
5931 		if (!is_last_catch) {
5932 			opline->op2.opline_num = get_next_op_number();
5933 		}
5934 	}
5935 
5936 	for (i = 0; i < catches->children; ++i) {
5937 		zend_update_jump_target_to_next(jmp_opnums[i]);
5938 	}
5939 
5940 	if (finally_ast) {
5941 		zend_loop_var discard_exception;
5942 		uint32_t opnum_jmp = get_next_op_number() + 1;
5943 
5944 		/* Pop FAST_CALL from unwind stack */
5945 		zend_stack_del_top(&CG(loop_var_stack));
5946 
5947 		/* Push DISCARD_EXCEPTION on unwind stack */
5948 		discard_exception.opcode = ZEND_DISCARD_EXCEPTION;
5949 		discard_exception.var_type = IS_TMP_VAR;
5950 		discard_exception.var_num = CG(context).fast_call_var;
5951 		zend_stack_push(&CG(loop_var_stack), &discard_exception);
5952 
5953 		CG(zend_lineno) = finally_ast->lineno;
5954 
5955 		opline = zend_emit_op(NULL, ZEND_FAST_CALL, NULL, NULL);
5956 		opline->op1.num = try_catch_offset;
5957 		opline->result_type = IS_TMP_VAR;
5958 		opline->result.var = CG(context).fast_call_var;
5959 
5960 		zend_emit_op(NULL, ZEND_JMP, NULL, NULL);
5961 
5962 		zend_compile_stmt(finally_ast);
5963 
5964 		CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = opnum_jmp + 1;
5965 		CG(active_op_array)->try_catch_array[try_catch_offset].finally_end
5966 			= get_next_op_number();
5967 
5968 		opline = zend_emit_op(NULL, ZEND_FAST_RET, NULL, NULL);
5969 		opline->op1_type = IS_TMP_VAR;
5970 		opline->op1.var = CG(context).fast_call_var;
5971 		opline->op2.num = orig_try_catch_offset;
5972 
5973 		zend_update_jump_target_to_next(opnum_jmp);
5974 
5975 		CG(context).fast_call_var = orig_fast_call_var;
5976 
5977 		/* Pop DISCARD_EXCEPTION from unwind stack */
5978 		zend_stack_del_top(&CG(loop_var_stack));
5979 	}
5980 
5981 	CG(context).try_catch_offset = orig_try_catch_offset;
5982 
5983 	efree(jmp_opnums);
5984 }
5985 /* }}} */
5986 
5987 /* Encoding declarations must already be handled during parsing */
zend_handle_encoding_declaration(zend_ast * ast)5988 bool zend_handle_encoding_declaration(zend_ast *ast) /* {{{ */
5989 {
5990 	zend_ast_list *declares = zend_ast_get_list(ast);
5991 	uint32_t i;
5992 	for (i = 0; i < declares->children; ++i) {
5993 		zend_ast *declare_ast = declares->child[i];
5994 		zend_ast *name_ast = declare_ast->child[0];
5995 		zend_ast *value_ast = declare_ast->child[1];
5996 		zend_string *name = zend_ast_get_str(name_ast);
5997 
5998 		if (zend_string_equals_literal_ci(name, "encoding")) {
5999 			if (value_ast->kind != ZEND_AST_ZVAL) {
6000 				zend_throw_exception(zend_ce_compile_error, "Encoding must be a literal", 0);
6001 				return 0;
6002 			}
6003 
6004 			if (CG(multibyte)) {
6005 				zend_string *encoding_name = zval_get_string(zend_ast_get_zval(value_ast));
6006 
6007 				const zend_encoding *new_encoding, *old_encoding;
6008 				zend_encoding_filter old_input_filter;
6009 
6010 				CG(encoding_declared) = 1;
6011 
6012 				new_encoding = zend_multibyte_fetch_encoding(ZSTR_VAL(encoding_name));
6013 				if (!new_encoding) {
6014 					zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", ZSTR_VAL(encoding_name));
6015 				} else {
6016 					old_input_filter = LANG_SCNG(input_filter);
6017 					old_encoding = LANG_SCNG(script_encoding);
6018 					zend_multibyte_set_filter(new_encoding);
6019 
6020 					/* need to re-scan if input filter changed */
6021 					if (old_input_filter != LANG_SCNG(input_filter) ||
6022 						 (old_input_filter && new_encoding != old_encoding)) {
6023 						zend_multibyte_yyinput_again(old_input_filter, old_encoding);
6024 					}
6025 				}
6026 
6027 				zend_string_release_ex(encoding_name, 0);
6028 			} else {
6029 				zend_error(E_COMPILE_WARNING, "declare(encoding=...) ignored because "
6030 					"Zend multibyte feature is turned off by settings");
6031 			}
6032 		}
6033 	}
6034 
6035 	return 1;
6036 }
6037 /* }}} */
6038 
6039 /* Check whether this is the first statement, not counting declares. */
zend_is_first_statement(zend_ast * ast,bool allow_nop)6040 static zend_result zend_is_first_statement(zend_ast *ast, bool allow_nop) /* {{{ */
6041 {
6042 	uint32_t i = 0;
6043 	zend_ast_list *file_ast = zend_ast_get_list(CG(ast));
6044 
6045 	while (i < file_ast->children) {
6046 		if (file_ast->child[i] == ast) {
6047 			return SUCCESS;
6048 		} else if (file_ast->child[i] == NULL) {
6049 			if (!allow_nop) {
6050 				return FAILURE;
6051 			}
6052 		} else if (file_ast->child[i]->kind != ZEND_AST_DECLARE) {
6053 			return FAILURE;
6054 		}
6055 		i++;
6056 	}
6057 	return FAILURE;
6058 }
6059 /* }}} */
6060 
zend_compile_declare(zend_ast * ast)6061 static void zend_compile_declare(zend_ast *ast) /* {{{ */
6062 {
6063 	zend_ast_list *declares = zend_ast_get_list(ast->child[0]);
6064 	zend_ast *stmt_ast = ast->child[1];
6065 	zend_declarables orig_declarables = FC(declarables);
6066 	uint32_t i;
6067 
6068 	for (i = 0; i < declares->children; ++i) {
6069 		zend_ast *declare_ast = declares->child[i];
6070 		zend_ast *name_ast = declare_ast->child[0];
6071 		zend_ast **value_ast_ptr = &declare_ast->child[1];
6072 		zend_string *name = zend_ast_get_str(name_ast);
6073 
6074 		if ((*value_ast_ptr)->kind != ZEND_AST_ZVAL) {
6075 			zend_error_noreturn(E_COMPILE_ERROR, "declare(%s) value must be a literal", ZSTR_VAL(name));
6076 		}
6077 
6078 		if (zend_string_equals_literal_ci(name, "ticks")) {
6079 			zval value_zv;
6080 			zend_const_expr_to_zval(&value_zv, value_ast_ptr, /* allow_dynamic */ false);
6081 			FC(declarables).ticks = zval_get_long(&value_zv);
6082 			zval_ptr_dtor_nogc(&value_zv);
6083 		} else if (zend_string_equals_literal_ci(name, "encoding")) {
6084 
6085 			if (FAILURE == zend_is_first_statement(ast, /* allow_nop */ 0)) {
6086 				zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be "
6087 					"the very first statement in the script");
6088 			}
6089 		} else if (zend_string_equals_literal_ci(name, "strict_types")) {
6090 			zval value_zv;
6091 
6092 			if (FAILURE == zend_is_first_statement(ast, /* allow_nop */ 0)) {
6093 				zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must be "
6094 					"the very first statement in the script");
6095 			}
6096 
6097 			if (ast->child[1] != NULL) {
6098 				zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must not "
6099 					"use block mode");
6100 			}
6101 
6102 			zend_const_expr_to_zval(&value_zv, value_ast_ptr, /* allow_dynamic */ false);
6103 
6104 			if (Z_TYPE(value_zv) != IS_LONG || (Z_LVAL(value_zv) != 0 && Z_LVAL(value_zv) != 1)) {
6105 				zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must have 0 or 1 as its value");
6106 			}
6107 
6108 			if (Z_LVAL(value_zv) == 1) {
6109 				CG(active_op_array)->fn_flags |= ZEND_ACC_STRICT_TYPES;
6110 			}
6111 
6112 		} else {
6113 			zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", ZSTR_VAL(name));
6114 		}
6115 	}
6116 
6117 	if (stmt_ast) {
6118 		zend_compile_stmt(stmt_ast);
6119 
6120 		FC(declarables) = orig_declarables;
6121 	}
6122 }
6123 /* }}} */
6124 
zend_compile_stmt_list(zend_ast * ast)6125 static void zend_compile_stmt_list(zend_ast *ast) /* {{{ */
6126 {
6127 	zend_ast_list *list = zend_ast_get_list(ast);
6128 	uint32_t i;
6129 	for (i = 0; i < list->children; ++i) {
6130 		zend_compile_stmt(list->child[i]);
6131 	}
6132 }
6133 /* }}} */
6134 
zend_set_function_arg_flags(zend_function * func)6135 ZEND_API void zend_set_function_arg_flags(zend_function *func) /* {{{ */
6136 {
6137 	uint32_t i, n;
6138 
6139 	func->common.arg_flags[0] = 0;
6140 	func->common.arg_flags[1] = 0;
6141 	func->common.arg_flags[2] = 0;
6142 	if (func->common.arg_info) {
6143 		n = MIN(func->common.num_args, MAX_ARG_FLAG_NUM);
6144 		i = 0;
6145 		while (i < n) {
6146 			ZEND_SET_ARG_FLAG(func, i + 1, ZEND_ARG_SEND_MODE(&func->common.arg_info[i]));
6147 			i++;
6148 		}
6149 		if (UNEXPECTED((func->common.fn_flags & ZEND_ACC_VARIADIC) && ZEND_ARG_SEND_MODE(&func->common.arg_info[i]))) {
6150 			uint32_t pass_by_reference = ZEND_ARG_SEND_MODE(&func->common.arg_info[i]);
6151 			while (i < MAX_ARG_FLAG_NUM) {
6152 				ZEND_SET_ARG_FLAG(func, i + 1, pass_by_reference);
6153 				i++;
6154 			}
6155 		}
6156 	}
6157 }
6158 /* }}} */
6159 
zend_compile_single_typename(zend_ast * ast)6160 static zend_type zend_compile_single_typename(zend_ast *ast)
6161 {
6162 	ZEND_ASSERT(!(ast->attr & ZEND_TYPE_NULLABLE));
6163 	if (ast->kind == ZEND_AST_TYPE) {
6164 		if (ast->attr == IS_STATIC && !CG(active_class_entry) && zend_is_scope_known()) {
6165 			zend_error_noreturn(E_COMPILE_ERROR,
6166 				"Cannot use \"static\" when no class scope is active");
6167 		}
6168 		return (zend_type) ZEND_TYPE_INIT_CODE(ast->attr, 0, 0);
6169 	} else {
6170 		zend_string *class_name = zend_ast_get_str(ast);
6171 		zend_uchar type_code = zend_lookup_builtin_type_by_name(class_name);
6172 
6173 		if (type_code != 0) {
6174 			if ((ast->attr & ZEND_NAME_NOT_FQ) != ZEND_NAME_NOT_FQ) {
6175 				zend_error_noreturn(E_COMPILE_ERROR,
6176 					"Type declaration '%s' must be unqualified",
6177 					ZSTR_VAL(zend_string_tolower(class_name)));
6178 			}
6179 			return (zend_type) ZEND_TYPE_INIT_CODE(type_code, 0, 0);
6180 		} else {
6181 			const char *correct_name;
6182 			zend_string *orig_name = zend_ast_get_str(ast);
6183 			uint32_t fetch_type = zend_get_class_fetch_type_ast(ast);
6184 			if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
6185 				class_name = zend_resolve_class_name_ast(ast);
6186 				zend_assert_valid_class_name(class_name);
6187 			} else {
6188 				zend_ensure_valid_class_fetch_type(fetch_type);
6189 				zend_string_addref(class_name);
6190 			}
6191 
6192 			if (ast->attr == ZEND_NAME_NOT_FQ
6193 					&& zend_is_confusable_type(orig_name, &correct_name)
6194 					&& zend_is_not_imported(orig_name)) {
6195 				const char *extra =
6196 					FC(current_namespace) ? " or import the class with \"use\"" : "";
6197 				if (correct_name) {
6198 					zend_error(E_COMPILE_WARNING,
6199 						"\"%s\" will be interpreted as a class name. Did you mean \"%s\"? "
6200 						"Write \"\\%s\"%s to suppress this warning",
6201 						ZSTR_VAL(orig_name), correct_name, ZSTR_VAL(class_name), extra);
6202 				} else {
6203 					zend_error(E_COMPILE_WARNING,
6204 						"\"%s\" is not a supported builtin type "
6205 						"and will be interpreted as a class name. "
6206 						"Write \"\\%s\"%s to suppress this warning",
6207 						ZSTR_VAL(orig_name), ZSTR_VAL(class_name), extra);
6208 				}
6209 			}
6210 
6211 			class_name = zend_new_interned_string(class_name);
6212 			zend_alloc_ce_cache(class_name);
6213 			return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, 0, 0);
6214 		}
6215 	}
6216 }
6217 
zend_type_contains_traversable(zend_type type)6218 static bool zend_type_contains_traversable(zend_type type) {
6219 	zend_type *single_type;
6220 	ZEND_TYPE_FOREACH(type, single_type) {
6221 		if (ZEND_TYPE_HAS_NAME(*single_type)
6222 				&& zend_string_equals_literal_ci(ZEND_TYPE_NAME(*single_type), "Traversable")) {
6223 			return 1;
6224 		}
6225 	} ZEND_TYPE_FOREACH_END();
6226 	return 0;
6227 }
6228 
6229 // TODO: Ideally we'd canonicalize "iterable" into "array|Traversable" and essentially
6230 // treat it as a built-in type alias.
zend_compile_typename(zend_ast * ast,bool force_allow_null)6231 static zend_type zend_compile_typename(
6232 		zend_ast *ast, bool force_allow_null) /* {{{ */
6233 {
6234 	bool allow_null = force_allow_null;
6235 	zend_ast_attr orig_ast_attr = ast->attr;
6236 	zend_type type = ZEND_TYPE_INIT_NONE(0);
6237 	if (ast->attr & ZEND_TYPE_NULLABLE) {
6238 		allow_null = 1;
6239 		ast->attr &= ~ZEND_TYPE_NULLABLE;
6240 	}
6241 
6242 	if (ast->kind == ZEND_AST_TYPE_UNION) {
6243 		zend_ast_list *list = zend_ast_get_list(ast);
6244 		zend_type_list *type_list;
6245 		ALLOCA_FLAG(use_heap)
6246 
6247 		type_list = do_alloca(ZEND_TYPE_LIST_SIZE(list->children), use_heap);
6248 		type_list->num_types = 0;
6249 
6250 		for (uint32_t i = 0; i < list->children; i++) {
6251 			zend_ast *type_ast = list->child[i];
6252 			zend_type single_type = zend_compile_single_typename(type_ast);
6253 			uint32_t single_type_mask = ZEND_TYPE_PURE_MASK(single_type);
6254 
6255 			if (single_type_mask == MAY_BE_ANY) {
6256 				zend_error_noreturn(E_COMPILE_ERROR, "Type mixed can only be used as a standalone type");
6257 			}
6258 
6259 			uint32_t type_mask_overlap = ZEND_TYPE_PURE_MASK(type) & single_type_mask;
6260 			if (type_mask_overlap) {
6261 				zend_type overlap_type = ZEND_TYPE_INIT_MASK(type_mask_overlap);
6262 				zend_string *overlap_type_str = zend_type_to_string(overlap_type);
6263 				zend_error_noreturn(E_COMPILE_ERROR,
6264 					"Duplicate type %s is redundant", ZSTR_VAL(overlap_type_str));
6265 			}
6266 			ZEND_TYPE_FULL_MASK(type) |= ZEND_TYPE_PURE_MASK(single_type);
6267 			ZEND_TYPE_FULL_MASK(single_type) &= ~_ZEND_TYPE_MAY_BE_MASK;
6268 
6269 			if (ZEND_TYPE_IS_COMPLEX(single_type)) {
6270 				if (!ZEND_TYPE_IS_COMPLEX(type)) {
6271 					/* The first class type can be stored directly as the type ptr payload. */
6272 					ZEND_TYPE_SET_PTR(type, ZEND_TYPE_NAME(single_type));
6273 					ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_NAME_BIT;
6274 				} else {
6275 					if (type_list->num_types == 0) {
6276 						/* Switch from single name to name list. */
6277 						type_list->num_types = 1;
6278 						type_list->types[0] = type;
6279 						ZEND_TYPE_FULL_MASK(type_list->types[0]) &= ~_ZEND_TYPE_MAY_BE_MASK;
6280 						ZEND_TYPE_SET_LIST(type, type_list);
6281 					}
6282 
6283 					type_list->types[type_list->num_types++] = single_type;
6284 
6285 					/* Check for trivially redundant class types */
6286 					for (size_t i = 0; i < type_list->num_types - 1; i++) {
6287 						if (zend_string_equals_ci(
6288 								ZEND_TYPE_NAME(type_list->types[i]), ZEND_TYPE_NAME(single_type))) {
6289 							zend_string *single_type_str = zend_type_to_string(single_type);
6290 							zend_error_noreturn(E_COMPILE_ERROR,
6291 								"Duplicate type %s is redundant", ZSTR_VAL(single_type_str));
6292 						}
6293 					}
6294 				}
6295 			}
6296 		}
6297 
6298 		if (type_list->num_types) {
6299 			zend_type_list *list = zend_arena_alloc(
6300 				&CG(arena), ZEND_TYPE_LIST_SIZE(type_list->num_types));
6301 			memcpy(list, type_list, ZEND_TYPE_LIST_SIZE(type_list->num_types));
6302 			ZEND_TYPE_SET_LIST(type, list);
6303 			ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT;
6304 			/* Inform that the type list is a union type */
6305 			ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_UNION_BIT;
6306 		}
6307 
6308 		free_alloca(type_list, use_heap);
6309 	} else if (ast->kind == ZEND_AST_TYPE_INTERSECTION) {
6310 		zend_ast_list *list = zend_ast_get_list(ast);
6311 		zend_type_list *type_list;
6312 
6313 		/* Allocate the type list directly on the arena as it must be a type
6314 		 * list of the same number of elements as the AST list has children */
6315 		type_list = zend_arena_alloc(&CG(arena), ZEND_TYPE_LIST_SIZE(list->children));
6316 		type_list->num_types = 0;
6317 
6318 		ZEND_ASSERT(list->children > 1);
6319 
6320 		for (uint32_t i = 0; i < list->children; i++) {
6321 			zend_ast *type_ast = list->child[i];
6322 			zend_type single_type = zend_compile_single_typename(type_ast);
6323 
6324 			/* An intersection of standard types cannot exist so invalidate it */
6325 			if (ZEND_TYPE_IS_ONLY_MASK(single_type)) {
6326 				zend_string *standard_type_str = zend_type_to_string(single_type);
6327 				zend_error_noreturn(E_COMPILE_ERROR,
6328 					"Type %s cannot be part of an intersection type", ZSTR_VAL(standard_type_str));
6329 				zend_string_release_ex(standard_type_str, false);
6330 			}
6331 			/* Check for "self" and "parent" too */
6332 			if (zend_string_equals_literal_ci(ZEND_TYPE_NAME(single_type), "self")
6333 					|| zend_string_equals_literal_ci(ZEND_TYPE_NAME(single_type), "parent")) {
6334 				zend_error_noreturn(E_COMPILE_ERROR,
6335 					"Type %s cannot be part of an intersection type", ZSTR_VAL(ZEND_TYPE_NAME(single_type)));
6336 			}
6337 
6338 			/* Add type to the type list */
6339 			type_list->types[type_list->num_types++] = single_type;
6340 
6341 			/* Check for trivially redundant class types */
6342 			for (size_t i = 0; i < type_list->num_types - 1; i++) {
6343 				if (zend_string_equals_ci(
6344 					ZEND_TYPE_NAME(type_list->types[i]), ZEND_TYPE_NAME(single_type))) {
6345 					zend_string *single_type_str = zend_type_to_string(single_type);
6346 					zend_error_noreturn(E_COMPILE_ERROR,
6347 						"Duplicate type %s is redundant", ZSTR_VAL(single_type_str));
6348 				}
6349 			}
6350 		}
6351 
6352 		ZEND_ASSERT(list->children == type_list->num_types);
6353 
6354 		ZEND_TYPE_SET_LIST(type, type_list);
6355 		ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT;
6356 		/* Inform that the type list is an intersection type */
6357 		ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_INTERSECTION_BIT;
6358 	} else {
6359 		type = zend_compile_single_typename(ast);
6360 	}
6361 
6362 	if (allow_null) {
6363 		ZEND_TYPE_FULL_MASK(type) |= MAY_BE_NULL;
6364 	}
6365 
6366 	uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
6367 	if ((type_mask & (MAY_BE_ARRAY|MAY_BE_ITERABLE)) == (MAY_BE_ARRAY|MAY_BE_ITERABLE)) {
6368 		zend_string *type_str = zend_type_to_string(type);
6369 		zend_error_noreturn(E_COMPILE_ERROR,
6370 			"Type %s contains both iterable and array, which is redundant", ZSTR_VAL(type_str));
6371 	}
6372 
6373 	if ((type_mask & MAY_BE_ITERABLE) && zend_type_contains_traversable(type)) {
6374 		zend_string *type_str = zend_type_to_string(type);
6375 		zend_error_noreturn(E_COMPILE_ERROR,
6376 			"Type %s contains both iterable and Traversable, which is redundant",
6377 			ZSTR_VAL(type_str));
6378 	}
6379 
6380 	if (type_mask == MAY_BE_ANY && (orig_ast_attr & ZEND_TYPE_NULLABLE)) {
6381 		zend_error_noreturn(E_COMPILE_ERROR, "Type mixed cannot be marked as nullable since mixed already includes null");
6382 	}
6383 
6384 	if ((type_mask & MAY_BE_OBJECT) && (ZEND_TYPE_IS_COMPLEX(type) || (type_mask & MAY_BE_STATIC))) {
6385 		zend_string *type_str = zend_type_to_string(type);
6386 		zend_error_noreturn(E_COMPILE_ERROR,
6387 			"Type %s contains both object and a class type, which is redundant",
6388 			ZSTR_VAL(type_str));
6389 	}
6390 
6391 	if ((type_mask & MAY_BE_VOID) && (ZEND_TYPE_IS_COMPLEX(type) || type_mask != MAY_BE_VOID)) {
6392 		zend_error_noreturn(E_COMPILE_ERROR, "Void can only be used as a standalone type");
6393 	}
6394 
6395 	if ((type_mask & MAY_BE_NEVER) && (ZEND_TYPE_IS_COMPLEX(type) || type_mask != MAY_BE_NEVER)) {
6396 		zend_error_noreturn(E_COMPILE_ERROR, "never can only be used as a standalone type");
6397 	}
6398 
6399 	if ((type_mask & (MAY_BE_NULL|MAY_BE_FALSE))
6400 			&& !ZEND_TYPE_IS_COMPLEX(type) && !(type_mask & ~(MAY_BE_NULL|MAY_BE_FALSE))) {
6401 		if (type_mask == MAY_BE_NULL) {
6402 			zend_error_noreturn(E_COMPILE_ERROR, "Null can not be used as a standalone type");
6403 		} else {
6404 			zend_error_noreturn(E_COMPILE_ERROR, "False can not be used as a standalone type");
6405 		}
6406 	}
6407 
6408 	ast->attr = orig_ast_attr;
6409 	return type;
6410 }
6411 /* }}} */
6412 
6413 /* May convert value from int to float. */
zend_is_valid_default_value(zend_type type,zval * value)6414 static bool zend_is_valid_default_value(zend_type type, zval *value)
6415 {
6416 	ZEND_ASSERT(ZEND_TYPE_IS_SET(type));
6417 	if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(value))) {
6418 		return 1;
6419 	}
6420 	if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_DOUBLE) && Z_TYPE_P(value) == IS_LONG) {
6421 		/* Integers are allowed as initializers for floating-point values. */
6422 		convert_to_double(value);
6423 		return 1;
6424 	}
6425 	if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_ITERABLE) && Z_TYPE_P(value) == IS_ARRAY) {
6426 		return 1;
6427 	}
6428 	return 0;
6429 }
6430 
zend_compile_attributes(HashTable ** attributes,zend_ast * ast,uint32_t offset,uint32_t target)6431 static void zend_compile_attributes(HashTable **attributes, zend_ast *ast, uint32_t offset, uint32_t target) /* {{{ */
6432 {
6433 	zend_attribute *attr;
6434 	zend_internal_attribute *config;
6435 
6436 	zend_ast_list *list = zend_ast_get_list(ast);
6437 	uint32_t g, i, j;
6438 
6439 	ZEND_ASSERT(ast->kind == ZEND_AST_ATTRIBUTE_LIST);
6440 
6441 	for (g = 0; g < list->children; g++) {
6442 		zend_ast_list *group = zend_ast_get_list(list->child[g]);
6443 
6444 		ZEND_ASSERT(group->kind == ZEND_AST_ATTRIBUTE_GROUP);
6445 
6446 		for (i = 0; i < group->children; i++) {
6447 			ZEND_ASSERT(group->child[i]->kind == ZEND_AST_ATTRIBUTE);
6448 
6449 			zend_ast *el = group->child[i];
6450 
6451 			if (el->child[1] &&
6452 			    el->child[1]->kind == ZEND_AST_CALLABLE_CONVERT) {
6453 			    zend_error_noreturn(E_COMPILE_ERROR,
6454 			        "Cannot create Closure as attribute argument");
6455 			}
6456 
6457 			zend_string *name = zend_resolve_class_name_ast(el->child[0]);
6458 			zend_ast_list *args = el->child[1] ? zend_ast_get_list(el->child[1]) : NULL;
6459 
6460 			uint32_t flags = (CG(active_op_array)->fn_flags & ZEND_ACC_STRICT_TYPES)
6461 				? ZEND_ATTRIBUTE_STRICT_TYPES : 0;
6462 			attr = zend_add_attribute(
6463 				attributes, name, args ? args->children : 0, flags, offset, el->lineno);
6464 			zend_string_release(name);
6465 
6466 			/* Populate arguments */
6467 			if (args) {
6468 				ZEND_ASSERT(args->kind == ZEND_AST_ARG_LIST);
6469 
6470 				bool uses_named_args = 0;
6471 				for (j = 0; j < args->children; j++) {
6472 					zend_ast **arg_ast_ptr = &args->child[j];
6473 					zend_ast *arg_ast = *arg_ast_ptr;
6474 
6475 					if (arg_ast->kind == ZEND_AST_UNPACK) {
6476 						zend_error_noreturn(E_COMPILE_ERROR,
6477 							"Cannot use unpacking in attribute argument list");
6478 					}
6479 
6480 					if (arg_ast->kind == ZEND_AST_NAMED_ARG) {
6481 						attr->args[j].name = zend_string_copy(zend_ast_get_str(arg_ast->child[0]));
6482 						arg_ast_ptr = &arg_ast->child[1];
6483 						uses_named_args = 1;
6484 
6485 						for (uint32_t k = 0; k < j; k++) {
6486 							if (attr->args[k].name &&
6487 									zend_string_equals(attr->args[k].name, attr->args[j].name)) {
6488 								zend_error_noreturn(E_COMPILE_ERROR, "Duplicate named parameter $%s",
6489 									ZSTR_VAL(attr->args[j].name));
6490 							}
6491 						}
6492 					} else if (uses_named_args) {
6493 						zend_error_noreturn(E_COMPILE_ERROR,
6494 							"Cannot use positional argument after named argument");
6495 					}
6496 
6497 					zend_const_expr_to_zval(
6498 						&attr->args[j].value, arg_ast_ptr, /* allow_dynamic */ true);
6499 				}
6500 			}
6501 		}
6502 	}
6503 
6504 	/* Validate attributes in a secondary loop (needed to detect repeated attributes). */
6505 	ZEND_HASH_FOREACH_PTR(*attributes, attr) {
6506 		if (attr->offset != offset || NULL == (config = zend_internal_attribute_get(attr->lcname))) {
6507 			continue;
6508 		}
6509 
6510 		if (!(target & (config->flags & ZEND_ATTRIBUTE_TARGET_ALL))) {
6511 			zend_string *location = zend_get_attribute_target_names(target);
6512 			zend_string *allowed = zend_get_attribute_target_names(config->flags);
6513 
6514 			zend_error_noreturn(E_ERROR, "Attribute \"%s\" cannot target %s (allowed targets: %s)",
6515 				ZSTR_VAL(attr->name), ZSTR_VAL(location), ZSTR_VAL(allowed)
6516 			);
6517 		}
6518 
6519 		if (!(config->flags & ZEND_ATTRIBUTE_IS_REPEATABLE)) {
6520 			if (zend_is_attribute_repeated(*attributes, attr)) {
6521 				zend_error_noreturn(E_ERROR, "Attribute \"%s\" must not be repeated", ZSTR_VAL(attr->name));
6522 			}
6523 		}
6524 
6525 		if (config->validator != NULL) {
6526 			config->validator(attr, target, CG(active_class_entry));
6527 		}
6528 	} ZEND_HASH_FOREACH_END();
6529 }
6530 /* }}} */
6531 
zend_compile_params(zend_ast * ast,zend_ast * return_type_ast,uint32_t fallback_return_type)6532 static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fallback_return_type) /* {{{ */
6533 {
6534 	zend_ast_list *list = zend_ast_get_list(ast);
6535 	uint32_t i;
6536 	zend_op_array *op_array = CG(active_op_array);
6537 	zend_arg_info *arg_infos;
6538 
6539 	if (return_type_ast || fallback_return_type) {
6540 		/* Use op_array->arg_info[-1] for return type */
6541 		arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children + 1, 0);
6542 		arg_infos->name = NULL;
6543 		if (return_type_ast) {
6544 			arg_infos->type = zend_compile_typename(
6545 				return_type_ast, /* force_allow_null */ 0);
6546 			ZEND_TYPE_FULL_MASK(arg_infos->type) |= _ZEND_ARG_INFO_FLAGS(
6547 				(op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0, /* is_tentative */ 0);
6548 		} else {
6549 			arg_infos->type = (zend_type) ZEND_TYPE_INIT_CODE(fallback_return_type, 0, 0);
6550 		}
6551 		arg_infos++;
6552 		op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
6553 
6554 		if (ZEND_TYPE_CONTAINS_CODE(arg_infos[-1].type, IS_VOID)
6555 				&& (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
6556 			zend_error(E_DEPRECATED, "Returning by reference from a void function is deprecated");
6557 		}
6558 	} else {
6559 		if (list->children == 0) {
6560 			return;
6561 		}
6562 		arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children, 0);
6563 	}
6564 
6565 	/* Find last required parameter number for deprecation message. */
6566 	uint32_t last_required_param = (uint32_t) -1;
6567 	for (i = 0; i < list->children; ++i) {
6568 		zend_ast *param_ast = list->child[i];
6569 		zend_ast *default_ast_ptr = param_ast->child[2];
6570 		bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
6571 		if (!default_ast_ptr && !is_variadic) {
6572 			last_required_param = i;
6573 		}
6574 	}
6575 
6576 	for (i = 0; i < list->children; ++i) {
6577 		zend_ast *param_ast = list->child[i];
6578 		zend_ast *type_ast = param_ast->child[0];
6579 		zend_ast *var_ast = param_ast->child[1];
6580 		zend_ast **default_ast_ptr = &param_ast->child[2];
6581 		zend_ast *attributes_ast = param_ast->child[3];
6582 		zend_ast *doc_comment_ast = param_ast->child[4];
6583 		zend_string *name = zval_make_interned_string(zend_ast_get_zval(var_ast));
6584 		bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
6585 		bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
6586 		uint32_t property_flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_READONLY);
6587 
6588 		znode var_node, default_node;
6589 		zend_uchar opcode;
6590 		zend_op *opline;
6591 		zend_arg_info *arg_info;
6592 
6593 		if (zend_is_auto_global(name)) {
6594 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign auto-global variable %s",
6595 				ZSTR_VAL(name));
6596 		}
6597 
6598 		var_node.op_type = IS_CV;
6599 		var_node.u.op.var = lookup_cv(name);
6600 
6601 		if (EX_VAR_TO_NUM(var_node.u.op.var) != i) {
6602 			zend_error_noreturn(E_COMPILE_ERROR, "Redefinition of parameter $%s",
6603 				ZSTR_VAL(name));
6604 		} else if (zend_string_equals_literal(name, "this")) {
6605 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as parameter");
6606 		}
6607 
6608 		if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
6609 			zend_error_noreturn(E_COMPILE_ERROR, "Only the last parameter can be variadic");
6610 		}
6611 
6612 		if (is_variadic) {
6613 			opcode = ZEND_RECV_VARIADIC;
6614 			default_node.op_type = IS_UNUSED;
6615 			op_array->fn_flags |= ZEND_ACC_VARIADIC;
6616 
6617 			if (*default_ast_ptr) {
6618 				zend_error_noreturn(E_COMPILE_ERROR,
6619 					"Variadic parameter cannot have a default value");
6620 			}
6621 		} else if (*default_ast_ptr) {
6622 			/* we cannot substitute constants here or it will break ReflectionParameter::getDefaultValueConstantName() and ReflectionParameter::isDefaultValueConstant() */
6623 			uint32_t cops = CG(compiler_options);
6624 			CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION;
6625 			opcode = ZEND_RECV_INIT;
6626 			default_node.op_type = IS_CONST;
6627 			zend_const_expr_to_zval(
6628 				&default_node.u.constant, default_ast_ptr, /* allow_dynamic */ true);
6629 			CG(compiler_options) = cops;
6630 
6631 			if (last_required_param != (uint32_t) -1 && i < last_required_param) {
6632 				/* Ignore parameters of the form "Type $param = null".
6633 				 * This is the PHP 5 style way of writing "?Type $param", so allow it for now. */
6634 				bool is_implicit_nullable =
6635 					type_ast && !(type_ast->attr & ZEND_TYPE_NULLABLE)
6636 					&& Z_TYPE(default_node.u.constant) == IS_NULL;
6637 				if (!is_implicit_nullable) {
6638 					zend_ast *required_param_ast = list->child[last_required_param];
6639 					zend_error(E_DEPRECATED,
6640 						"Optional parameter $%s declared before required parameter $%s "
6641 						"is implicitly treated as a required parameter",
6642 						ZSTR_VAL(name), ZSTR_VAL(zend_ast_get_str(required_param_ast->child[1])));
6643 				}
6644 
6645 				/* Regardless of whether we issue a deprecation, convert this parameter into
6646 				 * a required parameter without a default value. This ensures that it cannot be
6647 				 * used as an optional parameter even with named parameters. */
6648 				opcode = ZEND_RECV;
6649 				default_node.op_type = IS_UNUSED;
6650 				zval_ptr_dtor(&default_node.u.constant);
6651 			}
6652 		} else {
6653 			opcode = ZEND_RECV;
6654 			default_node.op_type = IS_UNUSED;
6655 			op_array->required_num_args = i + 1;
6656 		}
6657 
6658 		arg_info = &arg_infos[i];
6659 		arg_info->name = zend_string_copy(name);
6660 		arg_info->type = (zend_type) ZEND_TYPE_INIT_NONE(0);
6661 
6662 		if (attributes_ast) {
6663 			zend_compile_attributes(&op_array->attributes, attributes_ast, i + 1, ZEND_ATTRIBUTE_TARGET_PARAMETER);
6664 		}
6665 
6666 		if (type_ast) {
6667 			uint32_t default_type = *default_ast_ptr ? Z_TYPE(default_node.u.constant) : IS_UNDEF;
6668 			bool force_nullable = default_type == IS_NULL && !property_flags;
6669 
6670 			op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
6671 			arg_info->type = zend_compile_typename(type_ast, force_nullable);
6672 
6673 			if (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_VOID) {
6674 				zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type");
6675 			}
6676 
6677 			if (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_NEVER) {
6678 				zend_error_noreturn(E_COMPILE_ERROR, "never cannot be used as a parameter type");
6679 			}
6680 
6681 			if (force_nullable && ZEND_TYPE_IS_INTERSECTION(arg_info->type)) {
6682 				zend_string *type_str = zend_type_to_string(arg_info->type);
6683 				zend_error_noreturn(E_COMPILE_ERROR,
6684 					"Cannot use null as default value for parameter $%s of type %s",
6685 					/* We move type_str pointer one char forward to skip the '?' generated by
6686 					 * the call to zend_compile_typename() */
6687 					ZSTR_VAL(name), ZSTR_VAL(type_str)+1);
6688 			}
6689 
6690 			if (default_type != IS_UNDEF && default_type != IS_CONSTANT_AST && !force_nullable
6691 					&& !zend_is_valid_default_value(arg_info->type, &default_node.u.constant)) {
6692 				zend_string *type_str = zend_type_to_string(arg_info->type);
6693 				zend_error_noreturn(E_COMPILE_ERROR,
6694 					"Cannot use %s as default value for parameter $%s of type %s",
6695 					zend_get_type_by_const(default_type),
6696 					ZSTR_VAL(name), ZSTR_VAL(type_str));
6697 			}
6698 		}
6699 
6700 		opline = zend_emit_op(NULL, opcode, NULL, &default_node);
6701 		SET_NODE(opline->result, &var_node);
6702 		opline->op1.num = i + 1;
6703 
6704 		if (type_ast) {
6705 			/* Allocate cache slot to speed-up run-time class resolution */
6706 			opline->extended_value =
6707 				zend_alloc_cache_slots(zend_type_get_num_classes(arg_info->type));
6708 		}
6709 
6710 		uint32_t arg_info_flags = _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic, /* is_tentative */ 0)
6711 			| (property_flags ? _ZEND_IS_PROMOTED_BIT : 0);
6712 		ZEND_TYPE_FULL_MASK(arg_info->type) |= arg_info_flags;
6713 		if (opcode == ZEND_RECV) {
6714 			opline->op2.num = type_ast ?
6715 				ZEND_TYPE_FULL_MASK(arg_info->type) : MAY_BE_ANY;
6716 		}
6717 
6718 		if (property_flags) {
6719 			zend_op_array *op_array = CG(active_op_array);
6720 			zend_class_entry *scope = op_array->scope;
6721 			bool is_ctor =
6722 				scope && zend_is_constructor(op_array->function_name);
6723 			if (!is_ctor) {
6724 				zend_error_noreturn(E_COMPILE_ERROR,
6725 					"Cannot declare promoted property outside a constructor");
6726 			}
6727 			if ((op_array->fn_flags & ZEND_ACC_ABSTRACT)
6728 					|| (scope->ce_flags & ZEND_ACC_INTERFACE)) {
6729 				zend_error_noreturn(E_COMPILE_ERROR,
6730 					"Cannot declare promoted property in an abstract constructor");
6731 			}
6732 			if (is_variadic) {
6733 				zend_error_noreturn(E_COMPILE_ERROR,
6734 					"Cannot declare variadic promoted property");
6735 			}
6736 			if (zend_hash_exists(&scope->properties_info, name)) {
6737 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s",
6738 					ZSTR_VAL(scope->name), ZSTR_VAL(name));
6739 			}
6740 			if (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_CALLABLE) {
6741 				zend_string *str = zend_type_to_string(arg_info->type);
6742 				zend_error_noreturn(E_COMPILE_ERROR,
6743 					"Property %s::$%s cannot have type %s",
6744 					ZSTR_VAL(scope->name), ZSTR_VAL(name), ZSTR_VAL(str));
6745 			}
6746 
6747 			/* Recompile the type, as it has different memory management requirements. */
6748 			zend_type type = ZEND_TYPE_INIT_NONE(0);
6749 			if (type_ast) {
6750 				type = zend_compile_typename(type_ast, /* force_allow_null */ 0);
6751 			}
6752 
6753 			/* Don't give the property an explicit default value. For typed properties this means
6754 			 * uninitialized, for untyped properties it means an implicit null default value. */
6755 			zval default_value;
6756 			if (ZEND_TYPE_IS_SET(type)) {
6757 				ZVAL_UNDEF(&default_value);
6758 			} else {
6759 				if (property_flags & ZEND_ACC_READONLY) {
6760 					zend_error_noreturn(E_COMPILE_ERROR, "Readonly property %s::$%s must have type",
6761 						ZSTR_VAL(scope->name), ZSTR_VAL(name));
6762 				}
6763 
6764 				ZVAL_NULL(&default_value);
6765 			}
6766 
6767 			zend_string *doc_comment =
6768 				doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL;
6769 			zend_property_info *prop = zend_declare_typed_property(
6770 				scope, name, &default_value, property_flags | ZEND_ACC_PROMOTED, doc_comment, type);
6771 			if (attributes_ast) {
6772 				zend_compile_attributes(
6773 					&prop->attributes, attributes_ast, 0, ZEND_ATTRIBUTE_TARGET_PROPERTY);
6774 			}
6775 		}
6776 	}
6777 
6778 	/* These are assigned at the end to avoid uninitialized memory in case of an error */
6779 	op_array->num_args = list->children;
6780 	op_array->arg_info = arg_infos;
6781 
6782 	/* Don't count the variadic argument */
6783 	if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
6784 		op_array->num_args--;
6785 	}
6786 	zend_set_function_arg_flags((zend_function*)op_array);
6787 
6788 	for (i = 0; i < list->children; i++) {
6789 		zend_ast *param_ast = list->child[i];
6790 		bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
6791 		uint32_t flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_READONLY);
6792 		if (!flags) {
6793 			continue;
6794 		}
6795 
6796 		/* Emit $this->prop = $prop for promoted properties. */
6797 		zend_string *name = zend_ast_get_str(param_ast->child[1]);
6798 		znode name_node, value_node;
6799 		name_node.op_type = IS_CONST;
6800 		ZVAL_STR_COPY(&name_node.u.constant, name);
6801 		value_node.op_type = IS_CV;
6802 		value_node.u.op.var = lookup_cv(name);
6803 
6804 		zend_op *opline = zend_emit_op(NULL,
6805 			is_ref ? ZEND_ASSIGN_OBJ_REF : ZEND_ASSIGN_OBJ, NULL, &name_node);
6806 		opline->extended_value = zend_alloc_cache_slots(3);
6807 		zend_emit_op_data(&value_node);
6808 	}
6809 }
6810 /* }}} */
6811 
zend_compile_closure_binding(znode * closure,zend_op_array * op_array,zend_ast * uses_ast)6812 static void zend_compile_closure_binding(znode *closure, zend_op_array *op_array, zend_ast *uses_ast) /* {{{ */
6813 {
6814 	zend_ast_list *list = zend_ast_get_list(uses_ast);
6815 	uint32_t i;
6816 
6817 	if (!list->children) {
6818 		return;
6819 	}
6820 
6821 	if (!op_array->static_variables) {
6822 		op_array->static_variables = zend_new_array(8);
6823 	}
6824 
6825 	for (i = 0; i < list->children; ++i) {
6826 		zend_ast *var_name_ast = list->child[i];
6827 		zend_string *var_name = zval_make_interned_string(zend_ast_get_zval(var_name_ast));
6828 		uint32_t mode = var_name_ast->attr;
6829 		zend_op *opline;
6830 		zval *value;
6831 
6832 		if (zend_string_equals_literal(var_name, "this")) {
6833 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
6834 		}
6835 
6836 		if (zend_is_auto_global(var_name)) {
6837 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use auto-global as lexical variable");
6838 		}
6839 
6840 		value = zend_hash_add(op_array->static_variables, var_name, &EG(uninitialized_zval));
6841 		if (!value) {
6842 			zend_error_noreturn(E_COMPILE_ERROR,
6843 				"Cannot use variable $%s twice", ZSTR_VAL(var_name));
6844 		}
6845 
6846 		CG(zend_lineno) = zend_ast_get_lineno(var_name_ast);
6847 
6848 		opline = zend_emit_op(NULL, ZEND_BIND_LEXICAL, closure, NULL);
6849 		opline->op2_type = IS_CV;
6850 		opline->op2.var = lookup_cv(var_name);
6851 		opline->extended_value =
6852 			(uint32_t)((char*)value - (char*)op_array->static_variables->arData) | mode;
6853 	}
6854 }
6855 /* }}} */
6856 
6857 typedef struct {
6858 	HashTable uses;
6859 	bool varvars_used;
6860 } closure_info;
6861 
find_implicit_binds_recursively(closure_info * info,zend_ast * ast)6862 static void find_implicit_binds_recursively(closure_info *info, zend_ast *ast) {
6863 	if (!ast) {
6864 		return;
6865 	}
6866 
6867 	if (ast->kind == ZEND_AST_VAR) {
6868 		zend_ast *name_ast = ast->child[0];
6869 		if (name_ast->kind == ZEND_AST_ZVAL && Z_TYPE_P(zend_ast_get_zval(name_ast)) == IS_STRING) {
6870 			zend_string *name = zend_ast_get_str(name_ast);
6871 			if (zend_is_auto_global(name)) {
6872 				/* These is no need to explicitly import auto-globals. */
6873 				return;
6874 			}
6875 
6876 			if (zend_string_equals_literal(name, "this")) {
6877 				/* $this does not need to be explicitly imported. */
6878 				return;
6879 			}
6880 
6881 			zend_hash_add_empty_element(&info->uses, name);
6882 		} else {
6883 			info->varvars_used = 1;
6884 			find_implicit_binds_recursively(info, name_ast);
6885 		}
6886 	} else if (zend_ast_is_list(ast)) {
6887 		zend_ast_list *list = zend_ast_get_list(ast);
6888 		uint32_t i;
6889 		for (i = 0; i < list->children; i++) {
6890 			find_implicit_binds_recursively(info, list->child[i]);
6891 		}
6892 	} else if (ast->kind == ZEND_AST_CLOSURE) {
6893 		/* For normal closures add the use() list. */
6894 		zend_ast_decl *closure_ast = (zend_ast_decl *) ast;
6895 		zend_ast *uses_ast = closure_ast->child[1];
6896 		if (uses_ast) {
6897 			zend_ast_list *uses_list = zend_ast_get_list(uses_ast);
6898 			uint32_t i;
6899 			for (i = 0; i < uses_list->children; i++) {
6900 				zend_hash_add_empty_element(&info->uses, zend_ast_get_str(uses_list->child[i]));
6901 			}
6902 		}
6903 	} else if (ast->kind == ZEND_AST_ARROW_FUNC) {
6904 		/* For arrow functions recursively check the expression. */
6905 		zend_ast_decl *closure_ast = (zend_ast_decl *) ast;
6906 		find_implicit_binds_recursively(info, closure_ast->child[2]);
6907 	} else if (!zend_ast_is_special(ast)) {
6908 		uint32_t i, children = zend_ast_get_num_children(ast);
6909 		for (i = 0; i < children; i++) {
6910 			find_implicit_binds_recursively(info, ast->child[i]);
6911 		}
6912 	}
6913 }
6914 
find_implicit_binds(closure_info * info,zend_ast * params_ast,zend_ast * stmt_ast)6915 static void find_implicit_binds(closure_info *info, zend_ast *params_ast, zend_ast *stmt_ast)
6916 {
6917 	zend_ast_list *param_list = zend_ast_get_list(params_ast);
6918 	uint32_t i;
6919 
6920 	zend_hash_init(&info->uses, param_list->children, NULL, NULL, 0);
6921 
6922 	find_implicit_binds_recursively(info, stmt_ast);
6923 
6924 	/* Remove variables that are parameters */
6925 	for (i = 0; i < param_list->children; i++) {
6926 		zend_ast *param_ast = param_list->child[i];
6927 		zend_hash_del(&info->uses, zend_ast_get_str(param_ast->child[1]));
6928 	}
6929 }
6930 
compile_implicit_lexical_binds(closure_info * info,znode * closure,zend_op_array * op_array)6931 static void compile_implicit_lexical_binds(
6932 		closure_info *info, znode *closure, zend_op_array *op_array)
6933 {
6934 	zend_string *var_name;
6935 	zend_op *opline;
6936 
6937 	/* TODO We might want to use a special binding mode if varvars_used is set. */
6938 	if (zend_hash_num_elements(&info->uses) == 0) {
6939 		return;
6940 	}
6941 
6942 	if (!op_array->static_variables) {
6943 		op_array->static_variables = zend_new_array(8);
6944 	}
6945 
6946 	ZEND_HASH_FOREACH_STR_KEY(&info->uses, var_name)
6947 		zval *value = zend_hash_add(
6948 			op_array->static_variables, var_name, &EG(uninitialized_zval));
6949 		uint32_t offset = (uint32_t)((char*)value - (char*)op_array->static_variables->arData);
6950 
6951 		opline = zend_emit_op(NULL, ZEND_BIND_LEXICAL, closure, NULL);
6952 		opline->op2_type = IS_CV;
6953 		opline->op2.var = lookup_cv(var_name);
6954 		opline->extended_value = offset | ZEND_BIND_IMPLICIT;
6955 	ZEND_HASH_FOREACH_END();
6956 }
6957 
zend_compile_closure_uses(zend_ast * ast)6958 static void zend_compile_closure_uses(zend_ast *ast) /* {{{ */
6959 {
6960 	zend_op_array *op_array = CG(active_op_array);
6961 	zend_ast_list *list = zend_ast_get_list(ast);
6962 	uint32_t i;
6963 
6964 	for (i = 0; i < list->children; ++i) {
6965 		uint32_t mode = ZEND_BIND_EXPLICIT;
6966 		zend_ast *var_ast = list->child[i];
6967 		zend_string *var_name = zend_ast_get_str(var_ast);
6968 		zval zv;
6969 		ZVAL_NULL(&zv);
6970 
6971 		{
6972 			int i;
6973 			for (i = 0; i < op_array->last_var; i++) {
6974 				if (zend_string_equals(op_array->vars[i], var_name)) {
6975 					zend_error_noreturn(E_COMPILE_ERROR,
6976 						"Cannot use lexical variable $%s as a parameter name", ZSTR_VAL(var_name));
6977 				}
6978 			}
6979 		}
6980 
6981 		CG(zend_lineno) = zend_ast_get_lineno(var_ast);
6982 
6983 		if (var_ast->attr) {
6984 			mode |= ZEND_BIND_REF;
6985 		}
6986 
6987 		zend_compile_static_var_common(var_name, &zv, mode);
6988 	}
6989 }
6990 /* }}} */
6991 
zend_compile_implicit_closure_uses(closure_info * info)6992 static void zend_compile_implicit_closure_uses(closure_info *info)
6993 {
6994 	zend_string *var_name;
6995 	ZEND_HASH_FOREACH_STR_KEY(&info->uses, var_name)
6996 		zval zv;
6997 		ZVAL_NULL(&zv);
6998 		zend_compile_static_var_common(var_name, &zv, ZEND_BIND_IMPLICIT);
6999 	ZEND_HASH_FOREACH_END();
7000 }
7001 
add_stringable_interface(zend_class_entry * ce)7002 static void add_stringable_interface(zend_class_entry *ce) {
7003 	for (uint32_t i = 0; i < ce->num_interfaces; i++) {
7004 		if (zend_string_equals_literal(ce->interface_names[i].lc_name, "stringable")) {
7005 			/* Interface already explicitly implemented */
7006 			return;
7007 		}
7008 	}
7009 
7010 	ce->num_interfaces++;
7011 	ce->interface_names =
7012 		erealloc(ce->interface_names, sizeof(zend_class_name) * ce->num_interfaces);
7013 	// TODO: Add known interned strings instead?
7014 	ce->interface_names[ce->num_interfaces - 1].name =
7015 		zend_string_init("Stringable", sizeof("Stringable") - 1, 0);
7016 	ce->interface_names[ce->num_interfaces - 1].lc_name =
7017 		zend_string_init("stringable", sizeof("stringable") - 1, 0);
7018 }
7019 
zend_begin_method_decl(zend_op_array * op_array,zend_string * name,bool has_body)7020 static zend_string *zend_begin_method_decl(zend_op_array *op_array, zend_string *name, bool has_body) /* {{{ */
7021 {
7022 	zend_class_entry *ce = CG(active_class_entry);
7023 	bool in_interface = (ce->ce_flags & ZEND_ACC_INTERFACE) != 0;
7024 	uint32_t fn_flags = op_array->fn_flags;
7025 
7026 	zend_string *lcname;
7027 
7028 	if (fn_flags & ZEND_ACC_READONLY) {
7029 		zend_error(E_COMPILE_ERROR, "Cannot use 'readonly' as method modifier");
7030 	}
7031 
7032 	if ((fn_flags & ZEND_ACC_PRIVATE) && (fn_flags & ZEND_ACC_FINAL) && !zend_is_constructor(name)) {
7033 		zend_error(E_COMPILE_WARNING, "Private methods cannot be final as they are never overridden by other classes");
7034 	}
7035 
7036 	if (in_interface) {
7037 		if (!(fn_flags & ZEND_ACC_PUBLIC) || (fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT))) {
7038 			zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method "
7039 				"%s::%s() must be public", ZSTR_VAL(ce->name), ZSTR_VAL(name));
7040 		}
7041 		op_array->fn_flags |= ZEND_ACC_ABSTRACT;
7042 	}
7043 
7044 	if (op_array->fn_flags & ZEND_ACC_ABSTRACT) {
7045 		if ((op_array->fn_flags & ZEND_ACC_PRIVATE) && !(ce->ce_flags & ZEND_ACC_TRAIT)) {
7046 			zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private",
7047 				in_interface ? "Interface" : "Abstract", ZSTR_VAL(ce->name), ZSTR_VAL(name));
7048 		}
7049 
7050 		if (has_body) {
7051 			zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body",
7052 				in_interface ? "Interface" : "Abstract", ZSTR_VAL(ce->name), ZSTR_VAL(name));
7053 		}
7054 
7055 		ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
7056 	} else if (!has_body) {
7057 		zend_error_noreturn(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body",
7058 			ZSTR_VAL(ce->name), ZSTR_VAL(name));
7059 	}
7060 
7061 	op_array->scope = ce;
7062 	op_array->function_name = zend_string_copy(name);
7063 
7064 	lcname = zend_string_tolower(name);
7065 	lcname = zend_new_interned_string(lcname);
7066 
7067 	if (zend_hash_add_ptr(&ce->function_table, lcname, op_array) == NULL) {
7068 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()",
7069 			ZSTR_VAL(ce->name), ZSTR_VAL(name));
7070 	}
7071 
7072 	zend_add_magic_method(ce, (zend_function *) op_array, lcname);
7073 	if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)
7074 			&& !(ce->ce_flags & ZEND_ACC_TRAIT)) {
7075 		add_stringable_interface(ce);
7076 	}
7077 
7078 	return lcname;
7079 }
7080 /* }}} */
7081 
zend_add_dynamic_func_def(zend_op_array * def)7082 static uint32_t zend_add_dynamic_func_def(zend_op_array *def) {
7083 	zend_op_array *op_array = CG(active_op_array);
7084 	uint32_t def_offset = op_array->num_dynamic_func_defs++;
7085 	op_array->dynamic_func_defs = erealloc(
7086 		op_array->dynamic_func_defs, op_array->num_dynamic_func_defs * sizeof(zend_op_array *));
7087 	op_array->dynamic_func_defs[def_offset] = def;
7088 	return def_offset;
7089 }
7090 
zend_begin_func_decl(znode * result,zend_op_array * op_array,zend_ast_decl * decl,bool toplevel)7091 static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl, bool toplevel) /* {{{ */
7092 {
7093 	zend_string *unqualified_name, *name, *lcname;
7094 	zend_op *opline;
7095 
7096 	unqualified_name = decl->name;
7097 	op_array->function_name = name = zend_prefix_with_ns(unqualified_name);
7098 	lcname = zend_string_tolower(name);
7099 
7100 	if (FC(imports_function)) {
7101 		zend_string *import_name =
7102 			zend_hash_find_ptr_lc(FC(imports_function), unqualified_name);
7103 		if (import_name && !zend_string_equals_ci(lcname, import_name)) {
7104 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare function %s "
7105 				"because the name is already in use", ZSTR_VAL(name));
7106 		}
7107 	}
7108 
7109 	if (zend_string_equals_literal(lcname, "__autoload")) {
7110 		zend_error_noreturn(E_COMPILE_ERROR,
7111 			"__autoload() is no longer supported, use spl_autoload_register() instead");
7112 	}
7113 
7114 	if (zend_string_equals_literal_ci(unqualified_name, "assert")) {
7115 		zend_error(E_COMPILE_ERROR,
7116 			"Defining a custom assert() function is not allowed, "
7117 			"as the function has special semantics");
7118 	}
7119 
7120 	zend_register_seen_symbol(lcname, ZEND_SYMBOL_FUNCTION);
7121 	if (toplevel) {
7122 		if (UNEXPECTED(zend_hash_add_ptr(CG(function_table), lcname, op_array) == NULL)) {
7123 			do_bind_function_error(lcname, op_array, 1);
7124 		}
7125 		zend_string_release_ex(lcname, 0);
7126 		return;
7127 	}
7128 
7129 	uint32_t func_ref = zend_add_dynamic_func_def(op_array);
7130 	if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
7131 		opline = zend_emit_op_tmp(result, ZEND_DECLARE_LAMBDA_FUNCTION, NULL, NULL);
7132 		opline->op2.num = func_ref;
7133 	} else {
7134 		opline = get_next_op();
7135 		opline->opcode = ZEND_DECLARE_FUNCTION;
7136 		opline->op1_type = IS_CONST;
7137 		LITERAL_STR(opline->op1, zend_string_copy(lcname));
7138 		opline->op2.num = func_ref;
7139 	}
7140 	zend_string_release_ex(lcname, 0);
7141 }
7142 /* }}} */
7143 
zend_compile_func_decl(znode * result,zend_ast * ast,bool toplevel)7144 static void zend_compile_func_decl(znode *result, zend_ast *ast, bool toplevel) /* {{{ */
7145 {
7146 	zend_ast_decl *decl = (zend_ast_decl *) ast;
7147 	zend_ast *params_ast = decl->child[0];
7148 	zend_ast *uses_ast = decl->child[1];
7149 	zend_ast *stmt_ast = decl->child[2];
7150 	zend_ast *return_type_ast = decl->child[3];
7151 	bool is_method = decl->kind == ZEND_AST_METHOD;
7152 	zend_string *method_lcname = NULL;
7153 
7154 	zend_class_entry *orig_class_entry = CG(active_class_entry);
7155 	zend_op_array *orig_op_array = CG(active_op_array);
7156 	zend_op_array *op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
7157 	zend_oparray_context orig_oparray_context;
7158 	closure_info info;
7159 	memset(&info, 0, sizeof(closure_info));
7160 
7161 	init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE);
7162 
7163 	if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
7164 		op_array->fn_flags |= ZEND_ACC_PRELOADED;
7165 	}
7166 
7167 	ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void *)));
7168 	ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
7169 
7170 	op_array->fn_flags |= (orig_op_array->fn_flags & ZEND_ACC_STRICT_TYPES);
7171 	op_array->fn_flags |= decl->flags;
7172 	op_array->line_start = decl->start_lineno;
7173 	op_array->line_end = decl->end_lineno;
7174 	if (decl->doc_comment) {
7175 		op_array->doc_comment = zend_string_copy(decl->doc_comment);
7176 	}
7177 
7178 	if (decl->kind == ZEND_AST_CLOSURE || decl->kind == ZEND_AST_ARROW_FUNC) {
7179 		op_array->fn_flags |= ZEND_ACC_CLOSURE;
7180 	}
7181 
7182 	if (is_method) {
7183 		bool has_body = stmt_ast != NULL;
7184 		method_lcname = zend_begin_method_decl(op_array, decl->name, has_body);
7185 	} else {
7186 		zend_begin_func_decl(result, op_array, decl, toplevel);
7187 		if (decl->kind == ZEND_AST_ARROW_FUNC) {
7188 			find_implicit_binds(&info, params_ast, stmt_ast);
7189 			compile_implicit_lexical_binds(&info, result, op_array);
7190 		} else if (uses_ast) {
7191 			zend_compile_closure_binding(result, op_array, uses_ast);
7192 		}
7193 	}
7194 
7195 	CG(active_op_array) = op_array;
7196 
7197 	if (decl->child[4]) {
7198 		int target = ZEND_ATTRIBUTE_TARGET_FUNCTION;
7199 
7200 		if (is_method) {
7201 			target = ZEND_ATTRIBUTE_TARGET_METHOD;
7202 		}
7203 
7204 		zend_compile_attributes(&op_array->attributes, decl->child[4], 0, target);
7205 	}
7206 
7207 	/* Do not leak the class scope into free standing functions, even if they are dynamically
7208 	 * defined inside a class method. This is necessary for correct handling of magic constants.
7209 	 * For example __CLASS__ should always be "" inside a free standing function. */
7210 	if (decl->kind == ZEND_AST_FUNC_DECL) {
7211 		CG(active_class_entry) = NULL;
7212 	}
7213 
7214 	if (toplevel) {
7215 		op_array->fn_flags |= ZEND_ACC_TOP_LEVEL;
7216 	}
7217 
7218 	zend_oparray_context_begin(&orig_oparray_context);
7219 
7220 	{
7221 		/* Push a separator to the loop variable stack */
7222 		zend_loop_var dummy_var;
7223 		dummy_var.opcode = ZEND_RETURN;
7224 
7225 		zend_stack_push(&CG(loop_var_stack), (void *) &dummy_var);
7226 	}
7227 
7228 	zend_compile_params(params_ast, return_type_ast,
7229 		is_method && zend_string_equals_literal(method_lcname, ZEND_TOSTRING_FUNC_NAME) ? IS_STRING : 0);
7230 	if (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) {
7231 		zend_mark_function_as_generator();
7232 		zend_emit_op(NULL, ZEND_GENERATOR_CREATE, NULL, NULL);
7233 	}
7234 	if (decl->kind == ZEND_AST_ARROW_FUNC) {
7235 		zend_compile_implicit_closure_uses(&info);
7236 		zend_hash_destroy(&info.uses);
7237 	} else if (uses_ast) {
7238 		zend_compile_closure_uses(uses_ast);
7239 	}
7240 	zend_compile_stmt(stmt_ast);
7241 
7242 	if (is_method) {
7243 		CG(zend_lineno) = decl->start_lineno;
7244 		zend_check_magic_method_implementation(
7245 			CG(active_class_entry), (zend_function *) op_array, method_lcname, E_COMPILE_ERROR);
7246 		zend_string_release_ex(method_lcname, 0);
7247 	}
7248 
7249 	/* put the implicit return on the really last line */
7250 	CG(zend_lineno) = decl->end_lineno;
7251 
7252 	zend_do_extended_stmt();
7253 	zend_emit_final_return(0);
7254 
7255 	zend_init_static_variables_map_ptr(op_array);
7256 	pass_two(CG(active_op_array));
7257 	zend_oparray_context_end(&orig_oparray_context);
7258 
7259 	/* Pop the loop variable stack separator */
7260 	zend_stack_del_top(&CG(loop_var_stack));
7261 
7262 	CG(active_op_array) = orig_op_array;
7263 	CG(active_class_entry) = orig_class_entry;
7264 }
7265 /* }}} */
7266 
zend_compile_prop_decl(zend_ast * ast,zend_ast * type_ast,uint32_t flags,zend_ast * attr_ast)7267 static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags, zend_ast *attr_ast) /* {{{ */
7268 {
7269 	zend_ast_list *list = zend_ast_get_list(ast);
7270 	zend_class_entry *ce = CG(active_class_entry);
7271 	uint32_t i, children = list->children;
7272 
7273 	if (ce->ce_flags & ZEND_ACC_INTERFACE) {
7274 		zend_error_noreturn(E_COMPILE_ERROR, "Interfaces may not include properties");
7275 	}
7276 
7277 	if (ce->ce_flags & ZEND_ACC_ENUM) {
7278 		zend_error_noreturn(E_COMPILE_ERROR, "Enums may not include properties");
7279 	}
7280 
7281 	if (flags & ZEND_ACC_ABSTRACT) {
7282 		zend_error_noreturn(E_COMPILE_ERROR, "Properties cannot be declared abstract");
7283 	}
7284 
7285 	for (i = 0; i < children; ++i) {
7286 		zend_property_info *info;
7287 		zend_ast *prop_ast = list->child[i];
7288 		zend_ast *name_ast = prop_ast->child[0];
7289 		zend_ast **value_ast_ptr = &prop_ast->child[1];
7290 		zend_ast *doc_comment_ast = prop_ast->child[2];
7291 		zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast));
7292 		zend_string *doc_comment = NULL;
7293 		zval value_zv;
7294 		zend_type type = ZEND_TYPE_INIT_NONE(0);
7295 
7296 		if (type_ast) {
7297 			type = zend_compile_typename(type_ast, /* force_allow_null */ 0);
7298 
7299 			if (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_VOID|MAY_BE_NEVER|MAY_BE_CALLABLE)) {
7300 				zend_string *str = zend_type_to_string(type);
7301 				zend_error_noreturn(E_COMPILE_ERROR,
7302 					"Property %s::$%s cannot have type %s",
7303 					ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(str));
7304 			}
7305 		}
7306 
7307 		/* Doc comment has been appended as last element in ZEND_AST_PROP_ELEM ast */
7308 		if (doc_comment_ast) {
7309 			doc_comment = zend_string_copy(zend_ast_get_str(doc_comment_ast));
7310 		}
7311 
7312 		if (flags & ZEND_ACC_FINAL) {
7313 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, "
7314 				"the final modifier is allowed only for methods, classes, and class constants",
7315 				ZSTR_VAL(ce->name), ZSTR_VAL(name));
7316 		}
7317 
7318 		if (zend_hash_exists(&ce->properties_info, name)) {
7319 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s",
7320 				ZSTR_VAL(ce->name), ZSTR_VAL(name));
7321 		}
7322 
7323 		if (*value_ast_ptr) {
7324 			zend_const_expr_to_zval(&value_zv, value_ast_ptr, /* allow_dynamic */ false);
7325 
7326 			if (ZEND_TYPE_IS_SET(type) && !Z_CONSTANT(value_zv)
7327 					&& !zend_is_valid_default_value(type, &value_zv)) {
7328 				zend_string *str = zend_type_to_string(type);
7329 				if (Z_TYPE(value_zv) == IS_NULL && !ZEND_TYPE_IS_INTERSECTION(type)) {
7330 					ZEND_TYPE_FULL_MASK(type) |= MAY_BE_NULL;
7331 					zend_string *nullable_str = zend_type_to_string(type);
7332 
7333 					zend_error_noreturn(E_COMPILE_ERROR,
7334 						"Default value for property of type %s may not be null. "
7335 						"Use the nullable type %s to allow null default value",
7336 						ZSTR_VAL(str), ZSTR_VAL(nullable_str));
7337 				} else {
7338 					zend_error_noreturn(E_COMPILE_ERROR,
7339 						"Cannot use %s as default value for property %s::$%s of type %s",
7340 						zend_zval_type_name(&value_zv),
7341 						ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(str));
7342 				}
7343 			}
7344 		} else if (!ZEND_TYPE_IS_SET(type)) {
7345 			ZVAL_NULL(&value_zv);
7346 		} else {
7347 			ZVAL_UNDEF(&value_zv);
7348 		}
7349 
7350 		if (flags & ZEND_ACC_READONLY) {
7351 			if (!ZEND_TYPE_IS_SET(type)) {
7352 				zend_error_noreturn(E_COMPILE_ERROR, "Readonly property %s::$%s must have type",
7353 					ZSTR_VAL(ce->name), ZSTR_VAL(name));
7354 			}
7355 			if (!Z_ISUNDEF(value_zv)) {
7356 				zend_error_noreturn(E_COMPILE_ERROR,
7357 					"Readonly property %s::$%s cannot have default value",
7358 					ZSTR_VAL(ce->name), ZSTR_VAL(name));
7359 			}
7360 			if (flags & ZEND_ACC_STATIC) {
7361 				zend_error_noreturn(E_COMPILE_ERROR,
7362 					"Static property %s::$%s cannot be readonly",
7363 					ZSTR_VAL(ce->name), ZSTR_VAL(name));
7364 			}
7365 		}
7366 
7367 		info = zend_declare_typed_property(ce, name, &value_zv, flags, doc_comment, type);
7368 
7369 		if (attr_ast) {
7370 			zend_compile_attributes(&info->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_PROPERTY);
7371 		}
7372 	}
7373 }
7374 /* }}} */
7375 
zend_compile_prop_group(zend_ast * ast)7376 static void zend_compile_prop_group(zend_ast *ast) /* {{{ */
7377 {
7378 	zend_ast *type_ast = ast->child[0];
7379 	zend_ast *prop_ast = ast->child[1];
7380 	zend_ast *attr_ast = ast->child[2];
7381 
7382 	zend_compile_prop_decl(prop_ast, type_ast, ast->attr, attr_ast);
7383 }
7384 /* }}} */
7385 
zend_check_const_and_trait_alias_attr(uint32_t attr,const char * entity)7386 static void zend_check_const_and_trait_alias_attr(uint32_t attr, const char* entity) /* {{{ */
7387 {
7388 	if (attr & ZEND_ACC_STATIC) {
7389 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as %s modifier", entity);
7390 	} else if (attr & ZEND_ACC_ABSTRACT) {
7391 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as %s modifier", entity);
7392 	} else if (attr & ZEND_ACC_FINAL) {
7393 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as %s modifier", entity);
7394 	} else if (attr & ZEND_ACC_READONLY) {
7395 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'readonly' as %s modifier", entity);
7396 	}
7397 }
7398 /* }}} */
7399 
zend_compile_class_const_decl(zend_ast * ast,uint32_t flags,zend_ast * attr_ast)7400 static void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_ast *attr_ast) /* {{{ */
7401 {
7402 	zend_ast_list *list = zend_ast_get_list(ast);
7403 	zend_class_entry *ce = CG(active_class_entry);
7404 	uint32_t i, children = list->children;
7405 
7406 	if ((ce->ce_flags & ZEND_ACC_TRAIT) != 0) {
7407 		zend_error_noreturn(E_COMPILE_ERROR, "Traits cannot have constants");
7408 		return;
7409 	}
7410 
7411 	for (i = 0; i < children; ++i) {
7412 		zend_class_constant *c;
7413 		zend_ast *const_ast = list->child[i];
7414 		zend_ast *name_ast = const_ast->child[0];
7415 		zend_ast **value_ast_ptr = &const_ast->child[1];
7416 		zend_ast *doc_comment_ast = const_ast->child[2];
7417 		zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast));
7418 		zend_string *doc_comment = doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL;
7419 		zval value_zv;
7420 
7421 		if (UNEXPECTED(flags & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_READONLY))) {
7422 			zend_check_const_and_trait_alias_attr(flags, "constant");
7423 		}
7424 
7425 		if (UNEXPECTED((flags & ZEND_ACC_PRIVATE) && (flags & ZEND_ACC_FINAL))) {
7426 			zend_error_noreturn(
7427 				E_COMPILE_ERROR, "Private constant %s::%s cannot be final as it is not visible to other classes",
7428 				ZSTR_VAL(ce->name), ZSTR_VAL(name)
7429 			);
7430 		}
7431 
7432 		zend_const_expr_to_zval(&value_zv, value_ast_ptr, /* allow_dynamic */ false);
7433 		c = zend_declare_class_constant_ex(ce, name, &value_zv, flags, doc_comment);
7434 
7435 		if (attr_ast) {
7436 			zend_compile_attributes(&c->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_CLASS_CONST);
7437 		}
7438 	}
7439 }
7440 /* }}} */
7441 
zend_compile_class_const_group(zend_ast * ast)7442 static void zend_compile_class_const_group(zend_ast *ast) /* {{{ */
7443 {
7444 	zend_ast *const_ast = ast->child[0];
7445 	zend_ast *attr_ast = ast->child[1];
7446 
7447 	zend_compile_class_const_decl(const_ast, ast->attr, attr_ast);
7448 }
7449 /* }}} */
7450 
zend_compile_method_ref(zend_ast * ast,zend_trait_method_reference * method_ref)7451 static void zend_compile_method_ref(zend_ast *ast, zend_trait_method_reference *method_ref) /* {{{ */
7452 {
7453 	zend_ast *class_ast = ast->child[0];
7454 	zend_ast *method_ast = ast->child[1];
7455 
7456 	method_ref->method_name = zend_string_copy(zend_ast_get_str(method_ast));
7457 
7458 	if (class_ast) {
7459 		method_ref->class_name = zend_resolve_const_class_name_reference(class_ast, "trait name");
7460 	} else {
7461 		method_ref->class_name = NULL;
7462 	}
7463 }
7464 /* }}} */
7465 
zend_compile_trait_precedence(zend_ast * ast)7466 static void zend_compile_trait_precedence(zend_ast *ast) /* {{{ */
7467 {
7468 	zend_ast *method_ref_ast = ast->child[0];
7469 	zend_ast *insteadof_ast = ast->child[1];
7470 	zend_ast_list *insteadof_list = zend_ast_get_list(insteadof_ast);
7471 	uint32_t i;
7472 
7473 	zend_trait_precedence *precedence = emalloc(sizeof(zend_trait_precedence) + (insteadof_list->children - 1) * sizeof(zend_string*));
7474 	zend_compile_method_ref(method_ref_ast, &precedence->trait_method);
7475 	precedence->num_excludes = insteadof_list->children;
7476 
7477 	for (i = 0; i < insteadof_list->children; ++i) {
7478 		zend_ast *name_ast = insteadof_list->child[i];
7479 		precedence->exclude_class_names[i] =
7480 			zend_resolve_const_class_name_reference(name_ast, "trait name");
7481 	}
7482 
7483 	zend_add_to_list(&CG(active_class_entry)->trait_precedences, precedence);
7484 }
7485 /* }}} */
7486 
zend_compile_trait_alias(zend_ast * ast)7487 static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */
7488 {
7489 	zend_ast *method_ref_ast = ast->child[0];
7490 	zend_ast *alias_ast = ast->child[1];
7491 	uint32_t modifiers = ast->attr;
7492 
7493 	zend_trait_alias *alias;
7494 
7495 	zend_check_const_and_trait_alias_attr(modifiers, "method");
7496 
7497 	alias = emalloc(sizeof(zend_trait_alias));
7498 	zend_compile_method_ref(method_ref_ast, &alias->trait_method);
7499 	alias->modifiers = modifiers;
7500 
7501 	if (alias_ast) {
7502 		alias->alias = zend_string_copy(zend_ast_get_str(alias_ast));
7503 	} else {
7504 		alias->alias = NULL;
7505 	}
7506 
7507 	zend_add_to_list(&CG(active_class_entry)->trait_aliases, alias);
7508 }
7509 /* }}} */
7510 
zend_compile_use_trait(zend_ast * ast)7511 static void zend_compile_use_trait(zend_ast *ast) /* {{{ */
7512 {
7513 	zend_ast_list *traits = zend_ast_get_list(ast->child[0]);
7514 	zend_ast_list *adaptations = ast->child[1] ? zend_ast_get_list(ast->child[1]) : NULL;
7515 	zend_class_entry *ce = CG(active_class_entry);
7516 	uint32_t i;
7517 
7518 	ce->trait_names = erealloc(ce->trait_names, sizeof(zend_class_name) * (ce->num_traits + traits->children));
7519 
7520 	for (i = 0; i < traits->children; ++i) {
7521 		zend_ast *trait_ast = traits->child[i];
7522 
7523 		if (ce->ce_flags & ZEND_ACC_INTERFACE) {
7524 			zend_string *name = zend_ast_get_str(trait_ast);
7525 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use traits inside of interfaces. "
7526 				"%s is used in %s", ZSTR_VAL(name), ZSTR_VAL(ce->name));
7527 		}
7528 
7529 		ce->trait_names[ce->num_traits].name =
7530 			zend_resolve_const_class_name_reference(trait_ast, "trait name");
7531 		ce->trait_names[ce->num_traits].lc_name = zend_string_tolower(ce->trait_names[ce->num_traits].name);
7532 		ce->num_traits++;
7533 	}
7534 
7535 	if (!adaptations) {
7536 		return;
7537 	}
7538 
7539 	for (i = 0; i < adaptations->children; ++i) {
7540 		zend_ast *adaptation_ast = adaptations->child[i];
7541 		switch (adaptation_ast->kind) {
7542 			case ZEND_AST_TRAIT_PRECEDENCE:
7543 				zend_compile_trait_precedence(adaptation_ast);
7544 				break;
7545 			case ZEND_AST_TRAIT_ALIAS:
7546 				zend_compile_trait_alias(adaptation_ast);
7547 				break;
7548 			EMPTY_SWITCH_DEFAULT_CASE()
7549 		}
7550 	}
7551 }
7552 /* }}} */
7553 
zend_compile_implements(zend_ast * ast)7554 static void zend_compile_implements(zend_ast *ast) /* {{{ */
7555 {
7556 	zend_ast_list *list = zend_ast_get_list(ast);
7557 	zend_class_entry *ce = CG(active_class_entry);
7558 	zend_class_name *interface_names;
7559 	uint32_t i;
7560 
7561 	interface_names = emalloc(sizeof(zend_class_name) * list->children);
7562 
7563 	for (i = 0; i < list->children; ++i) {
7564 		zend_ast *class_ast = list->child[i];
7565 		interface_names[i].name =
7566 			zend_resolve_const_class_name_reference(class_ast, "interface name");
7567 		interface_names[i].lc_name = zend_string_tolower(interface_names[i].name);
7568 	}
7569 
7570 	ce->num_interfaces = list->children;
7571 	ce->interface_names = interface_names;
7572 }
7573 /* }}} */
7574 
zend_generate_anon_class_name(zend_ast_decl * decl)7575 static zend_string *zend_generate_anon_class_name(zend_ast_decl *decl)
7576 {
7577 	zend_string *filename = CG(active_op_array)->filename;
7578 	uint32_t start_lineno = decl->start_lineno;
7579 
7580 	/* Use parent or first interface as prefix. */
7581 	zend_string *prefix = ZSTR_KNOWN(ZEND_STR_CLASS);
7582 	if (decl->child[0]) {
7583 		prefix = zend_resolve_const_class_name_reference(decl->child[0], "class name");
7584 	} else if (decl->child[1]) {
7585 		zend_ast_list *list = zend_ast_get_list(decl->child[1]);
7586 		prefix = zend_resolve_const_class_name_reference(list->child[0], "interface name");
7587 	}
7588 
7589 	zend_string *result = zend_strpprintf(0, "%s@anonymous%c%s:%" PRIu32 "$%" PRIx32,
7590 		ZSTR_VAL(prefix), '\0', ZSTR_VAL(filename), start_lineno, CG(rtd_key_counter)++);
7591 	zend_string_release(prefix);
7592 	return zend_new_interned_string(result);
7593 }
7594 
zend_compile_enum_backing_type(zend_class_entry * ce,zend_ast * enum_backing_type_ast)7595 static void zend_compile_enum_backing_type(zend_class_entry *ce, zend_ast *enum_backing_type_ast)
7596 {
7597 	ZEND_ASSERT(ce->ce_flags & ZEND_ACC_ENUM);
7598 	zend_type type = zend_compile_typename(enum_backing_type_ast, 0);
7599 	uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
7600 	if (ZEND_TYPE_IS_COMPLEX(type) || (type_mask != MAY_BE_LONG && type_mask != MAY_BE_STRING)) {
7601 		zend_string *type_string = zend_type_to_string(type);
7602 		zend_error_noreturn(E_COMPILE_ERROR,
7603 			"Enum backing type must be int or string, %s given",
7604 			ZSTR_VAL(type_string));
7605 	}
7606 	if (type_mask == MAY_BE_LONG) {
7607 		ce->enum_backing_type = IS_LONG;
7608 	} else {
7609 		ZEND_ASSERT(type_mask == MAY_BE_STRING);
7610 		ce->enum_backing_type = IS_STRING;
7611 	}
7612 	zend_type_release(type, 0);
7613 
7614 	ce->backed_enum_table = emalloc(sizeof(HashTable));
7615 	zend_hash_init(ce->backed_enum_table, 0, NULL, ZVAL_PTR_DTOR, 0);
7616 }
7617 
zend_compile_class_decl(znode * result,zend_ast * ast,bool toplevel)7618 static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) /* {{{ */
7619 {
7620 	zend_ast_decl *decl = (zend_ast_decl *) ast;
7621 	zend_ast *extends_ast = decl->child[0];
7622 	zend_ast *implements_ast = decl->child[1];
7623 	zend_ast *stmt_ast = decl->child[2];
7624 	zend_ast *enum_backing_type_ast = decl->child[4];
7625 	zend_string *name, *lcname;
7626 	zend_class_entry *ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry));
7627 	zend_op *opline;
7628 
7629 	zend_class_entry *original_ce = CG(active_class_entry);
7630 
7631 	if (EXPECTED((decl->flags & ZEND_ACC_ANON_CLASS) == 0)) {
7632 		zend_string *unqualified_name = decl->name;
7633 
7634 		if (CG(active_class_entry)) {
7635 			zend_error_noreturn(E_COMPILE_ERROR, "Class declarations may not be nested");
7636 		}
7637 
7638 		zend_assert_valid_class_name(unqualified_name);
7639 		name = zend_prefix_with_ns(unqualified_name);
7640 		name = zend_new_interned_string(name);
7641 		lcname = zend_string_tolower(name);
7642 
7643 		if (FC(imports)) {
7644 			zend_string *import_name =
7645 				zend_hash_find_ptr_lc(FC(imports), unqualified_name);
7646 			if (import_name && !zend_string_equals_ci(lcname, import_name)) {
7647 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s "
7648 						"because the name is already in use", ZSTR_VAL(name));
7649 			}
7650 		}
7651 
7652 		zend_register_seen_symbol(lcname, ZEND_SYMBOL_CLASS);
7653 	} else {
7654 		/* Find an anon class name that is not in use yet. */
7655 		name = NULL;
7656 		lcname = NULL;
7657 		do {
7658 			zend_tmp_string_release(name);
7659 			zend_tmp_string_release(lcname);
7660 			name = zend_generate_anon_class_name(decl);
7661 			lcname = zend_string_tolower(name);
7662 		} while (zend_hash_exists(CG(class_table), lcname));
7663 	}
7664 	lcname = zend_new_interned_string(lcname);
7665 
7666 	ce->type = ZEND_USER_CLASS;
7667 	ce->name = name;
7668 	zend_initialize_class_data(ce, 1);
7669 	if (!(decl->flags & ZEND_ACC_ANON_CLASS)) {
7670 		zend_alloc_ce_cache(ce->name);
7671 	}
7672 
7673 	if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
7674 		ce->ce_flags |= ZEND_ACC_PRELOADED;
7675 		ZEND_MAP_PTR_NEW(ce->static_members_table);
7676 		ZEND_MAP_PTR_NEW(ce->mutable_data);
7677 	}
7678 
7679 	ce->ce_flags |= decl->flags;
7680 	ce->info.user.filename = zend_string_copy(zend_get_compiled_filename());
7681 	ce->info.user.line_start = decl->start_lineno;
7682 	ce->info.user.line_end = decl->end_lineno;
7683 
7684 	if (decl->doc_comment) {
7685 		ce->info.user.doc_comment = zend_string_copy(decl->doc_comment);
7686 	}
7687 
7688 	if (UNEXPECTED((decl->flags & ZEND_ACC_ANON_CLASS))) {
7689 		/* Serialization is not supported for anonymous classes */
7690 		ce->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE;
7691 	}
7692 
7693 	if (extends_ast) {
7694 		ce->parent_name =
7695 			zend_resolve_const_class_name_reference(extends_ast, "class name");
7696 	}
7697 
7698 	CG(active_class_entry) = ce;
7699 
7700 	if (decl->child[3]) {
7701 		zend_compile_attributes(&ce->attributes, decl->child[3], 0, ZEND_ATTRIBUTE_TARGET_CLASS);
7702 	}
7703 
7704 	if (implements_ast) {
7705 		zend_compile_implements(implements_ast);
7706 	}
7707 
7708 	if (ce->ce_flags & ZEND_ACC_ENUM) {
7709 		if (enum_backing_type_ast != NULL) {
7710 			zend_compile_enum_backing_type(ce, enum_backing_type_ast);
7711 		}
7712 		zend_enum_add_interfaces(ce);
7713 		zend_enum_register_props(ce);
7714 	}
7715 
7716 	zend_compile_stmt(stmt_ast);
7717 
7718 	/* Reset lineno for final opcodes and errors */
7719 	CG(zend_lineno) = ast->lineno;
7720 
7721 	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) {
7722 		zend_verify_abstract_class(ce);
7723 	}
7724 
7725 	CG(active_class_entry) = original_ce;
7726 
7727 	if (toplevel) {
7728 		ce->ce_flags |= ZEND_ACC_TOP_LEVEL;
7729 	}
7730 
7731 	/* We currently don't early-bind classes that implement interfaces or use traits */
7732 	if (!ce->num_interfaces && !ce->num_traits
7733 	 && !(CG(compiler_options) & ZEND_COMPILE_WITHOUT_EXECUTION)) {
7734 		if (toplevel) {
7735 			if (extends_ast) {
7736 				zend_class_entry *parent_ce = zend_lookup_class_ex(
7737 					ce->parent_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
7738 
7739 				if (parent_ce
7740 				 && ((parent_ce->type != ZEND_INTERNAL_CLASS) || !(CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES))
7741 				 && ((parent_ce->type != ZEND_USER_CLASS) || !(CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) || (parent_ce->info.user.filename == ce->info.user.filename))) {
7742 
7743 					if (zend_try_early_bind(ce, parent_ce, lcname, NULL)) {
7744 						zend_string_release(lcname);
7745 						return;
7746 					}
7747 				}
7748 			} else if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) {
7749 				zend_string_release(lcname);
7750 				zend_build_properties_info_table(ce);
7751 				ce->ce_flags |= ZEND_ACC_LINKED;
7752 				return;
7753 			}
7754 		} else if (!extends_ast) {
7755 			/* Link unbound simple class */
7756 			zend_build_properties_info_table(ce);
7757 			ce->ce_flags |= ZEND_ACC_LINKED;
7758 		}
7759 	}
7760 
7761 	opline = get_next_op();
7762 
7763 	if (ce->parent_name) {
7764 		/* Lowercased parent name */
7765 		zend_string *lc_parent_name = zend_string_tolower(ce->parent_name);
7766 		opline->op2_type = IS_CONST;
7767 		LITERAL_STR(opline->op2, lc_parent_name);
7768 	}
7769 
7770 	opline->op1_type = IS_CONST;
7771 	LITERAL_STR(opline->op1, lcname);
7772 
7773 	if (decl->flags & ZEND_ACC_ANON_CLASS) {
7774 		opline->opcode = ZEND_DECLARE_ANON_CLASS;
7775 		opline->extended_value = zend_alloc_cache_slot();
7776 		zend_make_var_result(result, opline);
7777 		if (!zend_hash_add_ptr(CG(class_table), lcname, ce)) {
7778 			/* We checked above that the class name is not used. This really shouldn't happen. */
7779 			zend_error_noreturn(E_ERROR,
7780 				"Runtime definition key collision for %s. This is a bug", ZSTR_VAL(name));
7781 		}
7782 	} else {
7783 		/* Generate RTD keys until we find one that isn't in use yet. */
7784 		zend_string *key = NULL;
7785 		do {
7786 			zend_tmp_string_release(key);
7787 			key = zend_build_runtime_definition_key(lcname, decl->start_lineno);
7788 		} while (!zend_hash_add_ptr(CG(class_table), key, ce));
7789 
7790 		/* RTD key is placed after lcname literal in op1 */
7791 		zend_add_literal_string(&key);
7792 
7793 		opline->opcode = ZEND_DECLARE_CLASS;
7794 		if (extends_ast && toplevel
7795 			 && (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING)
7796 				/* We currently don't early-bind classes that implement interfaces or use traits */
7797 			 && !ce->num_interfaces && !ce->num_traits
7798 		) {
7799 			CG(active_op_array)->fn_flags |= ZEND_ACC_EARLY_BINDING;
7800 			opline->opcode = ZEND_DECLARE_CLASS_DELAYED;
7801 			opline->extended_value = zend_alloc_cache_slot();
7802 			opline->result_type = IS_UNUSED;
7803 			opline->result.opline_num = -1;
7804 		}
7805 	}
7806 }
7807 /* }}} */
7808 
zend_compile_enum_case(zend_ast * ast)7809 static void zend_compile_enum_case(zend_ast *ast)
7810 {
7811 	zend_class_entry *enum_class = CG(active_class_entry);
7812 	if (!(enum_class->ce_flags & ZEND_ACC_ENUM)) {
7813 		zend_error_noreturn(E_COMPILE_ERROR, "Case can only be used in enums");
7814 	}
7815 
7816 	zend_string *enum_case_name = zval_make_interned_string(zend_ast_get_zval(ast->child[0]));
7817 	zend_string *enum_class_name = enum_class->name;
7818 
7819 	zval class_name_zval;
7820 	ZVAL_STR_COPY(&class_name_zval, enum_class_name);
7821 	zend_ast *class_name_ast = zend_ast_create_zval(&class_name_zval);
7822 
7823 	zval case_name_zval;
7824 	ZVAL_STR_COPY(&case_name_zval, enum_case_name);
7825 	zend_ast *case_name_ast = zend_ast_create_zval(&case_name_zval);
7826 
7827 	zend_ast *case_value_zval_ast = NULL;
7828 	zend_ast *case_value_ast = ast->child[1];
7829 	if (enum_class->enum_backing_type != IS_UNDEF && case_value_ast == NULL) {
7830 		zend_error_noreturn(E_COMPILE_ERROR, "Case %s of backed enum %s must have a value",
7831 			ZSTR_VAL(enum_case_name),
7832 			ZSTR_VAL(enum_class_name));
7833 	}
7834 	if (case_value_ast != NULL) {
7835 		zend_eval_const_expr(&ast->child[1]);
7836 		case_value_ast = ast->child[1];
7837 		if (case_value_ast->kind != ZEND_AST_ZVAL) {
7838 			zend_error_noreturn(
7839 				E_COMPILE_ERROR, "Enum case value must be compile-time evaluatable");
7840 		}
7841 
7842 		zval case_value_zv;
7843 		ZVAL_COPY(&case_value_zv, zend_ast_get_zval(case_value_ast));
7844 		if (enum_class->enum_backing_type == IS_UNDEF) {
7845 			if (Z_TYPE(case_value_zv) == IS_LONG || Z_TYPE(case_value_zv) == IS_STRING) {
7846 				zend_error_noreturn(E_COMPILE_ERROR, "Case %s of non-backed enum %s must not have a value, try adding \": %s\" to the enum declaration",
7847 					ZSTR_VAL(enum_case_name),
7848 					ZSTR_VAL(enum_class_name),
7849 					zend_zval_type_name(&case_value_zv));
7850 			} else {
7851 				zend_error_noreturn(E_COMPILE_ERROR, "Case %s of non-backed enum %s must not have a value",
7852 					ZSTR_VAL(enum_case_name),
7853 					ZSTR_VAL(enum_class_name));
7854 			}
7855 		}
7856 
7857 		if (enum_class->enum_backing_type != Z_TYPE(case_value_zv)) {
7858 			zend_error_noreturn(E_COMPILE_ERROR, "Enum case type %s does not match enum backing type %s",
7859 				zend_get_type_by_const(Z_TYPE(case_value_zv)),
7860 				zend_get_type_by_const(enum_class->enum_backing_type));
7861 		}
7862 
7863 		case_value_zval_ast = zend_ast_create_zval(&case_value_zv);
7864 		Z_TRY_ADDREF(case_name_zval);
7865 		if (enum_class->enum_backing_type == IS_LONG) {
7866 			zend_long long_key = Z_LVAL(case_value_zv);
7867 			zval *existing_case_name = zend_hash_index_find(enum_class->backed_enum_table, long_key);
7868 			if (existing_case_name) {
7869 				zend_error_noreturn(E_COMPILE_ERROR, "Duplicate value in enum %s for cases %s and %s",
7870 					ZSTR_VAL(enum_class_name),
7871 					Z_STRVAL_P(existing_case_name),
7872 					ZSTR_VAL(enum_case_name));
7873 			}
7874 			zend_hash_index_add_new(enum_class->backed_enum_table, long_key, &case_name_zval);
7875 		} else {
7876 			ZEND_ASSERT(enum_class->enum_backing_type == IS_STRING);
7877 			zend_string *string_key = Z_STR(case_value_zv);
7878 			zval *existing_case_name = zend_hash_find(enum_class->backed_enum_table, string_key);
7879 			if (existing_case_name != NULL) {
7880 				zend_error_noreturn(E_COMPILE_ERROR, "Duplicate value in enum %s for cases %s and %s",
7881 					ZSTR_VAL(enum_class_name),
7882 					Z_STRVAL_P(existing_case_name),
7883 					ZSTR_VAL(enum_case_name));
7884 			}
7885 			zend_hash_add_new(enum_class->backed_enum_table, string_key, &case_name_zval);
7886 		}
7887 	}
7888 
7889 	zend_ast *const_enum_init_ast = zend_ast_create(ZEND_AST_CONST_ENUM_INIT, class_name_ast, case_name_ast, case_value_zval_ast);
7890 
7891 	zval value_zv;
7892 	zend_const_expr_to_zval(&value_zv, &const_enum_init_ast, /* allow_dynamic */ false);
7893 
7894 	/* Doc comment has been appended as second last element in ZEND_AST_ENUM ast - attributes are conventionally last */
7895 	zend_ast *doc_comment_ast = ast->child[2];
7896 	zend_string *doc_comment = NULL;
7897 	if (doc_comment_ast) {
7898 		doc_comment = zend_string_copy(zend_ast_get_str(doc_comment_ast));
7899 	}
7900 
7901 	zend_class_constant *c = zend_declare_class_constant_ex(enum_class, enum_case_name, &value_zv, ZEND_ACC_PUBLIC, doc_comment);
7902 	ZEND_CLASS_CONST_FLAGS(c) |= ZEND_CLASS_CONST_IS_CASE;
7903 	zend_ast_destroy(const_enum_init_ast);
7904 
7905 	zend_ast *attr_ast = ast->child[3];
7906 	if (attr_ast) {
7907 		zend_compile_attributes(&c->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_CLASS_CONST);
7908 	}
7909 }
7910 
zend_get_import_ht(uint32_t type)7911 static HashTable *zend_get_import_ht(uint32_t type) /* {{{ */
7912 {
7913 	switch (type) {
7914 		case ZEND_SYMBOL_CLASS:
7915 			if (!FC(imports)) {
7916 				FC(imports) = emalloc(sizeof(HashTable));
7917 				zend_hash_init(FC(imports), 8, NULL, str_dtor, 0);
7918 			}
7919 			return FC(imports);
7920 		case ZEND_SYMBOL_FUNCTION:
7921 			if (!FC(imports_function)) {
7922 				FC(imports_function) = emalloc(sizeof(HashTable));
7923 				zend_hash_init(FC(imports_function), 8, NULL, str_dtor, 0);
7924 			}
7925 			return FC(imports_function);
7926 		case ZEND_SYMBOL_CONST:
7927 			if (!FC(imports_const)) {
7928 				FC(imports_const) = emalloc(sizeof(HashTable));
7929 				zend_hash_init(FC(imports_const), 8, NULL, str_dtor, 0);
7930 			}
7931 			return FC(imports_const);
7932 		EMPTY_SWITCH_DEFAULT_CASE()
7933 	}
7934 
7935 	return NULL;
7936 }
7937 /* }}} */
7938 
zend_get_use_type_str(uint32_t type)7939 static char *zend_get_use_type_str(uint32_t type) /* {{{ */
7940 {
7941 	switch (type) {
7942 		case ZEND_SYMBOL_CLASS:
7943 			return "";
7944 		case ZEND_SYMBOL_FUNCTION:
7945 			return " function";
7946 		case ZEND_SYMBOL_CONST:
7947 			return " const";
7948 		EMPTY_SWITCH_DEFAULT_CASE()
7949 	}
7950 
7951 	return " unknown";
7952 }
7953 /* }}} */
7954 
zend_check_already_in_use(uint32_t type,zend_string * old_name,zend_string * new_name,zend_string * check_name)7955 static void zend_check_already_in_use(uint32_t type, zend_string *old_name, zend_string *new_name, zend_string *check_name) /* {{{ */
7956 {
7957 	if (zend_string_equals_ci(old_name, check_name)) {
7958 		return;
7959 	}
7960 
7961 	zend_error_noreturn(E_COMPILE_ERROR, "Cannot use%s %s as %s because the name "
7962 		"is already in use", zend_get_use_type_str(type), ZSTR_VAL(old_name), ZSTR_VAL(new_name));
7963 }
7964 /* }}} */
7965 
zend_compile_use(zend_ast * ast)7966 static void zend_compile_use(zend_ast *ast) /* {{{ */
7967 {
7968 	zend_ast_list *list = zend_ast_get_list(ast);
7969 	uint32_t i;
7970 	zend_string *current_ns = FC(current_namespace);
7971 	uint32_t type = ast->attr;
7972 	HashTable *current_import = zend_get_import_ht(type);
7973 	bool case_sensitive = type == ZEND_SYMBOL_CONST;
7974 
7975 	for (i = 0; i < list->children; ++i) {
7976 		zend_ast *use_ast = list->child[i];
7977 		zend_ast *old_name_ast = use_ast->child[0];
7978 		zend_ast *new_name_ast = use_ast->child[1];
7979 		zend_string *old_name = zend_ast_get_str(old_name_ast);
7980 		zend_string *new_name, *lookup_name;
7981 
7982 		if (new_name_ast) {
7983 			new_name = zend_string_copy(zend_ast_get_str(new_name_ast));
7984 		} else {
7985 			const char *unqualified_name;
7986 			size_t unqualified_name_len;
7987 			if (zend_get_unqualified_name(old_name, &unqualified_name, &unqualified_name_len)) {
7988 				/* The form "use A\B" is equivalent to "use A\B as B" */
7989 				new_name = zend_string_init(unqualified_name, unqualified_name_len, 0);
7990 			} else {
7991 				new_name = zend_string_copy(old_name);
7992 
7993 				if (!current_ns) {
7994 					zend_error(E_WARNING, "The use statement with non-compound name '%s' "
7995 						"has no effect", ZSTR_VAL(new_name));
7996 				}
7997 			}
7998 		}
7999 
8000 		if (case_sensitive) {
8001 			lookup_name = zend_string_copy(new_name);
8002 		} else {
8003 			lookup_name = zend_string_tolower(new_name);
8004 		}
8005 
8006 		if (type == ZEND_SYMBOL_CLASS && zend_is_reserved_class_name(new_name)) {
8007 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' "
8008 				"is a special class name", ZSTR_VAL(old_name), ZSTR_VAL(new_name), ZSTR_VAL(new_name));
8009 		}
8010 
8011 		if (current_ns) {
8012 			zend_string *ns_name = zend_string_alloc(ZSTR_LEN(current_ns) + 1 + ZSTR_LEN(new_name), 0);
8013 			zend_str_tolower_copy(ZSTR_VAL(ns_name), ZSTR_VAL(current_ns), ZSTR_LEN(current_ns));
8014 			ZSTR_VAL(ns_name)[ZSTR_LEN(current_ns)] = '\\';
8015 			memcpy(ZSTR_VAL(ns_name) + ZSTR_LEN(current_ns) + 1, ZSTR_VAL(lookup_name), ZSTR_LEN(lookup_name) + 1);
8016 
8017 			if (zend_have_seen_symbol(ns_name, type)) {
8018 				zend_check_already_in_use(type, old_name, new_name, ns_name);
8019 			}
8020 
8021 			zend_string_efree(ns_name);
8022 		} else if (zend_have_seen_symbol(lookup_name, type)) {
8023 			zend_check_already_in_use(type, old_name, new_name, lookup_name);
8024 		}
8025 
8026 		zend_string_addref(old_name);
8027 		old_name = zend_new_interned_string(old_name);
8028 		if (!zend_hash_add_ptr(current_import, lookup_name, old_name)) {
8029 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use%s %s as %s because the name "
8030 				"is already in use", zend_get_use_type_str(type), ZSTR_VAL(old_name), ZSTR_VAL(new_name));
8031 		}
8032 
8033 		zend_string_release_ex(lookup_name, 0);
8034 		zend_string_release_ex(new_name, 0);
8035 	}
8036 }
8037 /* }}} */
8038 
zend_compile_group_use(zend_ast * ast)8039 static void zend_compile_group_use(zend_ast *ast) /* {{{ */
8040 {
8041 	uint32_t i;
8042 	zend_string *ns = zend_ast_get_str(ast->child[0]);
8043 	zend_ast_list *list = zend_ast_get_list(ast->child[1]);
8044 
8045 	for (i = 0; i < list->children; i++) {
8046 		zend_ast *inline_use, *use = list->child[i];
8047 		zval *name_zval = zend_ast_get_zval(use->child[0]);
8048 		zend_string *name = Z_STR_P(name_zval);
8049 		zend_string *compound_ns = zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
8050 		zend_string_release_ex(name, 0);
8051 		ZVAL_STR(name_zval, compound_ns);
8052 		inline_use = zend_ast_create_list(1, ZEND_AST_USE, use);
8053 		inline_use->attr = ast->attr ? ast->attr : use->attr;
8054 		zend_compile_use(inline_use);
8055 	}
8056 }
8057 /* }}} */
8058 
zend_compile_const_decl(zend_ast * ast)8059 static void zend_compile_const_decl(zend_ast *ast) /* {{{ */
8060 {
8061 	zend_ast_list *list = zend_ast_get_list(ast);
8062 	uint32_t i;
8063 	for (i = 0; i < list->children; ++i) {
8064 		zend_ast *const_ast = list->child[i];
8065 		zend_ast *name_ast = const_ast->child[0];
8066 		zend_ast **value_ast_ptr = &const_ast->child[1];
8067 		zend_string *unqualified_name = zend_ast_get_str(name_ast);
8068 
8069 		zend_string *name;
8070 		znode name_node, value_node;
8071 		zval *value_zv = &value_node.u.constant;
8072 
8073 		value_node.op_type = IS_CONST;
8074 		zend_const_expr_to_zval(value_zv, value_ast_ptr, /* allow_dynamic */ true);
8075 
8076 		if (zend_get_special_const(ZSTR_VAL(unqualified_name), ZSTR_LEN(unqualified_name))) {
8077 			zend_error_noreturn(E_COMPILE_ERROR,
8078 				"Cannot redeclare constant '%s'", ZSTR_VAL(unqualified_name));
8079 		}
8080 
8081 		name = zend_prefix_with_ns(unqualified_name);
8082 		name = zend_new_interned_string(name);
8083 
8084 		if (FC(imports_const)) {
8085 			zend_string *import_name = zend_hash_find_ptr(FC(imports_const), unqualified_name);
8086 			if (import_name && !zend_string_equals(import_name, name)) {
8087 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare const %s because "
8088 					"the name is already in use", ZSTR_VAL(name));
8089 			}
8090 		}
8091 
8092 		name_node.op_type = IS_CONST;
8093 		ZVAL_STR(&name_node.u.constant, name);
8094 
8095 		zend_emit_op(NULL, ZEND_DECLARE_CONST, &name_node, &value_node);
8096 
8097 		zend_register_seen_symbol(name, ZEND_SYMBOL_CONST);
8098 	}
8099 }
8100 /* }}}*/
8101 
zend_compile_namespace(zend_ast * ast)8102 static void zend_compile_namespace(zend_ast *ast) /* {{{ */
8103 {
8104 	zend_ast *name_ast = ast->child[0];
8105 	zend_ast *stmt_ast = ast->child[1];
8106 	zend_string *name;
8107 	bool with_bracket = stmt_ast != NULL;
8108 
8109 	/* handle mixed syntax declaration or nested namespaces */
8110 	if (!FC(has_bracketed_namespaces)) {
8111 		if (FC(current_namespace)) {
8112 			/* previous namespace declarations were unbracketed */
8113 			if (with_bracket) {
8114 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations "
8115 					"with unbracketed namespace declarations");
8116 			}
8117 		}
8118 	} else {
8119 		/* previous namespace declarations were bracketed */
8120 		if (!with_bracket) {
8121 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations "
8122 				"with unbracketed namespace declarations");
8123 		} else if (FC(current_namespace) || FC(in_namespace)) {
8124 			zend_error_noreturn(E_COMPILE_ERROR, "Namespace declarations cannot be nested");
8125 		}
8126 	}
8127 
8128 	bool is_first_namespace = (!with_bracket && !FC(current_namespace))
8129 		|| (with_bracket && !FC(has_bracketed_namespaces));
8130 	if (is_first_namespace && FAILURE == zend_is_first_statement(ast, /* allow_nop */ 1)) {
8131 		zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be "
8132 			"the very first statement or after any declare call in the script");
8133 	}
8134 
8135 	if (FC(current_namespace)) {
8136 		zend_string_release_ex(FC(current_namespace), 0);
8137 	}
8138 
8139 	if (name_ast) {
8140 		name = zend_ast_get_str(name_ast);
8141 
8142 		if (zend_string_equals_literal_ci(name, "namespace")) {
8143 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", ZSTR_VAL(name));
8144 		}
8145 
8146 		FC(current_namespace) = zend_string_copy(name);
8147 	} else {
8148 		FC(current_namespace) = NULL;
8149 	}
8150 
8151 	zend_reset_import_tables();
8152 
8153 	FC(in_namespace) = 1;
8154 	if (with_bracket) {
8155 		FC(has_bracketed_namespaces) = 1;
8156 	}
8157 
8158 	if (stmt_ast) {
8159 		zend_compile_top_stmt(stmt_ast);
8160 		zend_end_namespace();
8161 	}
8162 }
8163 /* }}} */
8164 
zend_compile_halt_compiler(zend_ast * ast)8165 static void zend_compile_halt_compiler(zend_ast *ast) /* {{{ */
8166 {
8167 	zend_ast *offset_ast = ast->child[0];
8168 	zend_long offset = Z_LVAL_P(zend_ast_get_zval(offset_ast));
8169 
8170 	zend_string *filename, *name;
8171 	const char const_name[] = "__COMPILER_HALT_OFFSET__";
8172 
8173 	if (FC(has_bracketed_namespaces) && FC(in_namespace)) {
8174 		zend_error_noreturn(E_COMPILE_ERROR,
8175 			"__HALT_COMPILER() can only be used from the outermost scope");
8176 	}
8177 
8178 	filename = zend_get_compiled_filename();
8179 	name = zend_mangle_property_name(const_name, sizeof(const_name) - 1,
8180 		ZSTR_VAL(filename), ZSTR_LEN(filename), 0);
8181 
8182 	zend_register_long_constant(ZSTR_VAL(name), ZSTR_LEN(name), offset, CONST_CS, 0);
8183 	zend_string_release_ex(name, 0);
8184 }
8185 /* }}} */
8186 
zend_try_ct_eval_magic_const(zval * zv,zend_ast * ast)8187 static bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */
8188 {
8189 	zend_op_array *op_array = CG(active_op_array);
8190 	zend_class_entry *ce = CG(active_class_entry);
8191 
8192 	switch (ast->attr) {
8193 		case T_LINE:
8194 			ZVAL_LONG(zv, ast->lineno);
8195 			break;
8196 		case T_FILE:
8197 			ZVAL_STR_COPY(zv, CG(compiled_filename));
8198 			break;
8199 		case T_DIR:
8200 		{
8201 			zend_string *filename = CG(compiled_filename);
8202 			zend_string *dirname = zend_string_init(ZSTR_VAL(filename), ZSTR_LEN(filename), 0);
8203 #ifdef ZEND_WIN32
8204 			ZSTR_LEN(dirname) = php_win32_ioutil_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname));
8205 #else
8206 			ZSTR_LEN(dirname) = zend_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname));
8207 #endif
8208 
8209 			if (zend_string_equals_literal(dirname, ".")) {
8210 				dirname = zend_string_extend(dirname, MAXPATHLEN, 0);
8211 #if HAVE_GETCWD
8212 				ZEND_IGNORE_VALUE(VCWD_GETCWD(ZSTR_VAL(dirname), MAXPATHLEN));
8213 #elif HAVE_GETWD
8214 				ZEND_IGNORE_VALUE(VCWD_GETWD(ZSTR_VAL(dirname)));
8215 #endif
8216 				ZSTR_LEN(dirname) = strlen(ZSTR_VAL(dirname));
8217 			}
8218 
8219 			ZVAL_STR(zv, dirname);
8220 			break;
8221 		}
8222 		case T_FUNC_C:
8223 			if (op_array && op_array->function_name) {
8224 				ZVAL_STR_COPY(zv, op_array->function_name);
8225 			} else {
8226 				ZVAL_EMPTY_STRING(zv);
8227 			}
8228 			break;
8229 		case T_METHOD_C:
8230 			/* Detect whether we are directly inside a class (e.g. a class constant) and treat
8231 			 * this as not being inside a function. */
8232 			if (op_array && ce && !op_array->scope && !(op_array->fn_flags & ZEND_ACC_CLOSURE)) {
8233 				op_array = NULL;
8234 			}
8235 			if (op_array && op_array->function_name) {
8236 				if (op_array->scope) {
8237 					ZVAL_NEW_STR(zv,
8238 						zend_create_member_string(op_array->scope->name, op_array->function_name));
8239 				} else {
8240 					ZVAL_STR_COPY(zv, op_array->function_name);
8241 				}
8242 			} else {
8243 				ZVAL_EMPTY_STRING(zv);
8244 			}
8245 			break;
8246 		case T_CLASS_C:
8247 			if (ce) {
8248 				if ((ce->ce_flags & ZEND_ACC_TRAIT) != 0) {
8249 					return 0;
8250 				} else {
8251 					ZVAL_STR_COPY(zv, ce->name);
8252 				}
8253 			} else {
8254 				ZVAL_EMPTY_STRING(zv);
8255 			}
8256 			break;
8257 		case T_TRAIT_C:
8258 			if (ce && (ce->ce_flags & ZEND_ACC_TRAIT) != 0) {
8259 				ZVAL_STR_COPY(zv, ce->name);
8260 			} else {
8261 				ZVAL_EMPTY_STRING(zv);
8262 			}
8263 			break;
8264 		case T_NS_C:
8265 			if (FC(current_namespace)) {
8266 				ZVAL_STR_COPY(zv, FC(current_namespace));
8267 			} else {
8268 				ZVAL_EMPTY_STRING(zv);
8269 			}
8270 			break;
8271 		EMPTY_SWITCH_DEFAULT_CASE()
8272 	}
8273 
8274 	return 1;
8275 }
8276 /* }}} */
8277 
zend_is_op_long_compatible(zval * op)8278 ZEND_API bool zend_is_op_long_compatible(zval *op)
8279 {
8280 	if (Z_TYPE_P(op) == IS_ARRAY) {
8281 		return false;
8282 	}
8283 
8284 	if (Z_TYPE_P(op) == IS_DOUBLE
8285 		&& !zend_is_long_compatible(Z_DVAL_P(op), zend_dval_to_lval(Z_DVAL_P(op)))) {
8286 		return false;
8287 	}
8288 
8289 	if (Z_TYPE_P(op) == IS_STRING) {
8290 		double dval = 0;
8291 		zend_uchar is_num = is_numeric_str_function(Z_STR_P(op), NULL, &dval);
8292 		if (is_num == 0 || (is_num == IS_DOUBLE && !zend_is_long_compatible(dval, zend_dval_to_lval(dval)))) {
8293 			return false;
8294 		}
8295 	}
8296 
8297 	return true;
8298 }
8299 
zend_binary_op_produces_error(uint32_t opcode,zval * op1,zval * op2)8300 ZEND_API bool zend_binary_op_produces_error(uint32_t opcode, zval *op1, zval *op2) /* {{{ */
8301 {
8302 	if ((opcode == ZEND_CONCAT || opcode == ZEND_FAST_CONCAT)) {
8303 		/* Array to string warning. */
8304 		return Z_TYPE_P(op1) == IS_ARRAY || Z_TYPE_P(op2) == IS_ARRAY;
8305 	}
8306 
8307 	if (!(opcode == ZEND_ADD || opcode == ZEND_SUB || opcode == ZEND_MUL || opcode == ZEND_DIV
8308                || opcode == ZEND_POW || opcode == ZEND_MOD || opcode == ZEND_SL || opcode == ZEND_SR
8309                || opcode == ZEND_BW_OR || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR)) {
8310 		/* Only the numeric operations throw errors. */
8311 		return 0;
8312 	}
8313 
8314 	if (Z_TYPE_P(op1) == IS_ARRAY || Z_TYPE_P(op2) == IS_ARRAY) {
8315 		if (opcode == ZEND_ADD && Z_TYPE_P(op1) == IS_ARRAY && Z_TYPE_P(op2) == IS_ARRAY) {
8316 			/* Adding two arrays is allowed. */
8317 			return 0;
8318 		}
8319 
8320 		/* Numeric operators throw when one of the operands is an array. */
8321 		return 1;
8322 	}
8323 
8324 	/* While basic arithmetic operators always produce numeric string errors,
8325 	 * bitwise operators don't produce errors if both operands are strings */
8326 	if ((opcode == ZEND_BW_OR || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR)
8327 		&& Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
8328 		return 0;
8329 	}
8330 
8331 	if (Z_TYPE_P(op1) == IS_STRING
8332 		&& !is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), NULL, NULL, 0)) {
8333 		return 1;
8334 	}
8335 
8336 	if (Z_TYPE_P(op2) == IS_STRING
8337 		&& !is_numeric_string(Z_STRVAL_P(op2), Z_STRLEN_P(op2), NULL, NULL, 0)) {
8338 		return 1;
8339 	}
8340 
8341 	if ((opcode == ZEND_MOD && zval_get_long(op2) == 0)
8342 			|| (opcode == ZEND_DIV && zval_get_double(op2) == 0.0)) {
8343 		/* Division by zero throws an error. */
8344 		return 1;
8345 	}
8346 	if ((opcode == ZEND_SL || opcode == ZEND_SR) && zval_get_long(op2) < 0) {
8347 		/* Shift by negative number throws an error. */
8348 		return 1;
8349 	}
8350 
8351 	/* Operation which cast float/float-strings to integers might produce incompatible float to int errors */
8352 	if (opcode == ZEND_SL || opcode == ZEND_SR || opcode == ZEND_BW_OR
8353 			|| opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR || opcode == ZEND_MOD) {
8354 		return !zend_is_op_long_compatible(op1) || !zend_is_op_long_compatible(op2);
8355 	}
8356 
8357 	return 0;
8358 }
8359 /* }}} */
8360 
zend_try_ct_eval_binary_op(zval * result,uint32_t opcode,zval * op1,zval * op2)8361 static inline bool zend_try_ct_eval_binary_op(zval *result, uint32_t opcode, zval *op1, zval *op2) /* {{{ */
8362 {
8363 	if (zend_binary_op_produces_error(opcode, op1, op2)) {
8364 		return 0;
8365 	}
8366 
8367 	binary_op_type fn = get_binary_op(opcode);
8368 	fn(result, op1, op2);
8369 	return 1;
8370 }
8371 /* }}} */
8372 
zend_unary_op_produces_error(uint32_t opcode,zval * op)8373 ZEND_API bool zend_unary_op_produces_error(uint32_t opcode, zval *op)
8374 {
8375 	if (opcode == ZEND_BW_NOT) {
8376 		/* BW_NOT on string does not convert the string into an integer. */
8377 		if (Z_TYPE_P(op) == IS_STRING) {
8378 			return 0;
8379 		}
8380 		return Z_TYPE_P(op) <= IS_TRUE || !zend_is_op_long_compatible(op);
8381 	}
8382 
8383 	return 0;
8384 }
8385 
zend_try_ct_eval_unary_op(zval * result,uint32_t opcode,zval * op)8386 static inline bool zend_try_ct_eval_unary_op(zval *result, uint32_t opcode, zval *op) /* {{{ */
8387 {
8388 	if (zend_unary_op_produces_error(opcode, op)) {
8389 		return 0;
8390 	}
8391 
8392 	unary_op_type fn = get_unary_op(opcode);
8393 	fn(result, op);
8394 	return 1;
8395 }
8396 /* }}} */
8397 
zend_try_ct_eval_unary_pm(zval * result,zend_ast_kind kind,zval * op)8398 static inline bool zend_try_ct_eval_unary_pm(zval *result, zend_ast_kind kind, zval *op) /* {{{ */
8399 {
8400 	zval right;
8401 	ZVAL_LONG(&right, (kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
8402 	return zend_try_ct_eval_binary_op(result, ZEND_MUL, op, &right);
8403 }
8404 /* }}} */
8405 
zend_ct_eval_greater(zval * result,zend_ast_kind kind,zval * op1,zval * op2)8406 static inline void zend_ct_eval_greater(zval *result, zend_ast_kind kind, zval *op1, zval *op2) /* {{{ */
8407 {
8408 	binary_op_type fn = kind == ZEND_AST_GREATER
8409 		? is_smaller_function : is_smaller_or_equal_function;
8410 	fn(result, op2, op1);
8411 }
8412 /* }}} */
8413 
zend_try_ct_eval_array(zval * result,zend_ast * ast)8414 static bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */
8415 {
8416 	zend_ast_list *list = zend_ast_get_list(ast);
8417 	zend_ast *last_elem_ast = NULL;
8418 	uint32_t i;
8419 	bool is_constant = 1;
8420 
8421 	if (ast->attr == ZEND_ARRAY_SYNTAX_LIST) {
8422 		zend_error(E_COMPILE_ERROR, "Cannot use list() as standalone expression");
8423 	}
8424 
8425 	/* First ensure that *all* child nodes are constant and by-val */
8426 	for (i = 0; i < list->children; ++i) {
8427 		zend_ast *elem_ast = list->child[i];
8428 
8429 		if (elem_ast == NULL) {
8430 			/* Report error at line of last non-empty element */
8431 			if (last_elem_ast) {
8432 				CG(zend_lineno) = zend_ast_get_lineno(last_elem_ast);
8433 			}
8434 			zend_error(E_COMPILE_ERROR, "Cannot use empty array elements in arrays");
8435 		}
8436 
8437 		if (elem_ast->kind != ZEND_AST_UNPACK) {
8438 			zend_eval_const_expr(&elem_ast->child[0]);
8439 			zend_eval_const_expr(&elem_ast->child[1]);
8440 
8441 			if (elem_ast->attr /* by_ref */ || elem_ast->child[0]->kind != ZEND_AST_ZVAL
8442 				|| (elem_ast->child[1] && elem_ast->child[1]->kind != ZEND_AST_ZVAL)
8443 			) {
8444 				is_constant = 0;
8445 			}
8446 		} else {
8447 			zend_eval_const_expr(&elem_ast->child[0]);
8448 
8449 			if (elem_ast->child[0]->kind != ZEND_AST_ZVAL) {
8450 				is_constant = 0;
8451 			}
8452 		}
8453 
8454 		last_elem_ast = elem_ast;
8455 	}
8456 
8457 	if (!is_constant) {
8458 		return 0;
8459 	}
8460 
8461 	if (!list->children) {
8462 		ZVAL_EMPTY_ARRAY(result);
8463 		return 1;
8464 	}
8465 
8466 	array_init_size(result, list->children);
8467 	for (i = 0; i < list->children; ++i) {
8468 		zend_ast *elem_ast = list->child[i];
8469 		zend_ast *value_ast = elem_ast->child[0];
8470 		zend_ast *key_ast;
8471 
8472 		zval *value = zend_ast_get_zval(value_ast);
8473 		if (elem_ast->kind == ZEND_AST_UNPACK) {
8474 			if (Z_TYPE_P(value) == IS_ARRAY) {
8475 				HashTable *ht = Z_ARRVAL_P(value);
8476 				zval *val;
8477 				zend_string *key;
8478 
8479 				ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
8480 					if (key) {
8481 						zend_hash_update(Z_ARRVAL_P(result), key, val);
8482 					} else if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), val)) {
8483 						zval_ptr_dtor(result);
8484 						return 0;
8485 					}
8486 					Z_TRY_ADDREF_P(val);
8487 				} ZEND_HASH_FOREACH_END();
8488 
8489 				continue;
8490 			} else {
8491 				zend_error_noreturn(E_COMPILE_ERROR, "Only arrays and Traversables can be unpacked");
8492 			}
8493 		}
8494 
8495 		Z_TRY_ADDREF_P(value);
8496 
8497 		key_ast = elem_ast->child[1];
8498 		if (key_ast) {
8499 			zval *key = zend_ast_get_zval(key_ast);
8500 			switch (Z_TYPE_P(key)) {
8501 				case IS_LONG:
8502 					zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(key), value);
8503 					break;
8504 				case IS_STRING:
8505 					zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(key), value);
8506 					break;
8507 				case IS_DOUBLE: {
8508 					zend_long lval = zend_dval_to_lval(Z_DVAL_P(key));
8509 					/* Incompatible float will generate an error, leave this to run-time */
8510 					if (!zend_is_long_compatible(Z_DVAL_P(key), lval)) {
8511 						zval_ptr_dtor_nogc(value);
8512 						zval_ptr_dtor(result);
8513 						return 0;
8514 					}
8515 					zend_hash_index_update(Z_ARRVAL_P(result), lval, value);
8516 					break;
8517 				}
8518 				case IS_FALSE:
8519 					zend_hash_index_update(Z_ARRVAL_P(result), 0, value);
8520 					break;
8521 				case IS_TRUE:
8522 					zend_hash_index_update(Z_ARRVAL_P(result), 1, value);
8523 					break;
8524 				case IS_NULL:
8525 					zend_hash_update(Z_ARRVAL_P(result), ZSTR_EMPTY_ALLOC(), value);
8526 					break;
8527 				default:
8528 					zend_error_noreturn(E_COMPILE_ERROR, "Illegal offset type");
8529 					break;
8530 			}
8531 		} else if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), value)) {
8532 			zval_ptr_dtor_nogc(value);
8533 			zval_ptr_dtor(result);
8534 			return 0;
8535 		}
8536 	}
8537 
8538 	return 1;
8539 }
8540 /* }}} */
8541 
zend_compile_binary_op(znode * result,zend_ast * ast)8542 static void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */
8543 {
8544 	zend_ast *left_ast = ast->child[0];
8545 	zend_ast *right_ast = ast->child[1];
8546 	uint32_t opcode = ast->attr;
8547 
8548 	znode left_node, right_node;
8549 
8550 	zend_compile_expr(&left_node, left_ast);
8551 	zend_compile_expr(&right_node, right_ast);
8552 
8553 	if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
8554 		if (zend_try_ct_eval_binary_op(&result->u.constant, opcode,
8555 				&left_node.u.constant, &right_node.u.constant)
8556 		) {
8557 			result->op_type = IS_CONST;
8558 			zval_ptr_dtor(&left_node.u.constant);
8559 			zval_ptr_dtor(&right_node.u.constant);
8560 			return;
8561 		}
8562 	}
8563 
8564 	do {
8565 		if (opcode == ZEND_IS_EQUAL || opcode == ZEND_IS_NOT_EQUAL) {
8566 			if (left_node.op_type == IS_CONST) {
8567 				if (Z_TYPE(left_node.u.constant) == IS_FALSE) {
8568 					opcode = (opcode == ZEND_IS_NOT_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
8569 					zend_emit_op_tmp(result, opcode, &right_node, NULL);
8570 					break;
8571 				} else if (Z_TYPE(left_node.u.constant) == IS_TRUE) {
8572 					opcode = (opcode == ZEND_IS_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
8573 					zend_emit_op_tmp(result, opcode, &right_node, NULL);
8574 					break;
8575 				}
8576 			} else if (right_node.op_type == IS_CONST) {
8577 				if (Z_TYPE(right_node.u.constant) == IS_FALSE) {
8578 					opcode = (opcode == ZEND_IS_NOT_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
8579 					zend_emit_op_tmp(result, opcode, &left_node, NULL);
8580 					break;
8581 				} else if (Z_TYPE(right_node.u.constant) == IS_TRUE) {
8582 					opcode = (opcode == ZEND_IS_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
8583 					zend_emit_op_tmp(result, opcode, &left_node, NULL);
8584 					break;
8585 				}
8586 			}
8587 		} else if (opcode == ZEND_IS_IDENTICAL || opcode == ZEND_IS_NOT_IDENTICAL) {
8588 			/* 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) */
8589 			if (left_node.op_type == IS_CONST) {
8590 				if (Z_TYPE(left_node.u.constant) <= IS_TRUE && Z_TYPE(left_node.u.constant) >= IS_NULL) {
8591 					zend_op *opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &right_node, NULL);
8592 					opline->extended_value =
8593 						(opcode == ZEND_IS_IDENTICAL) ?
8594 							(1 << Z_TYPE(left_node.u.constant)) :
8595 							(MAY_BE_ANY - (1 << Z_TYPE(left_node.u.constant)));
8596 					return;
8597 				}
8598 			} else if (right_node.op_type == IS_CONST) {
8599 				if (Z_TYPE(right_node.u.constant) <= IS_TRUE && Z_TYPE(right_node.u.constant) >= IS_NULL) {
8600 					zend_op *opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &left_node, NULL);
8601 					opline->extended_value =
8602 						(opcode == ZEND_IS_IDENTICAL) ?
8603 							(1 << Z_TYPE(right_node.u.constant)) :
8604 							(MAY_BE_ANY - (1 << Z_TYPE(right_node.u.constant)));
8605 					return;
8606 				}
8607 			}
8608 		} else if (opcode == ZEND_CONCAT) {
8609 			/* convert constant operands to strings at compile-time */
8610 			if (left_node.op_type == IS_CONST) {
8611 				if (Z_TYPE(left_node.u.constant) == IS_ARRAY) {
8612 					zend_emit_op_tmp(&left_node, ZEND_CAST, &left_node, NULL)->extended_value = IS_STRING;
8613 				} else {
8614 					convert_to_string(&left_node.u.constant);
8615 				}
8616 			}
8617 			if (right_node.op_type == IS_CONST) {
8618 				if (Z_TYPE(right_node.u.constant) == IS_ARRAY) {
8619 					zend_emit_op_tmp(&right_node, ZEND_CAST, &right_node, NULL)->extended_value = IS_STRING;
8620 				} else {
8621 					convert_to_string(&right_node.u.constant);
8622 				}
8623 			}
8624 			if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
8625 				opcode = ZEND_FAST_CONCAT;
8626 			}
8627 		}
8628 		zend_emit_op_tmp(result, opcode, &left_node, &right_node);
8629 	} while (0);
8630 }
8631 /* }}} */
8632 
8633 /* We do not use zend_compile_binary_op for this because we want to retain the left-to-right
8634  * evaluation order. */
zend_compile_greater(znode * result,zend_ast * ast)8635 static void zend_compile_greater(znode *result, zend_ast *ast) /* {{{ */
8636 {
8637 	zend_ast *left_ast = ast->child[0];
8638 	zend_ast *right_ast = ast->child[1];
8639 	znode left_node, right_node;
8640 
8641 	ZEND_ASSERT(ast->kind == ZEND_AST_GREATER || ast->kind == ZEND_AST_GREATER_EQUAL);
8642 
8643 	zend_compile_expr(&left_node, left_ast);
8644 	zend_compile_expr(&right_node, right_ast);
8645 
8646 	if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
8647 		result->op_type = IS_CONST;
8648 		zend_ct_eval_greater(&result->u.constant, ast->kind,
8649 			&left_node.u.constant, &right_node.u.constant);
8650 		zval_ptr_dtor(&left_node.u.constant);
8651 		zval_ptr_dtor(&right_node.u.constant);
8652 		return;
8653 	}
8654 
8655 	zend_emit_op_tmp(result,
8656 		ast->kind == ZEND_AST_GREATER ? ZEND_IS_SMALLER : ZEND_IS_SMALLER_OR_EQUAL,
8657 		&right_node, &left_node);
8658 }
8659 /* }}} */
8660 
zend_compile_unary_op(znode * result,zend_ast * ast)8661 static void zend_compile_unary_op(znode *result, zend_ast *ast) /* {{{ */
8662 {
8663 	zend_ast *expr_ast = ast->child[0];
8664 	uint32_t opcode = ast->attr;
8665 
8666 	znode expr_node;
8667 	zend_compile_expr(&expr_node, expr_ast);
8668 
8669 	if (expr_node.op_type == IS_CONST
8670 			&& zend_try_ct_eval_unary_op(&result->u.constant, opcode, &expr_node.u.constant)) {
8671 		result->op_type = IS_CONST;
8672 		zval_ptr_dtor(&expr_node.u.constant);
8673 		return;
8674 	}
8675 
8676 	zend_emit_op_tmp(result, opcode, &expr_node, NULL);
8677 }
8678 /* }}} */
8679 
zend_compile_unary_pm(znode * result,zend_ast * ast)8680 static void zend_compile_unary_pm(znode *result, zend_ast *ast) /* {{{ */
8681 {
8682 	zend_ast *expr_ast = ast->child[0];
8683 	znode expr_node, right_node;
8684 
8685 	ZEND_ASSERT(ast->kind == ZEND_AST_UNARY_PLUS || ast->kind == ZEND_AST_UNARY_MINUS);
8686 
8687 	zend_compile_expr(&expr_node, expr_ast);
8688 
8689 	if (expr_node.op_type == IS_CONST
8690 		&& zend_try_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant)) {
8691 		result->op_type = IS_CONST;
8692 		zval_ptr_dtor(&expr_node.u.constant);
8693 		return;
8694 	}
8695 
8696 	right_node.op_type = IS_CONST;
8697 	ZVAL_LONG(&right_node.u.constant, (ast->kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
8698 	zend_emit_op_tmp(result, ZEND_MUL, &expr_node, &right_node);
8699 }
8700 /* }}} */
8701 
zend_compile_short_circuiting(znode * result,zend_ast * ast)8702 static void zend_compile_short_circuiting(znode *result, zend_ast *ast) /* {{{ */
8703 {
8704 	zend_ast *left_ast = ast->child[0];
8705 	zend_ast *right_ast = ast->child[1];
8706 
8707 	znode left_node, right_node;
8708 	zend_op *opline_jmpz, *opline_bool;
8709 	uint32_t opnum_jmpz;
8710 
8711 	ZEND_ASSERT(ast->kind == ZEND_AST_AND || ast->kind == ZEND_AST_OR);
8712 
8713 	zend_compile_expr(&left_node, left_ast);
8714 
8715 	if (left_node.op_type == IS_CONST) {
8716 		if ((ast->kind == ZEND_AST_AND && !zend_is_true(&left_node.u.constant))
8717 		 || (ast->kind == ZEND_AST_OR && zend_is_true(&left_node.u.constant))) {
8718 			result->op_type = IS_CONST;
8719 			ZVAL_BOOL(&result->u.constant, zend_is_true(&left_node.u.constant));
8720 		} else {
8721 			zend_compile_expr(&right_node, right_ast);
8722 
8723 			if (right_node.op_type == IS_CONST) {
8724 				result->op_type = IS_CONST;
8725 				ZVAL_BOOL(&result->u.constant, zend_is_true(&right_node.u.constant));
8726 
8727 				zval_ptr_dtor(&right_node.u.constant);
8728 			} else {
8729 				zend_emit_op_tmp(result, ZEND_BOOL, &right_node, NULL);
8730 			}
8731 		}
8732 
8733 		zval_ptr_dtor(&left_node.u.constant);
8734 		return;
8735 	}
8736 
8737 	opnum_jmpz = get_next_op_number();
8738 	opline_jmpz = zend_emit_op(NULL, ast->kind == ZEND_AST_AND ? ZEND_JMPZ_EX : ZEND_JMPNZ_EX,
8739 		&left_node, NULL);
8740 
8741 	if (left_node.op_type == IS_TMP_VAR) {
8742 		SET_NODE(opline_jmpz->result, &left_node);
8743 		GET_NODE(result, opline_jmpz->result);
8744 	} else {
8745 		zend_make_tmp_result(result, opline_jmpz);
8746 	}
8747 
8748 	zend_compile_expr(&right_node, right_ast);
8749 
8750 	opline_bool = zend_emit_op(NULL, ZEND_BOOL, &right_node, NULL);
8751 	SET_NODE(opline_bool->result, result);
8752 
8753 	zend_update_jump_target_to_next(opnum_jmpz);
8754 }
8755 /* }}} */
8756 
zend_compile_post_incdec(znode * result,zend_ast * ast)8757 static void zend_compile_post_incdec(znode *result, zend_ast *ast) /* {{{ */
8758 {
8759 	zend_ast *var_ast = ast->child[0];
8760 	ZEND_ASSERT(ast->kind == ZEND_AST_POST_INC || ast->kind == ZEND_AST_POST_DEC);
8761 
8762 	zend_ensure_writable_variable(var_ast);
8763 
8764 	if (var_ast->kind == ZEND_AST_PROP || var_ast->kind == ZEND_AST_NULLSAFE_PROP) {
8765 		zend_op *opline = zend_compile_prop(NULL, var_ast, BP_VAR_RW, 0);
8766 		opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ;
8767 		zend_make_tmp_result(result, opline);
8768 	} else if (var_ast->kind == ZEND_AST_STATIC_PROP) {
8769 		zend_op *opline = zend_compile_static_prop(NULL, var_ast, BP_VAR_RW, 0, 0);
8770 		opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_STATIC_PROP : ZEND_POST_DEC_STATIC_PROP;
8771 		zend_make_tmp_result(result, opline);
8772 	} else {
8773 		znode var_node;
8774 		zend_compile_var(&var_node, var_ast, BP_VAR_RW, 0);
8775 		zend_emit_op_tmp(result, ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC : ZEND_POST_DEC,
8776 			&var_node, NULL);
8777 	}
8778 }
8779 /* }}} */
8780 
zend_compile_pre_incdec(znode * result,zend_ast * ast)8781 static void zend_compile_pre_incdec(znode *result, zend_ast *ast) /* {{{ */
8782 {
8783 	zend_ast *var_ast = ast->child[0];
8784 	ZEND_ASSERT(ast->kind == ZEND_AST_PRE_INC || ast->kind == ZEND_AST_PRE_DEC);
8785 
8786 	zend_ensure_writable_variable(var_ast);
8787 
8788 	if (var_ast->kind == ZEND_AST_PROP || var_ast->kind == ZEND_AST_NULLSAFE_PROP) {
8789 		zend_op *opline = zend_compile_prop(result, var_ast, BP_VAR_RW, 0);
8790 		opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ;
8791 		opline->result_type = IS_TMP_VAR;
8792 		result->op_type = IS_TMP_VAR;
8793 	} else if (var_ast->kind == ZEND_AST_STATIC_PROP) {
8794 		zend_op *opline = zend_compile_static_prop(result, var_ast, BP_VAR_RW, 0, 0);
8795 		opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_STATIC_PROP : ZEND_PRE_DEC_STATIC_PROP;
8796 		opline->result_type = IS_TMP_VAR;
8797 		result->op_type = IS_TMP_VAR;
8798 	} else {
8799 		znode var_node;
8800 		zend_compile_var(&var_node, var_ast, BP_VAR_RW, 0);
8801 		zend_emit_op_tmp(result, ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC : ZEND_PRE_DEC,
8802 			&var_node, NULL);
8803 	}
8804 }
8805 /* }}} */
8806 
zend_compile_cast(znode * result,zend_ast * ast)8807 static void zend_compile_cast(znode *result, zend_ast *ast) /* {{{ */
8808 {
8809 	zend_ast *expr_ast = ast->child[0];
8810 	znode expr_node;
8811 	zend_op *opline;
8812 
8813 	zend_compile_expr(&expr_node, expr_ast);
8814 
8815 	if (ast->attr == _IS_BOOL) {
8816 		opline = zend_emit_op_tmp(result, ZEND_BOOL, &expr_node, NULL);
8817 	} else if (ast->attr == IS_NULL) {
8818 		zend_error(E_COMPILE_ERROR, "The (unset) cast is no longer supported");
8819 	} else {
8820 		opline = zend_emit_op_tmp(result, ZEND_CAST, &expr_node, NULL);
8821 		opline->extended_value = ast->attr;
8822 	}
8823 }
8824 /* }}} */
8825 
zend_compile_shorthand_conditional(znode * result,zend_ast * ast)8826 static void zend_compile_shorthand_conditional(znode *result, zend_ast *ast) /* {{{ */
8827 {
8828 	zend_ast *cond_ast = ast->child[0];
8829 	zend_ast *false_ast = ast->child[2];
8830 
8831 	znode cond_node, false_node;
8832 	zend_op *opline_qm_assign;
8833 	uint32_t opnum_jmp_set;
8834 
8835 	ZEND_ASSERT(ast->child[1] == NULL);
8836 
8837 	zend_compile_expr(&cond_node, cond_ast);
8838 
8839 	opnum_jmp_set = get_next_op_number();
8840 	zend_emit_op_tmp(result, ZEND_JMP_SET, &cond_node, NULL);
8841 
8842 	zend_compile_expr(&false_node, false_ast);
8843 
8844 	opline_qm_assign = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &false_node, NULL);
8845 	SET_NODE(opline_qm_assign->result, result);
8846 
8847 	zend_update_jump_target_to_next(opnum_jmp_set);
8848 }
8849 /* }}} */
8850 
zend_compile_conditional(znode * result,zend_ast * ast)8851 static void zend_compile_conditional(znode *result, zend_ast *ast) /* {{{ */
8852 {
8853 	zend_ast *cond_ast = ast->child[0];
8854 	zend_ast *true_ast = ast->child[1];
8855 	zend_ast *false_ast = ast->child[2];
8856 
8857 	znode cond_node, true_node, false_node;
8858 	zend_op *opline_qm_assign2;
8859 	uint32_t opnum_jmpz, opnum_jmp;
8860 
8861 	if (cond_ast->kind == ZEND_AST_CONDITIONAL
8862 			&& cond_ast->attr != ZEND_PARENTHESIZED_CONDITIONAL) {
8863 		if (cond_ast->child[1]) {
8864 			if (true_ast) {
8865 				zend_error(E_COMPILE_ERROR,
8866 					"Unparenthesized `a ? b : c ? d : e` is not supported. "
8867 					"Use either `(a ? b : c) ? d : e` or `a ? b : (c ? d : e)`");
8868 			} else {
8869 				zend_error(E_COMPILE_ERROR,
8870 					"Unparenthesized `a ? b : c ?: d` is not supported. "
8871 					"Use either `(a ? b : c) ?: d` or `a ? b : (c ?: d)`");
8872 			}
8873 		} else {
8874 			if (true_ast) {
8875 				zend_error(E_COMPILE_ERROR,
8876 					"Unparenthesized `a ?: b ? c : d` is not supported. "
8877 					"Use either `(a ?: b) ? c : d` or `a ?: (b ? c : d)`");
8878 			} else {
8879 				/* This case is harmless:  (a ?: b) ?: c always produces the same result
8880 				 * as a ?: (b ?: c). */
8881 			}
8882 		}
8883 	}
8884 
8885 	if (!true_ast) {
8886 		zend_compile_shorthand_conditional(result, ast);
8887 		return;
8888 	}
8889 
8890 	zend_compile_expr(&cond_node, cond_ast);
8891 
8892 	opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
8893 
8894 	zend_compile_expr(&true_node, true_ast);
8895 
8896 	zend_emit_op_tmp(result, ZEND_QM_ASSIGN, &true_node, NULL);
8897 
8898 	opnum_jmp = zend_emit_jump(0);
8899 
8900 	zend_update_jump_target_to_next(opnum_jmpz);
8901 
8902 	zend_compile_expr(&false_node, false_ast);
8903 
8904 	opline_qm_assign2 = zend_emit_op(NULL, ZEND_QM_ASSIGN, &false_node, NULL);
8905 	SET_NODE(opline_qm_assign2->result, result);
8906 
8907 	zend_update_jump_target_to_next(opnum_jmp);
8908 }
8909 /* }}} */
8910 
zend_compile_coalesce(znode * result,zend_ast * ast)8911 static void zend_compile_coalesce(znode *result, zend_ast *ast) /* {{{ */
8912 {
8913 	zend_ast *expr_ast = ast->child[0];
8914 	zend_ast *default_ast = ast->child[1];
8915 
8916 	znode expr_node, default_node;
8917 	zend_op *opline;
8918 	uint32_t opnum;
8919 
8920 	zend_compile_var(&expr_node, expr_ast, BP_VAR_IS, 0);
8921 
8922 	opnum = get_next_op_number();
8923 	zend_emit_op_tmp(result, ZEND_COALESCE, &expr_node, NULL);
8924 
8925 	zend_compile_expr(&default_node, default_ast);
8926 
8927 	opline = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &default_node, NULL);
8928 	SET_NODE(opline->result, result);
8929 
8930 	opline = &CG(active_op_array)->opcodes[opnum];
8931 	opline->op2.opline_num = get_next_op_number();
8932 }
8933 /* }}} */
8934 
znode_dtor(zval * zv)8935 static void znode_dtor(zval *zv) {
8936 	znode *node = Z_PTR_P(zv);
8937 	if (node->op_type == IS_CONST) {
8938 		zval_ptr_dtor_nogc(&node->u.constant);
8939 	}
8940 	efree(node);
8941 }
8942 
zend_compile_assign_coalesce(znode * result,zend_ast * ast)8943 static void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */
8944 {
8945 	zend_ast *var_ast = ast->child[0];
8946 	zend_ast *default_ast = ast->child[1];
8947 
8948 	znode var_node_is, var_node_w, default_node, assign_node, *node;
8949 	zend_op *opline;
8950 	uint32_t coalesce_opnum;
8951 	bool need_frees = 0;
8952 
8953 	/* Remember expressions compiled during the initial BP_VAR_IS lookup,
8954 	 * to avoid double-evaluation when we compile again with BP_VAR_W. */
8955 	HashTable *orig_memoized_exprs = CG(memoized_exprs);
8956 	int orig_memoize_mode = CG(memoize_mode);
8957 
8958 	zend_ensure_writable_variable(var_ast);
8959 	if (is_this_fetch(var_ast)) {
8960 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
8961 	}
8962 
8963 	ALLOC_HASHTABLE(CG(memoized_exprs));
8964 	zend_hash_init(CG(memoized_exprs), 0, NULL, znode_dtor, 0);
8965 
8966 	CG(memoize_mode) = ZEND_MEMOIZE_COMPILE;
8967 	zend_compile_var(&var_node_is, var_ast, BP_VAR_IS, 0);
8968 
8969 	coalesce_opnum = get_next_op_number();
8970 	zend_emit_op_tmp(result, ZEND_COALESCE, &var_node_is, NULL);
8971 
8972 	CG(memoize_mode) = ZEND_MEMOIZE_NONE;
8973 	if (var_ast->kind == ZEND_AST_DIM) {
8974 		zend_compile_expr_with_potential_assign_to_self(&default_node, default_ast, var_ast);
8975 	} else {
8976 		zend_compile_expr(&default_node, default_ast);
8977 	}
8978 
8979 	CG(memoize_mode) = ZEND_MEMOIZE_FETCH;
8980 	zend_compile_var(&var_node_w, var_ast, BP_VAR_W, 0);
8981 
8982 	/* Reproduce some of the zend_compile_assign() opcode fixup logic here. */
8983 	opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
8984 	switch (var_ast->kind) {
8985 		case ZEND_AST_VAR:
8986 			zend_emit_op_tmp(&assign_node, ZEND_ASSIGN, &var_node_w, &default_node);
8987 			break;
8988 		case ZEND_AST_STATIC_PROP:
8989 			opline->opcode = ZEND_ASSIGN_STATIC_PROP;
8990 			opline->result_type = IS_TMP_VAR;
8991 			var_node_w.op_type = IS_TMP_VAR;
8992 			zend_emit_op_data(&default_node);
8993 			assign_node = var_node_w;
8994 			break;
8995 		case ZEND_AST_DIM:
8996 			opline->opcode = ZEND_ASSIGN_DIM;
8997 			opline->result_type = IS_TMP_VAR;
8998 			var_node_w.op_type = IS_TMP_VAR;
8999 			zend_emit_op_data(&default_node);
9000 			assign_node = var_node_w;
9001 			break;
9002 		case ZEND_AST_PROP:
9003 		case ZEND_AST_NULLSAFE_PROP:
9004 			opline->opcode = ZEND_ASSIGN_OBJ;
9005 			opline->result_type = IS_TMP_VAR;
9006 			var_node_w.op_type = IS_TMP_VAR;
9007 			zend_emit_op_data(&default_node);
9008 			assign_node = var_node_w;
9009 			break;
9010 		EMPTY_SWITCH_DEFAULT_CASE();
9011 	}
9012 
9013 	opline = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &assign_node, NULL);
9014 	SET_NODE(opline->result, result);
9015 
9016 	ZEND_HASH_FOREACH_PTR(CG(memoized_exprs), node) {
9017 		if (node->op_type == IS_TMP_VAR || node->op_type == IS_VAR) {
9018 			need_frees = 1;
9019 			break;
9020 		}
9021 	} ZEND_HASH_FOREACH_END();
9022 
9023 	/* Free DUPed expressions if there are any */
9024 	if (need_frees) {
9025 		uint32_t jump_opnum = zend_emit_jump(0);
9026 		zend_update_jump_target_to_next(coalesce_opnum);
9027 		ZEND_HASH_FOREACH_PTR(CG(memoized_exprs), node) {
9028 			if (node->op_type == IS_TMP_VAR || node->op_type == IS_VAR) {
9029 				zend_emit_op(NULL, ZEND_FREE, node, NULL);
9030 			}
9031 		} ZEND_HASH_FOREACH_END();
9032 		zend_update_jump_target_to_next(jump_opnum);
9033 	} else {
9034 		zend_update_jump_target_to_next(coalesce_opnum);
9035 	}
9036 
9037 	zend_hash_destroy(CG(memoized_exprs));
9038 	FREE_HASHTABLE(CG(memoized_exprs));
9039 	CG(memoized_exprs) = orig_memoized_exprs;
9040 	CG(memoize_mode) = orig_memoize_mode;
9041 }
9042 /* }}} */
9043 
zend_compile_print(znode * result,zend_ast * ast)9044 static void zend_compile_print(znode *result, zend_ast *ast) /* {{{ */
9045 {
9046 	zend_op *opline;
9047 	zend_ast *expr_ast = ast->child[0];
9048 
9049 	znode expr_node;
9050 	zend_compile_expr(&expr_node, expr_ast);
9051 
9052 	opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL);
9053 	opline->extended_value = 1;
9054 
9055 	result->op_type = IS_CONST;
9056 	ZVAL_LONG(&result->u.constant, 1);
9057 }
9058 /* }}} */
9059 
zend_compile_exit(znode * result,zend_ast * ast)9060 static void zend_compile_exit(znode *result, zend_ast *ast) /* {{{ */
9061 {
9062 	zend_ast *expr_ast = ast->child[0];
9063 	znode expr_node;
9064 
9065 	if (expr_ast) {
9066 		zend_compile_expr(&expr_node, expr_ast);
9067 	} else {
9068 		expr_node.op_type = IS_UNUSED;
9069 	}
9070 
9071 	zend_op *opline = zend_emit_op(NULL, ZEND_EXIT, &expr_node, NULL);
9072 	if (result) {
9073 		/* Mark this as an "expression throw" for opcache. */
9074 		opline->extended_value = ZEND_THROW_IS_EXPR;
9075 		result->op_type = IS_CONST;
9076 		ZVAL_TRUE(&result->u.constant);
9077 	}
9078 }
9079 /* }}} */
9080 
zend_compile_yield(znode * result,zend_ast * ast)9081 static void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */
9082 {
9083 	zend_ast *value_ast = ast->child[0];
9084 	zend_ast *key_ast = ast->child[1];
9085 
9086 	znode value_node, key_node;
9087 	znode *value_node_ptr = NULL, *key_node_ptr = NULL;
9088 	zend_op *opline;
9089 	bool returns_by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
9090 
9091 	zend_mark_function_as_generator();
9092 
9093 	if (key_ast) {
9094 		zend_compile_expr(&key_node, key_ast);
9095 		key_node_ptr = &key_node;
9096 	}
9097 
9098 	if (value_ast) {
9099 		if (returns_by_ref && zend_is_variable(value_ast)) {
9100 			zend_compile_var(&value_node, value_ast, BP_VAR_W, 1);
9101 		} else {
9102 			zend_compile_expr(&value_node, value_ast);
9103 		}
9104 		value_node_ptr = &value_node;
9105 	}
9106 
9107 	opline = zend_emit_op(result, ZEND_YIELD, value_node_ptr, key_node_ptr);
9108 
9109 	if (value_ast && returns_by_ref && zend_is_call(value_ast)) {
9110 		opline->extended_value = ZEND_RETURNS_FUNCTION;
9111 	}
9112 }
9113 /* }}} */
9114 
zend_compile_yield_from(znode * result,zend_ast * ast)9115 static void zend_compile_yield_from(znode *result, zend_ast *ast) /* {{{ */
9116 {
9117 	zend_ast *expr_ast = ast->child[0];
9118 	znode expr_node;
9119 
9120 	zend_mark_function_as_generator();
9121 
9122 	if (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
9123 		zend_error_noreturn(E_COMPILE_ERROR,
9124 			"Cannot use \"yield from\" inside a by-reference generator");
9125 	}
9126 
9127 	zend_compile_expr(&expr_node, expr_ast);
9128 	zend_emit_op_tmp(result, ZEND_YIELD_FROM, &expr_node, NULL);
9129 }
9130 /* }}} */
9131 
zend_compile_instanceof(znode * result,zend_ast * ast)9132 static void zend_compile_instanceof(znode *result, zend_ast *ast) /* {{{ */
9133 {
9134 	zend_ast *obj_ast = ast->child[0];
9135 	zend_ast *class_ast = ast->child[1];
9136 
9137 	znode obj_node, class_node;
9138 	zend_op *opline;
9139 
9140 	zend_compile_expr(&obj_node, obj_ast);
9141 	if (obj_node.op_type == IS_CONST) {
9142 		zend_do_free(&obj_node);
9143 		result->op_type = IS_CONST;
9144 		ZVAL_FALSE(&result->u.constant);
9145 		return;
9146 	}
9147 
9148 	zend_compile_class_ref(&class_node, class_ast,
9149 		ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_EXCEPTION | ZEND_FETCH_CLASS_SILENT);
9150 
9151 	opline = zend_emit_op_tmp(result, ZEND_INSTANCEOF, &obj_node, NULL);
9152 
9153 	if (class_node.op_type == IS_CONST) {
9154 		opline->op2_type = IS_CONST;
9155 		opline->op2.constant = zend_add_class_name_literal(
9156 			Z_STR(class_node.u.constant));
9157 		opline->extended_value = zend_alloc_cache_slot();
9158 	} else {
9159 		SET_NODE(opline->op2, &class_node);
9160 	}
9161 }
9162 /* }}} */
9163 
zend_compile_include_or_eval(znode * result,zend_ast * ast)9164 static void zend_compile_include_or_eval(znode *result, zend_ast *ast) /* {{{ */
9165 {
9166 	zend_ast *expr_ast = ast->child[0];
9167 	znode expr_node;
9168 	zend_op *opline;
9169 
9170 	zend_do_extended_fcall_begin();
9171 	zend_compile_expr(&expr_node, expr_ast);
9172 
9173 	opline = zend_emit_op(result, ZEND_INCLUDE_OR_EVAL, &expr_node, NULL);
9174 	opline->extended_value = ast->attr;
9175 
9176 	zend_do_extended_fcall_end();
9177 }
9178 /* }}} */
9179 
zend_compile_isset_or_empty(znode * result,zend_ast * ast)9180 static void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
9181 {
9182 	zend_ast *var_ast = ast->child[0];
9183 
9184 	znode var_node;
9185 	zend_op *opline = NULL;
9186 
9187 	ZEND_ASSERT(ast->kind == ZEND_AST_ISSET || ast->kind == ZEND_AST_EMPTY);
9188 
9189 	if (!zend_is_variable(var_ast)) {
9190 		if (ast->kind == ZEND_AST_EMPTY) {
9191 			/* empty(expr) can be transformed to !expr */
9192 			zend_ast *not_ast = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, var_ast);
9193 			zend_compile_expr(result, not_ast);
9194 			return;
9195 		} else {
9196 			zend_error_noreturn(E_COMPILE_ERROR,
9197 				"Cannot use isset() on the result of an expression "
9198 				"(you can use \"null !== expression\" instead)");
9199 		}
9200 	}
9201 
9202 	if (is_globals_fetch(var_ast)) {
9203 		result->op_type = IS_CONST;
9204 		ZVAL_BOOL(&result->u.constant, ast->kind == ZEND_AST_ISSET);
9205 		return;
9206 	}
9207 
9208 	if (is_global_var_fetch(var_ast)) {
9209 		if (!var_ast->child[1]) {
9210 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
9211 		}
9212 
9213 		zend_compile_expr(&var_node, var_ast->child[1]);
9214 		if (var_node.op_type == IS_CONST) {
9215 			convert_to_string(&var_node.u.constant);
9216 		}
9217 
9218 		opline = zend_emit_op_tmp(result, ZEND_ISSET_ISEMPTY_VAR, &var_node, NULL);
9219 		opline->extended_value =
9220 			ZEND_FETCH_GLOBAL | (ast->kind == ZEND_AST_EMPTY ? ZEND_ISEMPTY : 0);
9221 		return;
9222 	}
9223 
9224 	zend_short_circuiting_mark_inner(var_ast);
9225 	switch (var_ast->kind) {
9226 		case ZEND_AST_VAR:
9227 			if (is_this_fetch(var_ast)) {
9228 				opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_THIS, NULL, NULL);
9229 				CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
9230 			} else if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) {
9231 				opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_CV, &var_node, NULL);
9232 			} else {
9233 				opline = zend_compile_simple_var_no_cv(result, var_ast, BP_VAR_IS, 0);
9234 				opline->opcode = ZEND_ISSET_ISEMPTY_VAR;
9235 			}
9236 			break;
9237 		case ZEND_AST_DIM:
9238 			opline = zend_compile_dim(result, var_ast, BP_VAR_IS);
9239 			opline->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ;
9240 			break;
9241 		case ZEND_AST_PROP:
9242 		case ZEND_AST_NULLSAFE_PROP:
9243 			opline = zend_compile_prop(result, var_ast, BP_VAR_IS, 0);
9244 			opline->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ;
9245 			break;
9246 		case ZEND_AST_STATIC_PROP:
9247 			opline = zend_compile_static_prop(result, var_ast, BP_VAR_IS, 0, 0);
9248 			opline->opcode = ZEND_ISSET_ISEMPTY_STATIC_PROP;
9249 			break;
9250 		EMPTY_SWITCH_DEFAULT_CASE()
9251 	}
9252 
9253 	result->op_type = opline->result_type = IS_TMP_VAR;
9254 	if (!(ast->kind == ZEND_AST_ISSET)) {
9255 		opline->extended_value |= ZEND_ISEMPTY;
9256 	}
9257 }
9258 /* }}} */
9259 
zend_compile_silence(znode * result,zend_ast * ast)9260 static void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
9261 {
9262 	zend_ast *expr_ast = ast->child[0];
9263 	znode silence_node;
9264 
9265 	zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL);
9266 
9267 	if (expr_ast->kind == ZEND_AST_VAR) {
9268 		/* For @$var we need to force a FETCH instruction, otherwise the CV access will
9269 		 * happen outside the silenced section. */
9270 		zend_compile_simple_var_no_cv(result, expr_ast, BP_VAR_R, 0 );
9271 	} else {
9272 		zend_compile_expr(result, expr_ast);
9273 	}
9274 
9275 	zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL);
9276 }
9277 /* }}} */
9278 
zend_compile_shell_exec(znode * result,zend_ast * ast)9279 static void zend_compile_shell_exec(znode *result, zend_ast *ast) /* {{{ */
9280 {
9281 	zend_ast *expr_ast = ast->child[0];
9282 
9283 	zval fn_name;
9284 	zend_ast *name_ast, *args_ast, *call_ast;
9285 
9286 	ZVAL_STRING(&fn_name, "shell_exec");
9287 	name_ast = zend_ast_create_zval(&fn_name);
9288 	args_ast = zend_ast_create_list(1, ZEND_AST_ARG_LIST, expr_ast);
9289 	call_ast = zend_ast_create(ZEND_AST_CALL, name_ast, args_ast);
9290 
9291 	zend_compile_expr(result, call_ast);
9292 
9293 	zval_ptr_dtor(&fn_name);
9294 }
9295 /* }}} */
9296 
zend_compile_array(znode * result,zend_ast * ast)9297 static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
9298 {
9299 	zend_ast_list *list = zend_ast_get_list(ast);
9300 	zend_op *opline;
9301 	uint32_t i, opnum_init = -1;
9302 	bool packed = 1;
9303 
9304 	if (zend_try_ct_eval_array(&result->u.constant, ast)) {
9305 		result->op_type = IS_CONST;
9306 		return;
9307 	}
9308 
9309 	/* Empty arrays are handled at compile-time */
9310 	ZEND_ASSERT(list->children > 0);
9311 
9312 	for (i = 0; i < list->children; ++i) {
9313 		zend_ast *elem_ast = list->child[i];
9314 		zend_ast *value_ast, *key_ast;
9315 		bool by_ref;
9316 		znode value_node, key_node, *key_node_ptr = NULL;
9317 
9318 		if (elem_ast == NULL) {
9319 			zend_error(E_COMPILE_ERROR, "Cannot use empty array elements in arrays");
9320 		}
9321 
9322 		value_ast = elem_ast->child[0];
9323 
9324 		if (elem_ast->kind == ZEND_AST_UNPACK) {
9325 			zend_compile_expr(&value_node, value_ast);
9326 			if (i == 0) {
9327 				opnum_init = get_next_op_number();
9328 				opline = zend_emit_op_tmp(result, ZEND_INIT_ARRAY, NULL, NULL);
9329 			}
9330 			opline = zend_emit_op(NULL, ZEND_ADD_ARRAY_UNPACK, &value_node, NULL);
9331 			SET_NODE(opline->result, result);
9332 			continue;
9333 		}
9334 
9335 		key_ast = elem_ast->child[1];
9336 		by_ref = elem_ast->attr;
9337 
9338 		if (key_ast) {
9339 			zend_compile_expr(&key_node, key_ast);
9340 			zend_handle_numeric_op(&key_node);
9341 			key_node_ptr = &key_node;
9342 		}
9343 
9344 		if (by_ref) {
9345 			zend_ensure_writable_variable(value_ast);
9346 			zend_compile_var(&value_node, value_ast, BP_VAR_W, 1);
9347 		} else {
9348 			zend_compile_expr(&value_node, value_ast);
9349 		}
9350 
9351 		if (i == 0) {
9352 			opnum_init = get_next_op_number();
9353 			opline = zend_emit_op_tmp(result, ZEND_INIT_ARRAY, &value_node, key_node_ptr);
9354 			opline->extended_value = list->children << ZEND_ARRAY_SIZE_SHIFT;
9355 		} else {
9356 			opline = zend_emit_op(NULL, ZEND_ADD_ARRAY_ELEMENT,
9357 				&value_node, key_node_ptr);
9358 			SET_NODE(opline->result, result);
9359 		}
9360 		opline->extended_value |= by_ref;
9361 
9362 		if (key_ast && key_node.op_type == IS_CONST && Z_TYPE(key_node.u.constant) == IS_STRING) {
9363 			packed = 0;
9364 		}
9365 	}
9366 
9367 	/* Add a flag to INIT_ARRAY if we know this array cannot be packed */
9368 	if (!packed) {
9369 		ZEND_ASSERT(opnum_init != (uint32_t)-1);
9370 		opline = &CG(active_op_array)->opcodes[opnum_init];
9371 		opline->extended_value |= ZEND_ARRAY_NOT_PACKED;
9372 	}
9373 }
9374 /* }}} */
9375 
zend_compile_const(znode * result,zend_ast * ast)9376 static void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */
9377 {
9378 	zend_ast *name_ast = ast->child[0];
9379 
9380 	zend_op *opline;
9381 
9382 	bool is_fully_qualified;
9383 	zend_string *orig_name = zend_ast_get_str(name_ast);
9384 	zend_string *resolved_name = zend_resolve_const_name(orig_name, name_ast->attr, &is_fully_qualified);
9385 
9386 	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__"))) {
9387 		zend_ast *last = CG(ast);
9388 
9389 		while (last && last->kind == ZEND_AST_STMT_LIST) {
9390 			zend_ast_list *list = zend_ast_get_list(last);
9391 			if (list->children == 0) {
9392 				break;
9393 			}
9394 			last = list->child[list->children-1];
9395 		}
9396 		if (last && last->kind == ZEND_AST_HALT_COMPILER) {
9397 			result->op_type = IS_CONST;
9398 			ZVAL_LONG(&result->u.constant, Z_LVAL_P(zend_ast_get_zval(last->child[0])));
9399 			zend_string_release_ex(resolved_name, 0);
9400 			return;
9401 		}
9402 	}
9403 
9404 	if (zend_try_ct_eval_const(&result->u.constant, resolved_name, is_fully_qualified)) {
9405 		result->op_type = IS_CONST;
9406 		zend_string_release_ex(resolved_name, 0);
9407 		return;
9408 	}
9409 
9410 	opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, NULL);
9411 	opline->op2_type = IS_CONST;
9412 
9413 	if (is_fully_qualified || !FC(current_namespace)) {
9414 		opline->op2.constant = zend_add_const_name_literal(
9415 			resolved_name, 0);
9416 	} else {
9417 		opline->op1.num = IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE;
9418 		opline->op2.constant = zend_add_const_name_literal(
9419 			resolved_name, 1);
9420 	}
9421 	opline->extended_value = zend_alloc_cache_slot();
9422 }
9423 /* }}} */
9424 
zend_compile_class_const(znode * result,zend_ast * ast)9425 static void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
9426 {
9427 	zend_ast *class_ast;
9428 	zend_ast *const_ast;
9429 	znode class_node, const_node;
9430 	zend_op *opline;
9431 
9432 	zend_eval_const_expr(&ast->child[0]);
9433 	zend_eval_const_expr(&ast->child[1]);
9434 
9435 	class_ast = ast->child[0];
9436 	const_ast = ast->child[1];
9437 
9438 	if (class_ast->kind == ZEND_AST_ZVAL) {
9439 		zend_string *resolved_name;
9440 
9441 		resolved_name = zend_resolve_class_name_ast(class_ast);
9442 		if (const_ast->kind == ZEND_AST_ZVAL && zend_try_ct_eval_class_const(&result->u.constant, resolved_name, zend_ast_get_str(const_ast))) {
9443 			result->op_type = IS_CONST;
9444 			zend_string_release_ex(resolved_name, 0);
9445 			return;
9446 		}
9447 		zend_string_release_ex(resolved_name, 0);
9448 	}
9449 
9450 	zend_compile_class_ref(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
9451 
9452 	zend_compile_expr(&const_node, const_ast);
9453 
9454 	opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_CONSTANT, NULL, &const_node);
9455 
9456 	zend_set_class_name_op1(opline, &class_node);
9457 
9458 	opline->extended_value = zend_alloc_cache_slots(2);
9459 }
9460 /* }}} */
9461 
zend_compile_class_name(znode * result,zend_ast * ast)9462 static void zend_compile_class_name(znode *result, zend_ast *ast) /* {{{ */
9463 {
9464 	zend_ast *class_ast = ast->child[0];
9465 
9466 	if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast)) {
9467 		result->op_type = IS_CONST;
9468 		return;
9469 	}
9470 
9471 	if (class_ast->kind == ZEND_AST_ZVAL) {
9472 		zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
9473 		opline->op1.num = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
9474 	} else {
9475 		znode expr_node;
9476 		zend_compile_expr(&expr_node, class_ast);
9477 		if (expr_node.op_type == IS_CONST) {
9478 			/* Unlikely case that happen if class_ast is constant folded.
9479 			 * Handle it here, to avoid needing a CONST specialization in the VM. */
9480 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"::class\" on value of type %s",
9481 				zend_zval_type_name(&expr_node.u.constant));
9482 		}
9483 
9484 		zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, &expr_node, NULL);
9485 	}
9486 }
9487 /* }}} */
9488 
zend_compile_rope_add_ex(zend_op * opline,znode * result,uint32_t num,znode * elem_node)9489 static zend_op *zend_compile_rope_add_ex(zend_op *opline, znode *result, uint32_t num, znode *elem_node) /* {{{ */
9490 {
9491 	if (num == 0) {
9492 		result->op_type = IS_TMP_VAR;
9493 		result->u.op.var = -1;
9494 		opline->opcode = ZEND_ROPE_INIT;
9495 	} else {
9496 		opline->opcode = ZEND_ROPE_ADD;
9497 		SET_NODE(opline->op1, result);
9498 	}
9499 	SET_NODE(opline->op2, elem_node);
9500 	SET_NODE(opline->result, result);
9501 	opline->extended_value = num;
9502 	return opline;
9503 }
9504 /* }}} */
9505 
zend_compile_rope_add(znode * result,uint32_t num,znode * elem_node)9506 static zend_op *zend_compile_rope_add(znode *result, uint32_t num, znode *elem_node) /* {{{ */
9507 {
9508 	zend_op *opline = get_next_op();
9509 
9510 	if (num == 0) {
9511 		result->op_type = IS_TMP_VAR;
9512 		result->u.op.var = -1;
9513 		opline->opcode = ZEND_ROPE_INIT;
9514 	} else {
9515 		opline->opcode = ZEND_ROPE_ADD;
9516 		SET_NODE(opline->op1, result);
9517 	}
9518 	SET_NODE(opline->op2, elem_node);
9519 	SET_NODE(opline->result, result);
9520 	opline->extended_value = num;
9521 	return opline;
9522 }
9523 /* }}} */
9524 
zend_compile_encaps_list(znode * result,zend_ast * ast)9525 static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
9526 {
9527 	uint32_t i, j;
9528 	uint32_t rope_init_lineno = -1;
9529 	zend_op *opline = NULL, *init_opline;
9530 	znode elem_node, last_const_node;
9531 	zend_ast_list *list = zend_ast_get_list(ast);
9532 	uint32_t reserved_op_number = -1;
9533 
9534 	ZEND_ASSERT(list->children > 0);
9535 
9536 	j = 0;
9537 	last_const_node.op_type = IS_UNUSED;
9538 	for (i = 0; i < list->children; i++) {
9539 		zend_compile_expr(&elem_node, list->child[i]);
9540 
9541 		if (elem_node.op_type == IS_CONST) {
9542 			convert_to_string(&elem_node.u.constant);
9543 
9544 			if (Z_STRLEN(elem_node.u.constant) == 0) {
9545 				zval_ptr_dtor(&elem_node.u.constant);
9546 			} else if (last_const_node.op_type == IS_CONST) {
9547 				concat_function(&last_const_node.u.constant, &last_const_node.u.constant, &elem_node.u.constant);
9548 				zval_ptr_dtor(&elem_node.u.constant);
9549 			} else {
9550 				last_const_node.op_type = IS_CONST;
9551 				ZVAL_COPY_VALUE(&last_const_node.u.constant, &elem_node.u.constant);
9552 				/* Reserve place for ZEND_ROPE_ADD instruction */
9553 				reserved_op_number = get_next_op_number();
9554 				opline = get_next_op();
9555 				opline->opcode = ZEND_NOP;
9556 			}
9557 			continue;
9558 		} else {
9559 			if (j == 0) {
9560 				if (last_const_node.op_type == IS_CONST) {
9561 					rope_init_lineno = reserved_op_number;
9562 				} else {
9563 					rope_init_lineno = get_next_op_number();
9564 				}
9565 			}
9566 			if (last_const_node.op_type == IS_CONST) {
9567 				opline = &CG(active_op_array)->opcodes[reserved_op_number];
9568 				zend_compile_rope_add_ex(opline, result, j++, &last_const_node);
9569 				last_const_node.op_type = IS_UNUSED;
9570 			}
9571 			opline = zend_compile_rope_add(result, j++, &elem_node);
9572 		}
9573 	}
9574 
9575 	if (j == 0) {
9576 		result->op_type = IS_CONST;
9577 		if (last_const_node.op_type == IS_CONST) {
9578 			ZVAL_COPY_VALUE(&result->u.constant, &last_const_node.u.constant);
9579 		} else {
9580 			ZVAL_EMPTY_STRING(&result->u.constant);
9581 			/* empty string */
9582 		}
9583 		CG(active_op_array)->last = reserved_op_number - 1;
9584 		return;
9585 	} else if (last_const_node.op_type == IS_CONST) {
9586 		opline = &CG(active_op_array)->opcodes[reserved_op_number];
9587 		opline = zend_compile_rope_add_ex(opline, result, j++, &last_const_node);
9588 	}
9589 	init_opline = CG(active_op_array)->opcodes + rope_init_lineno;
9590 	if (j == 1) {
9591 		if (opline->op2_type == IS_CONST) {
9592 			GET_NODE(result, opline->op2);
9593 			MAKE_NOP(opline);
9594 		} else {
9595 			opline->opcode = ZEND_CAST;
9596 			opline->extended_value = IS_STRING;
9597 			opline->op1_type = opline->op2_type;
9598 			opline->op1 = opline->op2;
9599 			SET_UNUSED(opline->op2);
9600 			zend_make_tmp_result(result, opline);
9601 		}
9602 	} else if (j == 2) {
9603 		opline->opcode = ZEND_FAST_CONCAT;
9604 		opline->extended_value = 0;
9605 		opline->op1_type = init_opline->op2_type;
9606 		opline->op1 = init_opline->op2;
9607 		zend_make_tmp_result(result, opline);
9608 		MAKE_NOP(init_opline);
9609 	} else {
9610 		uint32_t var;
9611 
9612 		init_opline->extended_value = j;
9613 		opline->opcode = ZEND_ROPE_END;
9614 		zend_make_tmp_result(result, opline);
9615 		var = opline->op1.var = get_temporary_variable();
9616 
9617 		/* Allocates the necessary number of zval slots to keep the rope */
9618 		i = ((j * sizeof(zend_string*)) + (sizeof(zval) - 1)) / sizeof(zval);
9619 		while (i > 1) {
9620 			get_temporary_variable();
9621 			i--;
9622 		}
9623 
9624 		/* Update all the previous opcodes to use the same variable */
9625 		while (opline != init_opline) {
9626 			opline--;
9627 			if (opline->opcode == ZEND_ROPE_ADD &&
9628 			    opline->result.var == (uint32_t)-1) {
9629 				opline->op1.var = var;
9630 				opline->result.var = var;
9631 			} else if (opline->opcode == ZEND_ROPE_INIT &&
9632 			           opline->result.var == (uint32_t)-1) {
9633 				opline->result.var = var;
9634 			}
9635 		}
9636 	}
9637 }
9638 /* }}} */
9639 
zend_compile_magic_const(znode * result,zend_ast * ast)9640 static void zend_compile_magic_const(znode *result, zend_ast *ast) /* {{{ */
9641 {
9642 	zend_op *opline;
9643 
9644 	if (zend_try_ct_eval_magic_const(&result->u.constant, ast)) {
9645 		result->op_type = IS_CONST;
9646 		return;
9647 	}
9648 
9649 	ZEND_ASSERT(ast->attr == T_CLASS_C &&
9650 	            CG(active_class_entry) &&
9651 	            (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != 0);
9652 
9653 	opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
9654 	opline->op1.num = ZEND_FETCH_CLASS_SELF;
9655 }
9656 /* }}} */
9657 
zend_is_allowed_in_const_expr(zend_ast_kind kind)9658 static bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */
9659 {
9660 	return kind == ZEND_AST_ZVAL || kind == ZEND_AST_BINARY_OP
9661 		|| kind == ZEND_AST_GREATER || kind == ZEND_AST_GREATER_EQUAL
9662 		|| kind == ZEND_AST_AND || kind == ZEND_AST_OR
9663 		|| kind == ZEND_AST_UNARY_OP
9664 		|| kind == ZEND_AST_UNARY_PLUS || kind == ZEND_AST_UNARY_MINUS
9665 		|| kind == ZEND_AST_CONDITIONAL || kind == ZEND_AST_DIM
9666 		|| kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM
9667 		|| kind == ZEND_AST_UNPACK
9668 		|| kind == ZEND_AST_CONST || kind == ZEND_AST_CLASS_CONST
9669 		|| kind == ZEND_AST_CLASS_NAME
9670 		|| kind == ZEND_AST_MAGIC_CONST || kind == ZEND_AST_COALESCE
9671 		|| kind == ZEND_AST_CONST_ENUM_INIT
9672 		|| kind == ZEND_AST_NEW || kind == ZEND_AST_ARG_LIST
9673 		|| kind == ZEND_AST_NAMED_ARG;
9674 }
9675 /* }}} */
9676 
zend_compile_const_expr_class_const(zend_ast ** ast_ptr)9677 static void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */
9678 {
9679 	zend_ast *ast = *ast_ptr;
9680 	zend_ast *class_ast = ast->child[0];
9681 	zend_string *class_name;
9682 	int fetch_type;
9683 
9684 	if (class_ast->kind != ZEND_AST_ZVAL) {
9685 		zend_error_noreturn(E_COMPILE_ERROR,
9686 			"Dynamic class names are not allowed in compile-time class constant references");
9687 	}
9688 
9689 	class_name = zend_ast_get_str(class_ast);
9690 	fetch_type = zend_get_class_fetch_type(class_name);
9691 
9692 	if (ZEND_FETCH_CLASS_STATIC == fetch_type) {
9693 		zend_error_noreturn(E_COMPILE_ERROR,
9694 			"\"static::\" is not allowed in compile-time constants");
9695 	}
9696 
9697 	if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
9698 		zend_string *tmp = zend_resolve_class_name_ast(class_ast);
9699 
9700 		zend_string_release_ex(class_name, 0);
9701 		if (tmp != class_name) {
9702 			zval *zv = zend_ast_get_zval(class_ast);
9703 
9704 			ZVAL_STR(zv, tmp);
9705 		}
9706 	}
9707 
9708 	ast->attr |= ZEND_FETCH_CLASS_EXCEPTION;
9709 }
9710 /* }}} */
9711 
zend_compile_const_expr_class_name(zend_ast ** ast_ptr)9712 static void zend_compile_const_expr_class_name(zend_ast **ast_ptr) /* {{{ */
9713 {
9714 	zend_ast *ast = *ast_ptr;
9715 	zend_ast *class_ast = ast->child[0];
9716 	if (class_ast->kind != ZEND_AST_ZVAL) {
9717 		zend_error_noreturn(E_COMPILE_ERROR,
9718 			"(expression)::class cannot be used in constant expressions");
9719 	}
9720 
9721 	zend_string *class_name = zend_ast_get_str(class_ast);
9722 	uint32_t fetch_type = zend_get_class_fetch_type(class_name);
9723 
9724 	switch (fetch_type) {
9725 		case ZEND_FETCH_CLASS_SELF:
9726 		case ZEND_FETCH_CLASS_PARENT:
9727 			/* For the const-eval representation store the fetch type instead of the name. */
9728 			zend_string_release(class_name);
9729 			ast->child[0] = NULL;
9730 			ast->attr = fetch_type;
9731 			return;
9732 		case ZEND_FETCH_CLASS_STATIC:
9733 			zend_error_noreturn(E_COMPILE_ERROR,
9734 				"static::class cannot be used for compile-time class name resolution");
9735 			return;
9736 		EMPTY_SWITCH_DEFAULT_CASE()
9737 	}
9738 }
9739 
zend_compile_const_expr_const(zend_ast ** ast_ptr)9740 static void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */
9741 {
9742 	zend_ast *ast = *ast_ptr;
9743 	zend_ast *name_ast = ast->child[0];
9744 	zend_string *orig_name = zend_ast_get_str(name_ast);
9745 	bool is_fully_qualified;
9746 	zval result;
9747 	zend_string *resolved_name;
9748 
9749 	resolved_name = zend_resolve_const_name(
9750 		orig_name, name_ast->attr, &is_fully_qualified);
9751 
9752 	if (zend_try_ct_eval_const(&result, resolved_name, is_fully_qualified)) {
9753 		zend_string_release_ex(resolved_name, 0);
9754 		zend_ast_destroy(ast);
9755 		*ast_ptr = zend_ast_create_zval(&result);
9756 		return;
9757 	}
9758 
9759 	zend_ast_destroy(ast);
9760 	*ast_ptr = zend_ast_create_constant(resolved_name,
9761 		!is_fully_qualified && FC(current_namespace) ? IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE : 0);
9762 }
9763 /* }}} */
9764 
zend_compile_const_expr_magic_const(zend_ast ** ast_ptr)9765 static void zend_compile_const_expr_magic_const(zend_ast **ast_ptr) /* {{{ */
9766 {
9767 	zend_ast *ast = *ast_ptr;
9768 
9769 	/* Other cases already resolved by constant folding */
9770 	ZEND_ASSERT(ast->attr == T_CLASS_C);
9771 
9772 	zend_ast_destroy(ast);
9773 	*ast_ptr = zend_ast_create(ZEND_AST_CONSTANT_CLASS);
9774 }
9775 /* }}} */
9776 
zend_compile_const_expr_new(zend_ast ** ast_ptr)9777 static void zend_compile_const_expr_new(zend_ast **ast_ptr)
9778 {
9779 	zend_ast *class_ast = (*ast_ptr)->child[0];
9780 	if (class_ast->kind == ZEND_AST_CLASS) {
9781 		zend_error_noreturn(E_COMPILE_ERROR,
9782 			"Cannot use anonymous class in constant expression");
9783 	}
9784 	if (class_ast->kind != ZEND_AST_ZVAL) {
9785 		zend_error_noreturn(E_COMPILE_ERROR,
9786 			"Cannot use dynamic class name in constant expression");
9787 	}
9788 
9789 	zend_string *class_name = zend_resolve_class_name_ast(class_ast);
9790 	int fetch_type = zend_get_class_fetch_type(class_name);
9791 	if (ZEND_FETCH_CLASS_STATIC == fetch_type) {
9792 		zend_error_noreturn(E_COMPILE_ERROR,
9793 			"\"static\" is not allowed in compile-time constants");
9794 	}
9795 
9796 	zval *class_ast_zv = zend_ast_get_zval(class_ast);
9797 	zval_ptr_dtor_nogc(class_ast_zv);
9798 	ZVAL_STR(class_ast_zv, class_name);
9799 	class_ast->attr = fetch_type;
9800 }
9801 
zend_compile_const_expr_args(zend_ast ** ast_ptr)9802 static void zend_compile_const_expr_args(zend_ast **ast_ptr)
9803 {
9804 	zend_ast_list *list = zend_ast_get_list(*ast_ptr);
9805 	bool uses_named_args = false;
9806 	for (uint32_t i = 0; i < list->children; i++) {
9807 		zend_ast *arg = list->child[i];
9808 		if (arg->kind == ZEND_AST_UNPACK) {
9809 			zend_error_noreturn(E_COMPILE_ERROR,
9810 				"Argument unpacking in constant expressions is not supported");
9811 		}
9812 		if (arg->kind == ZEND_AST_NAMED_ARG) {
9813 			uses_named_args = true;
9814 		} else if (uses_named_args) {
9815 			zend_error_noreturn(E_COMPILE_ERROR,
9816 				"Cannot use positional argument after named argument");
9817 		}
9818 	}
9819 	if (uses_named_args) {
9820 		list->attr = 1;
9821 	}
9822 }
9823 
9824 typedef struct {
9825 	/* Whether the value of this expression may differ on each evaluation. */
9826 	bool allow_dynamic;
9827 } const_expr_context;
9828 
zend_compile_const_expr(zend_ast ** ast_ptr,void * context)9829 static void zend_compile_const_expr(zend_ast **ast_ptr, void *context) /* {{{ */
9830 {
9831 	const_expr_context *ctx = (const_expr_context *) context;
9832 	zend_ast *ast = *ast_ptr;
9833 	if (ast == NULL || ast->kind == ZEND_AST_ZVAL) {
9834 		return;
9835 	}
9836 
9837 	if (!zend_is_allowed_in_const_expr(ast->kind)) {
9838 		zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
9839 	}
9840 
9841 	switch (ast->kind) {
9842 		case ZEND_AST_CLASS_CONST:
9843 			zend_compile_const_expr_class_const(ast_ptr);
9844 			break;
9845 		case ZEND_AST_CLASS_NAME:
9846 			zend_compile_const_expr_class_name(ast_ptr);
9847 			break;
9848 		case ZEND_AST_CONST:
9849 			zend_compile_const_expr_const(ast_ptr);
9850 			break;
9851 		case ZEND_AST_MAGIC_CONST:
9852 			zend_compile_const_expr_magic_const(ast_ptr);
9853 			break;
9854 		case ZEND_AST_NEW:
9855 			if (!ctx->allow_dynamic) {
9856 				zend_error_noreturn(E_COMPILE_ERROR,
9857 					"New expressions are not supported in this context");
9858 			}
9859 			zend_compile_const_expr_new(ast_ptr);
9860 			break;
9861 		case ZEND_AST_ARG_LIST:
9862 			zend_compile_const_expr_args(ast_ptr);
9863 			break;
9864 	}
9865 
9866 	zend_ast_apply(ast, zend_compile_const_expr, context);
9867 }
9868 /* }}} */
9869 
zend_const_expr_to_zval(zval * result,zend_ast ** ast_ptr,bool allow_dynamic)9870 void zend_const_expr_to_zval(zval *result, zend_ast **ast_ptr, bool allow_dynamic) /* {{{ */
9871 {
9872 	const_expr_context context;
9873 	context.allow_dynamic = allow_dynamic;
9874 
9875 	zend_eval_const_expr(ast_ptr);
9876 	zend_compile_const_expr(ast_ptr, &context);
9877 	if ((*ast_ptr)->kind != ZEND_AST_ZVAL) {
9878 		/* Replace with compiled AST zval representation. */
9879 		zval ast_zv;
9880 		ZVAL_AST(&ast_zv, zend_ast_copy(*ast_ptr));
9881 		zend_ast_destroy(*ast_ptr);
9882 		*ast_ptr = zend_ast_create_zval(&ast_zv);
9883 	}
9884 	ZVAL_COPY(result, zend_ast_get_zval(*ast_ptr));
9885 }
9886 /* }}} */
9887 
9888 /* Same as compile_stmt, but with early binding */
zend_compile_top_stmt(zend_ast * ast)9889 void zend_compile_top_stmt(zend_ast *ast) /* {{{ */
9890 {
9891 	if (!ast) {
9892 		return;
9893 	}
9894 
9895 	if (ast->kind == ZEND_AST_STMT_LIST) {
9896 		zend_ast_list *list = zend_ast_get_list(ast);
9897 		uint32_t i;
9898 		for (i = 0; i < list->children; ++i) {
9899 			zend_compile_top_stmt(list->child[i]);
9900 		}
9901 		return;
9902 	}
9903 
9904 	if (ast->kind == ZEND_AST_FUNC_DECL) {
9905 		CG(zend_lineno) = ast->lineno;
9906 		zend_compile_func_decl(NULL, ast, 1);
9907 		CG(zend_lineno) = ((zend_ast_decl *) ast)->end_lineno;
9908 	} else if (ast->kind == ZEND_AST_CLASS) {
9909 		CG(zend_lineno) = ast->lineno;
9910 		zend_compile_class_decl(NULL, ast, 1);
9911 		CG(zend_lineno) = ((zend_ast_decl *) ast)->end_lineno;
9912 	} else {
9913 		zend_compile_stmt(ast);
9914 	}
9915 	if (ast->kind != ZEND_AST_NAMESPACE && ast->kind != ZEND_AST_HALT_COMPILER) {
9916 		zend_verify_namespace();
9917 	}
9918 }
9919 /* }}} */
9920 
zend_compile_stmt(zend_ast * ast)9921 static void zend_compile_stmt(zend_ast *ast) /* {{{ */
9922 {
9923 	if (!ast) {
9924 		return;
9925 	}
9926 
9927 	CG(zend_lineno) = ast->lineno;
9928 
9929 	if ((CG(compiler_options) & ZEND_COMPILE_EXTENDED_STMT) && !zend_is_unticked_stmt(ast)) {
9930 		zend_do_extended_stmt();
9931 	}
9932 
9933 	switch (ast->kind) {
9934 		case ZEND_AST_STMT_LIST:
9935 			zend_compile_stmt_list(ast);
9936 			break;
9937 		case ZEND_AST_GLOBAL:
9938 			zend_compile_global_var(ast);
9939 			break;
9940 		case ZEND_AST_STATIC:
9941 			zend_compile_static_var(ast);
9942 			break;
9943 		case ZEND_AST_UNSET:
9944 			zend_compile_unset(ast);
9945 			break;
9946 		case ZEND_AST_RETURN:
9947 			zend_compile_return(ast);
9948 			break;
9949 		case ZEND_AST_ECHO:
9950 			zend_compile_echo(ast);
9951 			break;
9952 		case ZEND_AST_BREAK:
9953 		case ZEND_AST_CONTINUE:
9954 			zend_compile_break_continue(ast);
9955 			break;
9956 		case ZEND_AST_GOTO:
9957 			zend_compile_goto(ast);
9958 			break;
9959 		case ZEND_AST_LABEL:
9960 			zend_compile_label(ast);
9961 			break;
9962 		case ZEND_AST_WHILE:
9963 			zend_compile_while(ast);
9964 			break;
9965 		case ZEND_AST_DO_WHILE:
9966 			zend_compile_do_while(ast);
9967 			break;
9968 		case ZEND_AST_FOR:
9969 			zend_compile_for(ast);
9970 			break;
9971 		case ZEND_AST_FOREACH:
9972 			zend_compile_foreach(ast);
9973 			break;
9974 		case ZEND_AST_IF:
9975 			zend_compile_if(ast);
9976 			break;
9977 		case ZEND_AST_SWITCH:
9978 			zend_compile_switch(ast);
9979 			break;
9980 		case ZEND_AST_TRY:
9981 			zend_compile_try(ast);
9982 			break;
9983 		case ZEND_AST_DECLARE:
9984 			zend_compile_declare(ast);
9985 			break;
9986 		case ZEND_AST_FUNC_DECL:
9987 		case ZEND_AST_METHOD:
9988 			zend_compile_func_decl(NULL, ast, 0);
9989 			break;
9990 		case ZEND_AST_ENUM_CASE:
9991 			zend_compile_enum_case(ast);
9992 			break;
9993 		case ZEND_AST_PROP_GROUP:
9994 			zend_compile_prop_group(ast);
9995 			break;
9996 		case ZEND_AST_CLASS_CONST_GROUP:
9997 			zend_compile_class_const_group(ast);
9998 			break;
9999 		case ZEND_AST_USE_TRAIT:
10000 			zend_compile_use_trait(ast);
10001 			break;
10002 		case ZEND_AST_CLASS:
10003 			zend_compile_class_decl(NULL, ast, 0);
10004 			break;
10005 		case ZEND_AST_GROUP_USE:
10006 			zend_compile_group_use(ast);
10007 			break;
10008 		case ZEND_AST_USE:
10009 			zend_compile_use(ast);
10010 			break;
10011 		case ZEND_AST_CONST_DECL:
10012 			zend_compile_const_decl(ast);
10013 			break;
10014 		case ZEND_AST_NAMESPACE:
10015 			zend_compile_namespace(ast);
10016 			break;
10017 		case ZEND_AST_HALT_COMPILER:
10018 			zend_compile_halt_compiler(ast);
10019 			break;
10020 		case ZEND_AST_THROW:
10021 		case ZEND_AST_EXIT:
10022 			zend_compile_expr(NULL, ast);
10023 			break;
10024 		default:
10025 		{
10026 			znode result;
10027 			zend_compile_expr(&result, ast);
10028 			zend_do_free(&result);
10029 		}
10030 	}
10031 
10032 	if (FC(declarables).ticks && !zend_is_unticked_stmt(ast)) {
10033 		zend_emit_tick();
10034 	}
10035 }
10036 /* }}} */
10037 
zend_compile_expr_inner(znode * result,zend_ast * ast)10038 static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */
10039 {
10040 	/* CG(zend_lineno) = ast->lineno; */
10041 	CG(zend_lineno) = zend_ast_get_lineno(ast);
10042 
10043 	if (CG(memoize_mode) != ZEND_MEMOIZE_NONE) {
10044 		zend_compile_memoized_expr(result, ast);
10045 		return;
10046 	}
10047 
10048 	switch (ast->kind) {
10049 		case ZEND_AST_ZVAL:
10050 			ZVAL_COPY(&result->u.constant, zend_ast_get_zval(ast));
10051 			result->op_type = IS_CONST;
10052 			return;
10053 		case ZEND_AST_ZNODE:
10054 			*result = *zend_ast_get_znode(ast);
10055 			return;
10056 		case ZEND_AST_VAR:
10057 		case ZEND_AST_DIM:
10058 		case ZEND_AST_PROP:
10059 		case ZEND_AST_NULLSAFE_PROP:
10060 		case ZEND_AST_STATIC_PROP:
10061 		case ZEND_AST_CALL:
10062 		case ZEND_AST_METHOD_CALL:
10063 		case ZEND_AST_NULLSAFE_METHOD_CALL:
10064 		case ZEND_AST_STATIC_CALL:
10065 			zend_compile_var(result, ast, BP_VAR_R, 0);
10066 			return;
10067 		case ZEND_AST_ASSIGN:
10068 			zend_compile_assign(result, ast);
10069 			return;
10070 		case ZEND_AST_ASSIGN_REF:
10071 			zend_compile_assign_ref(result, ast);
10072 			return;
10073 		case ZEND_AST_NEW:
10074 			zend_compile_new(result, ast);
10075 			return;
10076 		case ZEND_AST_CLONE:
10077 			zend_compile_clone(result, ast);
10078 			return;
10079 		case ZEND_AST_ASSIGN_OP:
10080 			zend_compile_compound_assign(result, ast);
10081 			return;
10082 		case ZEND_AST_BINARY_OP:
10083 			zend_compile_binary_op(result, ast);
10084 			return;
10085 		case ZEND_AST_GREATER:
10086 		case ZEND_AST_GREATER_EQUAL:
10087 			zend_compile_greater(result, ast);
10088 			return;
10089 		case ZEND_AST_UNARY_OP:
10090 			zend_compile_unary_op(result, ast);
10091 			return;
10092 		case ZEND_AST_UNARY_PLUS:
10093 		case ZEND_AST_UNARY_MINUS:
10094 			zend_compile_unary_pm(result, ast);
10095 			return;
10096 		case ZEND_AST_AND:
10097 		case ZEND_AST_OR:
10098 			zend_compile_short_circuiting(result, ast);
10099 			return;
10100 		case ZEND_AST_POST_INC:
10101 		case ZEND_AST_POST_DEC:
10102 			zend_compile_post_incdec(result, ast);
10103 			return;
10104 		case ZEND_AST_PRE_INC:
10105 		case ZEND_AST_PRE_DEC:
10106 			zend_compile_pre_incdec(result, ast);
10107 			return;
10108 		case ZEND_AST_CAST:
10109 			zend_compile_cast(result, ast);
10110 			return;
10111 		case ZEND_AST_CONDITIONAL:
10112 			zend_compile_conditional(result, ast);
10113 			return;
10114 		case ZEND_AST_COALESCE:
10115 			zend_compile_coalesce(result, ast);
10116 			return;
10117 		case ZEND_AST_ASSIGN_COALESCE:
10118 			zend_compile_assign_coalesce(result, ast);
10119 			return;
10120 		case ZEND_AST_PRINT:
10121 			zend_compile_print(result, ast);
10122 			return;
10123 		case ZEND_AST_EXIT:
10124 			zend_compile_exit(result, ast);
10125 			return;
10126 		case ZEND_AST_YIELD:
10127 			zend_compile_yield(result, ast);
10128 			return;
10129 		case ZEND_AST_YIELD_FROM:
10130 			zend_compile_yield_from(result, ast);
10131 			return;
10132 		case ZEND_AST_INSTANCEOF:
10133 			zend_compile_instanceof(result, ast);
10134 			return;
10135 		case ZEND_AST_INCLUDE_OR_EVAL:
10136 			zend_compile_include_or_eval(result, ast);
10137 			return;
10138 		case ZEND_AST_ISSET:
10139 		case ZEND_AST_EMPTY:
10140 			zend_compile_isset_or_empty(result, ast);
10141 			return;
10142 		case ZEND_AST_SILENCE:
10143 			zend_compile_silence(result, ast);
10144 			return;
10145 		case ZEND_AST_SHELL_EXEC:
10146 			zend_compile_shell_exec(result, ast);
10147 			return;
10148 		case ZEND_AST_ARRAY:
10149 			zend_compile_array(result, ast);
10150 			return;
10151 		case ZEND_AST_CONST:
10152 			zend_compile_const(result, ast);
10153 			return;
10154 		case ZEND_AST_CLASS_CONST:
10155 			zend_compile_class_const(result, ast);
10156 			return;
10157 		case ZEND_AST_CLASS_NAME:
10158 			zend_compile_class_name(result, ast);
10159 			return;
10160 		case ZEND_AST_ENCAPS_LIST:
10161 			zend_compile_encaps_list(result, ast);
10162 			return;
10163 		case ZEND_AST_MAGIC_CONST:
10164 			zend_compile_magic_const(result, ast);
10165 			return;
10166 		case ZEND_AST_CLOSURE:
10167 		case ZEND_AST_ARROW_FUNC:
10168 			zend_compile_func_decl(result, ast, 0);
10169 			return;
10170 		case ZEND_AST_THROW:
10171 			zend_compile_throw(result, ast);
10172 			return;
10173 		case ZEND_AST_MATCH:
10174 			zend_compile_match(result, ast);
10175 			return;
10176 		default:
10177 			ZEND_ASSERT(0 /* not supported */);
10178 	}
10179 }
10180 /* }}} */
10181 
zend_compile_expr(znode * result,zend_ast * ast)10182 static void zend_compile_expr(znode *result, zend_ast *ast)
10183 {
10184 	uint32_t checkpoint = zend_short_circuiting_checkpoint();
10185 	zend_compile_expr_inner(result, ast);
10186 	zend_short_circuiting_commit(checkpoint, result, ast);
10187 }
10188 
zend_compile_var_inner(znode * result,zend_ast * ast,uint32_t type,bool by_ref)10189 static zend_op *zend_compile_var_inner(znode *result, zend_ast *ast, uint32_t type, bool by_ref)
10190 {
10191 	CG(zend_lineno) = zend_ast_get_lineno(ast);
10192 
10193 	switch (ast->kind) {
10194 		case ZEND_AST_VAR:
10195 			return zend_compile_simple_var(result, ast, type, 0);
10196 		case ZEND_AST_DIM:
10197 			return zend_compile_dim(result, ast, type);
10198 		case ZEND_AST_PROP:
10199 		case ZEND_AST_NULLSAFE_PROP:
10200 			return zend_compile_prop(result, ast, type, by_ref);
10201 		case ZEND_AST_STATIC_PROP:
10202 			return zend_compile_static_prop(result, ast, type, by_ref, 0);
10203 		case ZEND_AST_CALL:
10204 			zend_compile_call(result, ast, type);
10205 			return NULL;
10206 		case ZEND_AST_METHOD_CALL:
10207 		case ZEND_AST_NULLSAFE_METHOD_CALL:
10208 			zend_compile_method_call(result, ast, type);
10209 			return NULL;
10210 		case ZEND_AST_STATIC_CALL:
10211 			zend_compile_static_call(result, ast, type);
10212 			return NULL;
10213 		case ZEND_AST_ZNODE:
10214 			*result = *zend_ast_get_znode(ast);
10215 			return NULL;
10216 		default:
10217 			if (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) {
10218 				zend_error_noreturn(E_COMPILE_ERROR,
10219 					"Cannot use temporary expression in write context");
10220 			}
10221 
10222 			zend_compile_expr(result, ast);
10223 			return NULL;
10224 	}
10225 }
10226 
zend_compile_var(znode * result,zend_ast * ast,uint32_t type,bool by_ref)10227 static zend_op *zend_compile_var(znode *result, zend_ast *ast, uint32_t type, bool by_ref) /* {{{ */
10228 {
10229 	uint32_t checkpoint = zend_short_circuiting_checkpoint();
10230 	zend_op *opcode = zend_compile_var_inner(result, ast, type, by_ref);
10231 	zend_short_circuiting_commit(checkpoint, result, ast);
10232 	return opcode;
10233 }
10234 
zend_delayed_compile_var(znode * result,zend_ast * ast,uint32_t type,bool by_ref)10235 static zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type, bool by_ref) /* {{{ */
10236 {
10237 	switch (ast->kind) {
10238 		case ZEND_AST_VAR:
10239 			return zend_compile_simple_var(result, ast, type, 1);
10240 		case ZEND_AST_DIM:
10241 			return zend_delayed_compile_dim(result, ast, type);
10242 		case ZEND_AST_PROP:
10243 		case ZEND_AST_NULLSAFE_PROP:
10244 		{
10245 			zend_op *opline = zend_delayed_compile_prop(result, ast, type);
10246 			if (by_ref) {
10247 				opline->extended_value |= ZEND_FETCH_REF;
10248 			}
10249 			return opline;
10250 		}
10251 		case ZEND_AST_STATIC_PROP:
10252 			return zend_compile_static_prop(result, ast, type, by_ref, 1);
10253 		default:
10254 			return zend_compile_var(result, ast, type, 0);
10255 	}
10256 }
10257 /* }}} */
10258 
zend_eval_const_expr(zend_ast ** ast_ptr)10259 static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
10260 {
10261 	zend_ast *ast = *ast_ptr;
10262 	zval result;
10263 
10264 	if (!ast) {
10265 		return;
10266 	}
10267 
10268 	switch (ast->kind) {
10269 		case ZEND_AST_BINARY_OP:
10270 			zend_eval_const_expr(&ast->child[0]);
10271 			zend_eval_const_expr(&ast->child[1]);
10272 			if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
10273 				return;
10274 			}
10275 
10276 			if (!zend_try_ct_eval_binary_op(&result, ast->attr,
10277 					zend_ast_get_zval(ast->child[0]), zend_ast_get_zval(ast->child[1]))
10278 			) {
10279 				return;
10280 			}
10281 			break;
10282 		case ZEND_AST_GREATER:
10283 		case ZEND_AST_GREATER_EQUAL:
10284 			zend_eval_const_expr(&ast->child[0]);
10285 			zend_eval_const_expr(&ast->child[1]);
10286 			if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
10287 				return;
10288 			}
10289 
10290 			zend_ct_eval_greater(&result, ast->kind,
10291 				zend_ast_get_zval(ast->child[0]), zend_ast_get_zval(ast->child[1]));
10292 			break;
10293 		case ZEND_AST_AND:
10294 		case ZEND_AST_OR:
10295 		{
10296 			bool child0_is_true, child1_is_true;
10297 			zend_eval_const_expr(&ast->child[0]);
10298 			zend_eval_const_expr(&ast->child[1]);
10299 			if (ast->child[0]->kind != ZEND_AST_ZVAL) {
10300 				return;
10301 			}
10302 
10303 			child0_is_true = zend_is_true(zend_ast_get_zval(ast->child[0]));
10304 			if (child0_is_true == (ast->kind == ZEND_AST_OR)) {
10305 				ZVAL_BOOL(&result, ast->kind == ZEND_AST_OR);
10306 				break;
10307 			}
10308 
10309 			if (ast->child[1]->kind != ZEND_AST_ZVAL) {
10310 				return;
10311 			}
10312 
10313 			child1_is_true = zend_is_true(zend_ast_get_zval(ast->child[1]));
10314 			if (ast->kind == ZEND_AST_OR) {
10315 				ZVAL_BOOL(&result, child0_is_true || child1_is_true);
10316 			} else {
10317 				ZVAL_BOOL(&result, child0_is_true && child1_is_true);
10318 			}
10319 			break;
10320 		}
10321 		case ZEND_AST_UNARY_OP:
10322 			zend_eval_const_expr(&ast->child[0]);
10323 			if (ast->child[0]->kind != ZEND_AST_ZVAL) {
10324 				return;
10325 			}
10326 
10327 			if (!zend_try_ct_eval_unary_op(&result, ast->attr, zend_ast_get_zval(ast->child[0]))) {
10328 				return;
10329 			}
10330 			break;
10331 		case ZEND_AST_UNARY_PLUS:
10332 		case ZEND_AST_UNARY_MINUS:
10333 			zend_eval_const_expr(&ast->child[0]);
10334 			if (ast->child[0]->kind != ZEND_AST_ZVAL) {
10335 				return;
10336 			}
10337 
10338 			if (!zend_try_ct_eval_unary_pm(&result, ast->kind, zend_ast_get_zval(ast->child[0]))) {
10339 				return;
10340 			}
10341 			break;
10342 		case ZEND_AST_COALESCE:
10343 			/* Set isset fetch indicator here, opcache disallows runtime altering of the AST */
10344 			if (ast->child[0]->kind == ZEND_AST_DIM) {
10345 				ast->child[0]->attr |= ZEND_DIM_IS;
10346 			}
10347 			zend_eval_const_expr(&ast->child[0]);
10348 
10349 			if (ast->child[0]->kind != ZEND_AST_ZVAL) {
10350 				/* ensure everything was compile-time evaluated at least once */
10351 				zend_eval_const_expr(&ast->child[1]);
10352 				return;
10353 			}
10354 
10355 			if (Z_TYPE_P(zend_ast_get_zval(ast->child[0])) == IS_NULL) {
10356 				zend_eval_const_expr(&ast->child[1]);
10357 				*ast_ptr = ast->child[1];
10358 				ast->child[1] = NULL;
10359 				zend_ast_destroy(ast);
10360 			} else {
10361 				*ast_ptr = ast->child[0];
10362 				ast->child[0] = NULL;
10363 				zend_ast_destroy(ast);
10364 			}
10365 			return;
10366 		case ZEND_AST_CONDITIONAL:
10367 		{
10368 			zend_ast **child, *child_ast;
10369 			zend_eval_const_expr(&ast->child[0]);
10370 			if (ast->child[0]->kind != ZEND_AST_ZVAL) {
10371 				/* ensure everything was compile-time evaluated at least once */
10372 				if (ast->child[1]) {
10373 					zend_eval_const_expr(&ast->child[1]);
10374 				}
10375 				zend_eval_const_expr(&ast->child[2]);
10376 				return;
10377 			}
10378 
10379 			child = &ast->child[2 - zend_is_true(zend_ast_get_zval(ast->child[0]))];
10380 			if (*child == NULL) {
10381 				child--;
10382 			}
10383 			child_ast = *child;
10384 			*child = NULL;
10385 			zend_ast_destroy(ast);
10386 			*ast_ptr = child_ast;
10387 			zend_eval_const_expr(ast_ptr);
10388 			return;
10389 		}
10390 		case ZEND_AST_DIM:
10391 		{
10392 			/* constant expression should be always read context ... */
10393 			zval *container, *dim;
10394 
10395 			if (ast->child[1] == NULL) {
10396 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
10397 			}
10398 
10399 			if (ast->attr & ZEND_DIM_ALTERNATIVE_SYNTAX) {
10400 				ast->attr &= ~ZEND_DIM_ALTERNATIVE_SYNTAX; /* remove flag to avoid duplicate warning */
10401 				zend_error(E_COMPILE_ERROR, "Array and string offset access syntax with curly braces is no longer supported");
10402 			}
10403 
10404 			/* Set isset fetch indicator here, opcache disallows runtime altering of the AST */
10405 			if ((ast->attr & ZEND_DIM_IS) && ast->child[0]->kind == ZEND_AST_DIM) {
10406 				ast->child[0]->attr |= ZEND_DIM_IS;
10407 			}
10408 
10409 			zend_eval_const_expr(&ast->child[0]);
10410 			zend_eval_const_expr(&ast->child[1]);
10411 			if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
10412 				return;
10413 			}
10414 
10415 			container = zend_ast_get_zval(ast->child[0]);
10416 			dim = zend_ast_get_zval(ast->child[1]);
10417 
10418 			if (Z_TYPE_P(container) == IS_ARRAY) {
10419 				zval *el;
10420 				if (Z_TYPE_P(dim) == IS_LONG) {
10421 					el = zend_hash_index_find(Z_ARR_P(container), Z_LVAL_P(dim));
10422 					if (el) {
10423 						ZVAL_COPY(&result, el);
10424 					} else {
10425 						return;
10426 					}
10427 				} else if (Z_TYPE_P(dim) == IS_STRING) {
10428 					el = zend_symtable_find(Z_ARR_P(container), Z_STR_P(dim));
10429 					if (el) {
10430 						ZVAL_COPY(&result, el);
10431 					} else {
10432 						return;
10433 					}
10434 				} else {
10435 					return; /* warning... handle at runtime */
10436 				}
10437 			} else if (Z_TYPE_P(container) == IS_STRING) {
10438 				zend_long offset;
10439 				zend_uchar c;
10440 				if (Z_TYPE_P(dim) == IS_LONG) {
10441 					offset = Z_LVAL_P(dim);
10442 				} else if (Z_TYPE_P(dim) != IS_STRING || is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), &offset, NULL, 1) != IS_LONG) {
10443 					return;
10444 				}
10445 				if (offset < 0 || (size_t)offset >= Z_STRLEN_P(container)) {
10446 					return;
10447 				}
10448 				c = (zend_uchar) Z_STRVAL_P(container)[offset];
10449 				ZVAL_CHAR(&result, c);
10450 			} else if (Z_TYPE_P(container) <= IS_FALSE) {
10451 				ZVAL_NULL(&result);
10452 			} else {
10453 				return;
10454 			}
10455 			break;
10456 		}
10457 		case ZEND_AST_ARRAY:
10458 			if (!zend_try_ct_eval_array(&result, ast)) {
10459 				return;
10460 			}
10461 			break;
10462 		case ZEND_AST_MAGIC_CONST:
10463 			if (!zend_try_ct_eval_magic_const(&result, ast)) {
10464 				return;
10465 			}
10466 			break;
10467 		case ZEND_AST_CONST:
10468 		{
10469 			zend_ast *name_ast = ast->child[0];
10470 			bool is_fully_qualified;
10471 			zend_string *resolved_name = zend_resolve_const_name(
10472 				zend_ast_get_str(name_ast), name_ast->attr, &is_fully_qualified);
10473 
10474 			if (!zend_try_ct_eval_const(&result, resolved_name, is_fully_qualified)) {
10475 				zend_string_release_ex(resolved_name, 0);
10476 				return;
10477 			}
10478 
10479 			zend_string_release_ex(resolved_name, 0);
10480 			break;
10481 		}
10482 		case ZEND_AST_CLASS_CONST:
10483 		{
10484 			zend_ast *class_ast;
10485 			zend_ast *name_ast;
10486 			zend_string *resolved_name;
10487 
10488 			zend_eval_const_expr(&ast->child[0]);
10489 			zend_eval_const_expr(&ast->child[1]);
10490 
10491 			class_ast = ast->child[0];
10492 			name_ast = ast->child[1];
10493 
10494 			if (class_ast->kind != ZEND_AST_ZVAL || name_ast->kind != ZEND_AST_ZVAL) {
10495 				return;
10496 			}
10497 
10498 			resolved_name = zend_resolve_class_name_ast(class_ast);
10499 			if (!zend_try_ct_eval_class_const(&result, resolved_name, zend_ast_get_str(name_ast))) {
10500 				zend_string_release_ex(resolved_name, 0);
10501 				return;
10502 			}
10503 
10504 			zend_string_release_ex(resolved_name, 0);
10505 			break;
10506 		}
10507 		case ZEND_AST_CLASS_NAME:
10508 		{
10509 			zend_ast *class_ast = ast->child[0];
10510 			if (!zend_try_compile_const_expr_resolve_class_name(&result, class_ast)) {
10511 				return;
10512 			}
10513 			break;
10514 		}
10515 		// TODO: We should probably use zend_ast_apply to recursively walk nodes without
10516 		// special handling. It is required that all nodes that are part of a const expr
10517 		// are visited. Probably we should be distinguishing evaluation of const expr and
10518 		// normal exprs here.
10519 		case ZEND_AST_ARG_LIST:
10520 		{
10521 			zend_ast_list *list = zend_ast_get_list(ast);
10522 			for (uint32_t i = 0; i < list->children; i++) {
10523 				zend_eval_const_expr(&list->child[i]);
10524 			}
10525 			return;
10526 		}
10527 		case ZEND_AST_NEW:
10528 			zend_eval_const_expr(&ast->child[0]);
10529 			zend_eval_const_expr(&ast->child[1]);
10530 			return;
10531 		case ZEND_AST_NAMED_ARG:
10532 			zend_eval_const_expr(&ast->child[1]);
10533 			return;
10534 		default:
10535 			return;
10536 	}
10537 
10538 	zend_ast_destroy(ast);
10539 	*ast_ptr = zend_ast_create_zval(&result);
10540 }
10541 /* }}} */
10542