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