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