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