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