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