xref: /php-src/Zend/zend_ast.c (revision d5ad7510)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) Zend Technologies Ltd. (http://www.zend.com)           |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 2.00 of the Zend license,     |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.zend.com/license/2_00.txt.                                |
11    | If you did not receive a copy of the Zend license and are unable to  |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@zend.com so we can mail you a copy immediately.              |
14    +----------------------------------------------------------------------+
15    | Authors: Bob Weinand <bwoebi@php.net>                                |
16    |          Dmitry Stogov <dmitry@php.net>                              |
17    +----------------------------------------------------------------------+
18 */
19 
20 #include "zend_ast.h"
21 #include "zend_API.h"
22 #include "zend_operators.h"
23 #include "zend_language_parser.h"
24 #include "zend_smart_str.h"
25 #include "zend_exceptions.h"
26 #include "zend_constants.h"
27 #include "zend_enum.h"
28 
29 ZEND_API zend_ast_process_t zend_ast_process = NULL;
30 
zend_ast_alloc(size_t size)31 static inline void *zend_ast_alloc(size_t size) {
32 	return zend_arena_alloc(&CG(ast_arena), size);
33 }
34 
zend_ast_realloc(void * old,size_t old_size,size_t new_size)35 static inline void *zend_ast_realloc(void *old, size_t old_size, size_t new_size) {
36 	void *new = zend_ast_alloc(new_size);
37 	memcpy(new, old, old_size);
38 	return new;
39 }
40 
zend_ast_list_size(uint32_t children)41 static inline size_t zend_ast_list_size(uint32_t children) {
42 	return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
43 }
44 
zend_ast_create_znode(znode * node)45 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(znode *node) {
46 	zend_ast_znode *ast;
47 
48 	ast = zend_ast_alloc(sizeof(zend_ast_znode));
49 	ast->kind = ZEND_AST_ZNODE;
50 	ast->attr = 0;
51 	ast->lineno = CG(zend_lineno);
52 	ast->node = *node;
53 	return (zend_ast *) ast;
54 }
55 
zend_ast_create_zval_int(zval * zv,uint32_t attr,uint32_t lineno)56 static zend_always_inline zend_ast * zend_ast_create_zval_int(zval *zv, uint32_t attr, uint32_t lineno) {
57 	zend_ast_zval *ast;
58 
59 	ast = zend_ast_alloc(sizeof(zend_ast_zval));
60 	ast->kind = ZEND_AST_ZVAL;
61 	ast->attr = attr;
62 	ZVAL_COPY_VALUE(&ast->val, zv);
63 	Z_LINENO(ast->val) = lineno;
64 	return (zend_ast *) ast;
65 }
66 
zend_ast_create_zval_with_lineno(zval * zv,uint32_t lineno)67 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_with_lineno(zval *zv, uint32_t lineno) {
68 	return zend_ast_create_zval_int(zv, 0, lineno);
69 }
70 
zend_ast_create_zval_ex(zval * zv,zend_ast_attr attr)71 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) {
72 	return zend_ast_create_zval_int(zv, attr, CG(zend_lineno));
73 }
74 
zend_ast_create_zval(zval * zv)75 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval(zval *zv) {
76 	return zend_ast_create_zval_int(zv, 0, CG(zend_lineno));
77 }
78 
zend_ast_create_zval_from_str(zend_string * str)79 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_str(zend_string *str) {
80 	zval zv;
81 	ZVAL_STR(&zv, str);
82 	return zend_ast_create_zval_int(&zv, 0, CG(zend_lineno));
83 }
84 
zend_ast_create_zval_from_long(zend_long lval)85 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_long(zend_long lval) {
86 	zval zv;
87 	ZVAL_LONG(&zv, lval);
88 	return zend_ast_create_zval_int(&zv, 0, CG(zend_lineno));
89 }
90 
zend_ast_create_constant(zend_string * name,zend_ast_attr attr)91 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_constant(zend_string *name, zend_ast_attr attr) {
92 	zend_ast_zval *ast;
93 
94 	ast = zend_ast_alloc(sizeof(zend_ast_zval));
95 	ast->kind = ZEND_AST_CONSTANT;
96 	ast->attr = attr;
97 	ZVAL_STR(&ast->val, name);
98 	Z_LINENO(ast->val) = CG(zend_lineno);
99 	return (zend_ast *) ast;
100 }
101 
zend_ast_create_class_const_or_name(zend_ast * class_name,zend_ast * name)102 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_class_const_or_name(zend_ast *class_name, zend_ast *name) {
103 	zend_string *name_str = zend_ast_get_str(name);
104 	if (zend_string_equals_ci(name_str, ZSTR_KNOWN(ZEND_STR_CLASS))) {
105 		zend_string_release(name_str);
106 		return zend_ast_create(ZEND_AST_CLASS_NAME, class_name);
107 	} else {
108 		return zend_ast_create(ZEND_AST_CLASS_CONST, class_name, name);
109 	}
110 }
111 
zend_ast_create_decl(zend_ast_kind kind,uint32_t flags,uint32_t start_lineno,zend_string * doc_comment,zend_string * name,zend_ast * child0,zend_ast * child1,zend_ast * child2,zend_ast * child3,zend_ast * child4)112 ZEND_API zend_ast *zend_ast_create_decl(
113 	zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment,
114 	zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4
115 ) {
116 	zend_ast_decl *ast;
117 
118 	ast = zend_ast_alloc(sizeof(zend_ast_decl));
119 	ast->kind = kind;
120 	ast->attr = 0;
121 	ast->start_lineno = start_lineno;
122 	ast->end_lineno = CG(zend_lineno);
123 	ast->flags = flags;
124 	ast->doc_comment = doc_comment;
125 	ast->name = name;
126 	ast->child[0] = child0;
127 	ast->child[1] = child1;
128 	ast->child[2] = child2;
129 	ast->child[3] = child3;
130 	ast->child[4] = child4;
131 
132 	return (zend_ast *) ast;
133 }
134 
135 #if ZEND_AST_SPEC
zend_ast_create_0(zend_ast_kind kind)136 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_0(zend_ast_kind kind) {
137 	zend_ast *ast;
138 
139 	ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 0);
140 	ast = zend_ast_alloc(zend_ast_size(0));
141 	ast->kind = kind;
142 	ast->attr = 0;
143 	ast->lineno = CG(zend_lineno);
144 
145 	return ast;
146 }
147 
zend_ast_create_1(zend_ast_kind kind,zend_ast * child)148 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_1(zend_ast_kind kind, zend_ast *child) {
149 	zend_ast *ast;
150 	uint32_t lineno;
151 
152 	ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 1);
153 	ast = zend_ast_alloc(zend_ast_size(1));
154 	ast->kind = kind;
155 	ast->attr = 0;
156 	ast->child[0] = child;
157 	if (child) {
158 		lineno = zend_ast_get_lineno(child);
159 	} else {
160 		lineno = CG(zend_lineno);
161 	}
162 	ast->lineno = lineno;
163 
164 	return ast;
165 }
166 
zend_ast_create_2(zend_ast_kind kind,zend_ast * child1,zend_ast * child2)167 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
168 	zend_ast *ast;
169 	uint32_t lineno;
170 
171 	ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 2);
172 	ast = zend_ast_alloc(zend_ast_size(2));
173 	ast->kind = kind;
174 	ast->attr = 0;
175 	ast->child[0] = child1;
176 	ast->child[1] = child2;
177 	if (child1) {
178 		lineno = zend_ast_get_lineno(child1);
179 	} else if (child2) {
180 		lineno = zend_ast_get_lineno(child2);
181 	} else {
182 		lineno = CG(zend_lineno);
183 	}
184 	ast->lineno = lineno;
185 
186 	return ast;
187 }
188 
zend_ast_create_3(zend_ast_kind kind,zend_ast * child1,zend_ast * child2,zend_ast * child3)189 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_3(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3) {
190 	zend_ast *ast;
191 	uint32_t lineno;
192 
193 	ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 3);
194 	ast = zend_ast_alloc(zend_ast_size(3));
195 	ast->kind = kind;
196 	ast->attr = 0;
197 	ast->child[0] = child1;
198 	ast->child[1] = child2;
199 	ast->child[2] = child3;
200 	if (child1) {
201 		lineno = zend_ast_get_lineno(child1);
202 	} else if (child2) {
203 		lineno = zend_ast_get_lineno(child2);
204 	} else if (child3) {
205 		lineno = zend_ast_get_lineno(child3);
206 	} else {
207 		lineno = CG(zend_lineno);
208 	}
209 	ast->lineno = lineno;
210 
211 	return ast;
212 }
213 
zend_ast_create_4(zend_ast_kind kind,zend_ast * child1,zend_ast * child2,zend_ast * child3,zend_ast * child4)214 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_4(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4) {
215 	zend_ast *ast;
216 	uint32_t lineno;
217 
218 	ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 4);
219 	ast = zend_ast_alloc(zend_ast_size(4));
220 	ast->kind = kind;
221 	ast->attr = 0;
222 	ast->child[0] = child1;
223 	ast->child[1] = child2;
224 	ast->child[2] = child3;
225 	ast->child[3] = child4;
226 	if (child1) {
227 		lineno = zend_ast_get_lineno(child1);
228 	} else if (child2) {
229 		lineno = zend_ast_get_lineno(child2);
230 	} else if (child3) {
231 		lineno = zend_ast_get_lineno(child3);
232 	} else if (child4) {
233 		lineno = zend_ast_get_lineno(child4);
234 	} else {
235 		lineno = CG(zend_lineno);
236 	}
237 	ast->lineno = lineno;
238 
239 	return ast;
240 }
241 
zend_ast_create_5(zend_ast_kind kind,zend_ast * child1,zend_ast * child2,zend_ast * child3,zend_ast * child4,zend_ast * child5)242 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_5(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4, zend_ast *child5) {
243 	zend_ast *ast;
244 	uint32_t lineno;
245 
246 	ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 5);
247 	ast = zend_ast_alloc(zend_ast_size(5));
248 	ast->kind = kind;
249 	ast->attr = 0;
250 	ast->child[0] = child1;
251 	ast->child[1] = child2;
252 	ast->child[2] = child3;
253 	ast->child[3] = child4;
254 	ast->child[4] = child5;
255 	if (child1) {
256 		lineno = zend_ast_get_lineno(child1);
257 	} else if (child2) {
258 		lineno = zend_ast_get_lineno(child2);
259 	} else if (child3) {
260 		lineno = zend_ast_get_lineno(child3);
261 	} else if (child4) {
262 		lineno = zend_ast_get_lineno(child4);
263 	} else if (child5) {
264 		lineno = zend_ast_get_lineno(child5);
265 	} else {
266 		lineno = CG(zend_lineno);
267 	}
268 	ast->lineno = lineno;
269 
270 	return ast;
271 }
272 
zend_ast_create_list_0(zend_ast_kind kind)273 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_0(zend_ast_kind kind) {
274 	zend_ast *ast;
275 	zend_ast_list *list;
276 
277 	ast = zend_ast_alloc(zend_ast_list_size(4));
278 	list = (zend_ast_list *) ast;
279 	list->kind = kind;
280 	list->attr = 0;
281 	list->lineno = CG(zend_lineno);
282 	list->children = 0;
283 
284 	return ast;
285 }
286 
zend_ast_create_list_1(zend_ast_kind kind,zend_ast * child)287 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_1(zend_ast_kind kind, zend_ast *child) {
288 	zend_ast *ast;
289 	zend_ast_list *list;
290 	uint32_t lineno;
291 
292 	ast = zend_ast_alloc(zend_ast_list_size(4));
293 	list = (zend_ast_list *) ast;
294 	list->kind = kind;
295 	list->attr = 0;
296 	list->children = 1;
297 	list->child[0] = child;
298 	if (child) {
299 		lineno = zend_ast_get_lineno(child);
300 		if (lineno > CG(zend_lineno)) {
301 			lineno = CG(zend_lineno);
302 		}
303 	} else {
304 		lineno = CG(zend_lineno);
305 	}
306 	list->lineno = lineno;
307 
308 	return ast;
309 }
310 
zend_ast_create_list_2(zend_ast_kind kind,zend_ast * child1,zend_ast * child2)311 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
312 	zend_ast *ast;
313 	zend_ast_list *list;
314 	uint32_t lineno;
315 
316 	ast = zend_ast_alloc(zend_ast_list_size(4));
317 	list = (zend_ast_list *) ast;
318 	list->kind = kind;
319 	list->attr = 0;
320 	list->children = 2;
321 	list->child[0] = child1;
322 	list->child[1] = child2;
323 	if (child1) {
324 		lineno = zend_ast_get_lineno(child1);
325 		if (lineno > CG(zend_lineno)) {
326 			lineno = CG(zend_lineno);
327 		}
328 	} else if (child2) {
329 		lineno = zend_ast_get_lineno(child2);
330 		if (lineno > CG(zend_lineno)) {
331 			lineno = CG(zend_lineno);
332 		}
333 	} else {
334 		list->children = 0;
335 		lineno = CG(zend_lineno);
336 	}
337 	list->lineno = lineno;
338 
339 	return ast;
340 }
341 #else
zend_ast_create_from_va_list(zend_ast_kind kind,zend_ast_attr attr,va_list va)342 static zend_ast *zend_ast_create_from_va_list(zend_ast_kind kind, zend_ast_attr attr, va_list va) {
343 	uint32_t i, children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
344 	zend_ast *ast;
345 
346 	ast = zend_ast_alloc(zend_ast_size(children));
347 	ast->kind = kind;
348 	ast->attr = attr;
349 	ast->lineno = (uint32_t) -1;
350 
351 	for (i = 0; i < children; ++i) {
352 		ast->child[i] = va_arg(va, zend_ast *);
353 		if (ast->child[i] != NULL) {
354 			uint32_t lineno = zend_ast_get_lineno(ast->child[i]);
355 			if (lineno < ast->lineno) {
356 				ast->lineno = lineno;
357 			}
358 		}
359 	}
360 
361 	if (ast->lineno == UINT_MAX) {
362 		ast->lineno = CG(zend_lineno);
363 	}
364 
365 	return ast;
366 }
367 
zend_ast_create_ex(zend_ast_kind kind,zend_ast_attr attr,...)368 ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...) {
369 	va_list va;
370 	zend_ast *ast;
371 
372 	va_start(va, attr);
373 	ast = zend_ast_create_from_va_list(kind, attr, va);
374 	va_end(va);
375 
376 	return ast;
377 }
378 
zend_ast_create(zend_ast_kind kind,...)379 ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...) {
380 	va_list va;
381 	zend_ast *ast;
382 
383 	va_start(va, kind);
384 	ast = zend_ast_create_from_va_list(kind, 0, va);
385 	va_end(va);
386 
387 	return ast;
388 }
389 
zend_ast_create_list(uint32_t init_children,zend_ast_kind kind,...)390 ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...) {
391 	zend_ast *ast;
392 	zend_ast_list *list;
393 
394 	ast = zend_ast_alloc(zend_ast_list_size(4));
395 	list = (zend_ast_list *) ast;
396 	list->kind = kind;
397 	list->attr = 0;
398 	list->lineno = CG(zend_lineno);
399 	list->children = 0;
400 
401 	{
402 		va_list va;
403 		uint32_t i;
404 		va_start(va, kind);
405 		for (i = 0; i < init_children; ++i) {
406 			zend_ast *child = va_arg(va, zend_ast *);
407 			ast = zend_ast_list_add(ast, child);
408 			if (child != NULL) {
409 				uint32_t lineno = zend_ast_get_lineno(child);
410 				if (lineno < ast->lineno) {
411 					ast->lineno = lineno;
412 				}
413 			}
414 		}
415 		va_end(va);
416 	}
417 
418 	return ast;
419 }
420 #endif
421 
zend_ast_create_concat_op(zend_ast * op0,zend_ast * op1)422 zend_ast *zend_ast_create_concat_op(zend_ast *op0, zend_ast *op1) {
423 	if (op0->kind == ZEND_AST_ZVAL && op1->kind == ZEND_AST_ZVAL) {
424 		zval *zv0 = zend_ast_get_zval(op0);
425 		zval *zv1 = zend_ast_get_zval(op1);
426 		if (!zend_binary_op_produces_error(ZEND_CONCAT, zv0, zv1) &&
427 				concat_function(zv0, zv0, zv1) == SUCCESS) {
428 			zval_ptr_dtor_nogc(zv1);
429 			return zend_ast_create_zval(zv0);
430 		}
431 	}
432 	return zend_ast_create_binary_op(ZEND_CONCAT, op0, op1);
433 }
434 
is_power_of_two(uint32_t n)435 static inline bool is_power_of_two(uint32_t n) {
436 	return ((n != 0) && (n == (n & (~n + 1))));
437 }
438 
zend_ast_list_add(zend_ast * ast,zend_ast * op)439 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *ast, zend_ast *op) {
440 	zend_ast_list *list = zend_ast_get_list(ast);
441 	if (list->children >= 4 && is_power_of_two(list->children)) {
442 			list = zend_ast_realloc(list,
443 			zend_ast_list_size(list->children), zend_ast_list_size(list->children * 2));
444 	}
445 	list->child[list->children++] = op;
446 	return (zend_ast *) list;
447 }
448 
zend_ast_add_array_element(zval * result,zval * offset,zval * expr)449 static zend_result zend_ast_add_array_element(zval *result, zval *offset, zval *expr)
450 {
451 	if (Z_TYPE_P(offset) == IS_UNDEF) {
452 		if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), expr)) {
453 			zend_throw_error(NULL,
454 				"Cannot add element to the array as the next element is already occupied");
455 			return FAILURE;
456 		}
457 		return SUCCESS;
458 	}
459 
460 	if (array_set_zval_key(Z_ARRVAL_P(result), offset, expr) == FAILURE) {
461 		return FAILURE;
462 	}
463 
464 	zval_ptr_dtor_nogc(offset);
465 	zval_ptr_dtor_nogc(expr);
466 	return SUCCESS;
467 }
468 
zend_ast_add_unpacked_element(zval * result,zval * expr)469 static zend_result zend_ast_add_unpacked_element(zval *result, zval *expr) {
470 	if (EXPECTED(Z_TYPE_P(expr) == IS_ARRAY)) {
471 		HashTable *ht = Z_ARRVAL_P(expr);
472 		zval *val;
473 		zend_string *key;
474 
475 		ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
476 			if (key) {
477 				zend_hash_update(Z_ARRVAL_P(result), key, val);
478 			} else {
479 				if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), val)) {
480 					zend_throw_error(NULL,
481 						"Cannot add element to the array as the next element is already occupied");
482 					return FAILURE;
483 				}
484 			}
485 			Z_TRY_ADDREF_P(val);
486 		} ZEND_HASH_FOREACH_END();
487 		return SUCCESS;
488 	}
489 
490 	zend_throw_error(NULL, "Only arrays can be unpacked in constant expression");
491 	return FAILURE;
492 }
493 
zend_ast_fetch_class(zend_ast * ast,zend_class_entry * scope)494 zend_class_entry *zend_ast_fetch_class(zend_ast *ast, zend_class_entry *scope)
495 {
496 	return zend_fetch_class_with_scope(zend_ast_get_str(ast), (ast->attr >> ZEND_CONST_EXPR_NEW_FETCH_TYPE_SHIFT) | ZEND_FETCH_CLASS_EXCEPTION, scope);
497 }
498 
499 ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
500 	zval *result,
501 	zend_ast *ast,
502 	zend_class_entry *scope,
503 	bool *short_circuited_ptr,
504 	zend_ast_evaluate_ctx *ctx
505 );
506 
zend_ast_evaluate_ex(zval * result,zend_ast * ast,zend_class_entry * scope,bool * short_circuited_ptr,zend_ast_evaluate_ctx * ctx)507 ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_ex(
508 	zval *result,
509 	zend_ast *ast,
510 	zend_class_entry *scope,
511 	bool *short_circuited_ptr,
512 	zend_ast_evaluate_ctx *ctx
513 ) {
514 	zend_string *previous_filename;
515 	zend_long previous_lineno;
516 	if (scope) {
517 		previous_filename = EG(filename_override);
518 		previous_lineno = EG(lineno_override);
519 		EG(filename_override) = scope->info.user.filename;
520 		EG(lineno_override) = zend_ast_get_lineno(ast);
521 	}
522 	zend_result r = zend_ast_evaluate_inner(result, ast, scope, short_circuited_ptr, ctx);
523 	if (scope) {
524 		EG(filename_override) = previous_filename;
525 		EG(lineno_override) = previous_lineno;
526 	}
527 	return r;
528 }
529 
zend_ast_evaluate_inner(zval * result,zend_ast * ast,zend_class_entry * scope,bool * short_circuited_ptr,zend_ast_evaluate_ctx * ctx)530 ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
531 	zval *result,
532 	zend_ast *ast,
533 	zend_class_entry *scope,
534 	bool *short_circuited_ptr,
535 	zend_ast_evaluate_ctx *ctx
536 ) {
537 	zval op1, op2;
538 	zend_result ret = SUCCESS;
539 	bool short_circuited;
540 	*short_circuited_ptr = false;
541 
542 	switch (ast->kind) {
543 		case ZEND_AST_BINARY_OP:
544 			if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
545 				ret = FAILURE;
546 			} else if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
547 				zval_ptr_dtor_nogc(&op1);
548 				ret = FAILURE;
549 			} else {
550 				binary_op_type op = get_binary_op(ast->attr);
551 				ret = op(result, &op1, &op2);
552 				zval_ptr_dtor_nogc(&op1);
553 				zval_ptr_dtor_nogc(&op2);
554 			}
555 			break;
556 		case ZEND_AST_GREATER:
557 		case ZEND_AST_GREATER_EQUAL:
558 			if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
559 				ret = FAILURE;
560 			} else if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
561 				zval_ptr_dtor_nogc(&op1);
562 				ret = FAILURE;
563 			} else {
564 				/* op1 > op2 is the same as op2 < op1 */
565 				binary_op_type op = ast->kind == ZEND_AST_GREATER
566 					? is_smaller_function : is_smaller_or_equal_function;
567 				ret = op(result, &op2, &op1);
568 				zval_ptr_dtor_nogc(&op1);
569 				zval_ptr_dtor_nogc(&op2);
570 			}
571 			break;
572 		case ZEND_AST_UNARY_OP:
573 			if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
574 				ret = FAILURE;
575 			} else {
576 				unary_op_type op = get_unary_op(ast->attr);
577 				ret = op(result, &op1);
578 				zval_ptr_dtor_nogc(&op1);
579 			}
580 			break;
581 		case ZEND_AST_ZVAL:
582 		{
583 			zval *zv = zend_ast_get_zval(ast);
584 
585 			ZVAL_COPY(result, zv);
586 			break;
587 		}
588 		case ZEND_AST_CONSTANT:
589 		{
590 			zend_string *name = zend_ast_get_constant_name(ast);
591 			zval *zv = zend_get_constant_ex(name, scope, ast->attr);
592 
593 			if (UNEXPECTED(zv == NULL)) {
594 				ZVAL_UNDEF(result);
595 				return FAILURE;
596 			}
597 			ZVAL_COPY_OR_DUP(result, zv);
598 			break;
599 		}
600 		case ZEND_AST_CONSTANT_CLASS:
601 			if (scope) {
602 				ZVAL_STR_COPY(result, scope->name);
603 			} else {
604 				ZVAL_EMPTY_STRING(result);
605 			}
606 			break;
607 		case ZEND_AST_CLASS_NAME:
608 			if (!scope) {
609 				zend_throw_error(NULL, "Cannot use \"self\" when no class scope is active");
610 				return FAILURE;
611 			}
612 			if (ast->attr == ZEND_FETCH_CLASS_SELF) {
613 				ZVAL_STR_COPY(result, scope->name);
614 			} else if (ast->attr == ZEND_FETCH_CLASS_PARENT) {
615 				if (!scope->parent) {
616 					zend_throw_error(NULL,
617 						"Cannot use \"parent\" when current class scope has no parent");
618 					return FAILURE;
619 				}
620 				ZVAL_STR_COPY(result, scope->parent->name);
621 			} else {
622 				ZEND_ASSERT(0 && "Should have errored during compilation");
623 			}
624 			break;
625 		case ZEND_AST_AND:
626 			if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
627 				ret = FAILURE;
628 				break;
629 			}
630 			if (zend_is_true(&op1)) {
631 				if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
632 					zval_ptr_dtor_nogc(&op1);
633 					ret = FAILURE;
634 					break;
635 				}
636 				ZVAL_BOOL(result, zend_is_true(&op2));
637 				zval_ptr_dtor_nogc(&op2);
638 			} else {
639 				ZVAL_FALSE(result);
640 			}
641 			zval_ptr_dtor_nogc(&op1);
642 			break;
643 		case ZEND_AST_OR:
644 			if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
645 				ret = FAILURE;
646 				break;
647 			}
648 			if (zend_is_true(&op1)) {
649 				ZVAL_TRUE(result);
650 			} else {
651 				if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
652 					zval_ptr_dtor_nogc(&op1);
653 					ret = FAILURE;
654 					break;
655 				}
656 				ZVAL_BOOL(result, zend_is_true(&op2));
657 				zval_ptr_dtor_nogc(&op2);
658 			}
659 			zval_ptr_dtor_nogc(&op1);
660 			break;
661 		case ZEND_AST_CONDITIONAL:
662 			if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
663 				ret = FAILURE;
664 				break;
665 			}
666 			if (zend_is_true(&op1)) {
667 				if (!ast->child[1]) {
668 					*result = op1;
669 				} else {
670 					if (UNEXPECTED(zend_ast_evaluate_ex(result, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
671 						zval_ptr_dtor_nogc(&op1);
672 						ret = FAILURE;
673 						break;
674 					}
675 					zval_ptr_dtor_nogc(&op1);
676 				}
677 			} else {
678 				if (UNEXPECTED(zend_ast_evaluate_ex(result, ast->child[2], scope, &short_circuited, ctx) != SUCCESS)) {
679 					zval_ptr_dtor_nogc(&op1);
680 					ret = FAILURE;
681 					break;
682 				}
683 				zval_ptr_dtor_nogc(&op1);
684 			}
685 			break;
686 		case ZEND_AST_COALESCE:
687 			if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
688 				ret = FAILURE;
689 				break;
690 			}
691 			if (Z_TYPE(op1) > IS_NULL) {
692 				*result = op1;
693 			} else {
694 				if (UNEXPECTED(zend_ast_evaluate_ex(result, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
695 					zval_ptr_dtor_nogc(&op1);
696 					ret = FAILURE;
697 					break;
698 				}
699 				zval_ptr_dtor_nogc(&op1);
700 			}
701 			break;
702 		case ZEND_AST_UNARY_PLUS:
703 			if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
704 				ret = FAILURE;
705 			} else {
706 				ZVAL_LONG(&op1, 0);
707 				ret = add_function(result, &op1, &op2);
708 				zval_ptr_dtor_nogc(&op2);
709 			}
710 			break;
711 		case ZEND_AST_UNARY_MINUS:
712 			if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
713 				ret = FAILURE;
714 			} else {
715 				ZVAL_LONG(&op1, -1);
716 				ret = mul_function(result, &op1, &op2);
717 				zval_ptr_dtor_nogc(&op2);
718 			}
719 			break;
720 		case ZEND_AST_ARRAY:
721 			{
722 				uint32_t i;
723 				zend_ast_list *list = zend_ast_get_list(ast);
724 
725 				if (!list->children) {
726 					ZVAL_EMPTY_ARRAY(result);
727 					break;
728 				}
729 				array_init(result);
730 				for (i = 0; i < list->children; i++) {
731 					zend_ast *elem = list->child[i];
732 					if (elem->kind == ZEND_AST_UNPACK) {
733 						if (UNEXPECTED(zend_ast_evaluate_ex(&op1, elem->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
734 							zval_ptr_dtor_nogc(result);
735 							return FAILURE;
736 						}
737 						if (UNEXPECTED(zend_ast_add_unpacked_element(result, &op1) != SUCCESS)) {
738 							zval_ptr_dtor_nogc(&op1);
739 							zval_ptr_dtor_nogc(result);
740 							return FAILURE;
741 						}
742 						zval_ptr_dtor_nogc(&op1);
743 						continue;
744 					}
745 					if (elem->child[1]) {
746 						if (UNEXPECTED(zend_ast_evaluate_ex(&op1, elem->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
747 							zval_ptr_dtor_nogc(result);
748 							return FAILURE;
749 						}
750 					} else {
751 						ZVAL_UNDEF(&op1);
752 					}
753 					if (UNEXPECTED(zend_ast_evaluate_ex(&op2, elem->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
754 						zval_ptr_dtor_nogc(&op1);
755 						zval_ptr_dtor_nogc(result);
756 						return FAILURE;
757 					}
758 					if (UNEXPECTED(zend_ast_add_array_element(result, &op1, &op2) != SUCCESS)) {
759 						zval_ptr_dtor_nogc(&op1);
760 						zval_ptr_dtor_nogc(&op2);
761 						zval_ptr_dtor_nogc(result);
762 						return FAILURE;
763 					}
764 				}
765 			}
766 			break;
767 		case ZEND_AST_DIM:
768 			if (ast->child[1] == NULL) {
769 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
770 			}
771 
772 			if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
773 				ret = FAILURE;
774 				break;
775 			}
776 			if (short_circuited) {
777 				*short_circuited_ptr = true;
778 				ZVAL_NULL(result);
779 				return SUCCESS;
780 			}
781 
782 			// DIM on objects is disallowed because it allows executing arbitrary expressions
783 			if (Z_TYPE(op1) == IS_OBJECT) {
784 				zval_ptr_dtor_nogc(&op1);
785 				zend_throw_error(NULL, "Cannot use [] on objects in constant expression");
786 				ret = FAILURE;
787 				break;
788 			}
789 
790 			if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
791 				zval_ptr_dtor_nogc(&op1);
792 				ret = FAILURE;
793 				break;
794 			}
795 
796 			zend_fetch_dimension_const(result, &op1, &op2, (ast->attr & ZEND_DIM_IS) ? BP_VAR_IS : BP_VAR_R);
797 
798 			zval_ptr_dtor_nogc(&op1);
799 			zval_ptr_dtor_nogc(&op2);
800 			if (UNEXPECTED(EG(exception))) {
801 				return FAILURE;
802 			}
803 
804 			break;
805 		case ZEND_AST_CONST_ENUM_INIT:
806 		{
807 			// Preloading will attempt to resolve constants but objects can't be stored in shm
808 			// Aborting here to store the const AST instead
809 			if (CG(in_compilation)) {
810 				return FAILURE;
811 			}
812 
813 			zend_ast *class_name_ast = ast->child[0];
814 			zend_string *class_name = zend_ast_get_str(class_name_ast);
815 
816 			zend_ast *case_name_ast = ast->child[1];
817 			zend_string *case_name = zend_ast_get_str(case_name_ast);
818 
819 			zend_ast *case_value_ast = ast->child[2];
820 
821 			zval case_value_zv;
822 			ZVAL_UNDEF(&case_value_zv);
823 			if (case_value_ast != NULL) {
824 				if (UNEXPECTED(zend_ast_evaluate_ex(&case_value_zv, case_value_ast, scope, &short_circuited, ctx) != SUCCESS)) {
825 					return FAILURE;
826 				}
827 			}
828 
829 			zend_class_entry *ce = zend_lookup_class(class_name);
830 			zend_enum_new(result, ce, case_name, case_value_ast != NULL ? &case_value_zv : NULL);
831 			zval_ptr_dtor_nogc(&case_value_zv);
832 			break;
833 		}
834 		case ZEND_AST_CLASS_CONST:
835 		{
836 			zend_string *class_name = zend_ast_get_str(ast->child[0]);
837 			if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
838 				return FAILURE;
839 			}
840 			if (UNEXPECTED(Z_TYPE(op2) != IS_STRING)) {
841 				zend_invalid_class_constant_type_error(Z_TYPE(op2));
842 				zval_ptr_dtor_nogc(&op2);
843 				return FAILURE;
844 			}
845 			zend_string *const_name = Z_STR(op2);
846 
847 			zend_string *previous_filename;
848 			zend_long previous_lineno;
849 			if (scope) {
850 				previous_filename = EG(filename_override);
851 				previous_lineno = EG(lineno_override);
852 				EG(filename_override) = scope->info.user.filename;
853 				EG(lineno_override) = zend_ast_get_lineno(ast);
854 			}
855 			zval *zv = zend_get_class_constant_ex(class_name, const_name, scope, ast->attr);
856 			if (scope) {
857 				EG(filename_override) = previous_filename;
858 				EG(lineno_override) = previous_lineno;
859 			}
860 
861 			if (UNEXPECTED(zv == NULL)) {
862 				ZVAL_UNDEF(result);
863 				zval_ptr_dtor_nogc(&op2);
864 				return FAILURE;
865 			}
866 			ZVAL_COPY_OR_DUP(result, zv);
867 			zval_ptr_dtor_nogc(&op2);
868 			break;
869 		}
870 		case ZEND_AST_NEW:
871 		{
872 			zend_class_entry *ce = zend_ast_fetch_class(ast->child[0], scope);
873 			if (!ce) {
874 				return FAILURE;
875 			}
876 
877 			if (object_init_ex(result, ce) != SUCCESS) {
878 				return FAILURE;
879 			}
880 
881 			/* Even if there is no constructor, the object can have cause side-effects in various ways (__toString(), __get(), __isset(), etc). */
882 			ctx->had_side_effects = true;
883 
884 			zend_ast_list *args_ast = zend_ast_get_list(ast->child[1]);
885 			if (args_ast->attr) {
886 				/* Has named arguments. */
887 				HashTable *args = zend_new_array(args_ast->children);
888 				for (uint32_t i = 0; i < args_ast->children; i++) {
889 					zend_ast *arg_ast = args_ast->child[i];
890 					zend_string *name = NULL;
891 					zval arg;
892 					if (arg_ast->kind == ZEND_AST_NAMED_ARG) {
893 						name = zend_ast_get_str(arg_ast->child[0]);
894 						arg_ast = arg_ast->child[1];
895 					}
896 					if (zend_ast_evaluate_ex(&arg, arg_ast, scope, &short_circuited, ctx) == FAILURE) {
897 						zend_array_destroy(args);
898 						zval_ptr_dtor(result);
899 						return FAILURE;
900 					}
901 					if (name) {
902 						if (!zend_hash_add(args, name, &arg)) {
903 							zend_throw_error(NULL,
904 								"Named parameter $%s overwrites previous argument",
905 								ZSTR_VAL(name));
906 							zend_array_destroy(args);
907 							zval_ptr_dtor(result);
908 							return FAILURE;
909 						}
910 					} else {
911 						zend_hash_next_index_insert(args, &arg);
912 					}
913 				}
914 
915 				zend_function *ctor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
916 				if (ctor) {
917 					zend_call_known_function(
918 						ctor, Z_OBJ_P(result), Z_OBJCE_P(result), NULL, 0, NULL, args);
919 				}
920 
921 				zend_array_destroy(args);
922 			} else {
923 				ALLOCA_FLAG(use_heap)
924 				zval *args = do_alloca(sizeof(zval) * args_ast->children, use_heap);
925 				for (uint32_t i = 0; i < args_ast->children; i++) {
926 					if (zend_ast_evaluate_ex(&args[i], args_ast->child[i], scope, &short_circuited, ctx) == FAILURE) {
927 						for (uint32_t j = 0; j < i; j++) {
928 							zval_ptr_dtor(&args[j]);
929 						}
930 						free_alloca(args, use_heap);
931 						zval_ptr_dtor(result);
932 						return FAILURE;
933 					}
934 				}
935 
936 				zend_function *ctor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
937 				if (ctor) {
938 					zend_call_known_instance_method(
939 						ctor, Z_OBJ_P(result), NULL, args_ast->children, args);
940 				}
941 
942 				for (uint32_t i = 0; i < args_ast->children; i++) {
943 					zval_ptr_dtor(&args[i]);
944 				}
945 				free_alloca(args, use_heap);
946 			}
947 
948 			if (EG(exception)) {
949 				zend_object_store_ctor_failed(Z_OBJ_P(result));
950 				zval_ptr_dtor(result);
951 				return FAILURE;
952 			}
953 			return SUCCESS;
954 		}
955 		case ZEND_AST_PROP:
956 		case ZEND_AST_NULLSAFE_PROP:
957 		{
958 			if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
959 				return FAILURE;
960 			}
961 			if (short_circuited) {
962 				*short_circuited_ptr = true;
963 				ZVAL_NULL(result);
964 				return SUCCESS;
965 			}
966 			if (ast->kind == ZEND_AST_NULLSAFE_PROP && Z_TYPE(op1) == IS_NULL) {
967 				*short_circuited_ptr = true;
968 				ZVAL_NULL(result);
969 				return SUCCESS;
970 			}
971 
972 			if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
973 				zval_ptr_dtor_nogc(&op1);
974 				return FAILURE;
975 			}
976 
977 			if (!try_convert_to_string(&op2)) {
978 				zval_ptr_dtor_nogc(&op1);
979 				zval_ptr_dtor_nogc(&op2);
980 				return FAILURE;
981 			}
982 
983 			if (Z_TYPE(op1) != IS_OBJECT) {
984 				zend_wrong_property_read(&op1, &op2);
985 
986 				zval_ptr_dtor_nogc(&op1);
987 				zval_ptr_dtor_nogc(&op2);
988 
989 				ZVAL_NULL(result);
990 				return SUCCESS;
991 			}
992 
993 			zend_object *zobj = Z_OBJ(op1);
994 			if (!(zobj->ce->ce_flags & ZEND_ACC_ENUM)) {
995 				zend_throw_error(NULL, "Fetching properties on non-enums in constant expressions is not allowed");
996 				zval_ptr_dtor_nogc(&op1);
997 				zval_ptr_dtor_nogc(&op2);
998 				return FAILURE;
999 			}
1000 
1001 			zend_string *name = Z_STR(op2);
1002 			zval *property_result = zend_read_property_ex(scope, zobj, name, 0, result);
1003 			if (EG(exception)) {
1004 				zval_ptr_dtor_nogc(&op1);
1005 				zval_ptr_dtor_nogc(&op2);
1006 				return FAILURE;
1007 			}
1008 
1009 			if (result != property_result) {
1010 				ZVAL_COPY(result, property_result);
1011 			}
1012 			zval_ptr_dtor_nogc(&op1);
1013 			zval_ptr_dtor_nogc(&op2);
1014 			return SUCCESS;
1015 		}
1016 		default:
1017 			zend_throw_error(NULL, "Unsupported constant expression");
1018 			ret = FAILURE;
1019 	}
1020 	return ret;
1021 }
1022 
zend_ast_evaluate(zval * result,zend_ast * ast,zend_class_entry * scope)1023 ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope)
1024 {
1025 	zend_ast_evaluate_ctx ctx = {0};
1026 	bool short_circuited;
1027 	return zend_ast_evaluate_ex(result, ast, scope, &short_circuited, &ctx);
1028 }
1029 
zend_ast_tree_size(zend_ast * ast)1030 static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast)
1031 {
1032 	size_t size;
1033 
1034 	if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
1035 		size = sizeof(zend_ast_zval);
1036 	} else if (zend_ast_is_list(ast)) {
1037 		uint32_t i;
1038 		zend_ast_list *list = zend_ast_get_list(ast);
1039 
1040 		size = zend_ast_list_size(list->children);
1041 		for (i = 0; i < list->children; i++) {
1042 			if (list->child[i]) {
1043 				size += zend_ast_tree_size(list->child[i]);
1044 			}
1045 		}
1046 	} else {
1047 		uint32_t i, children = zend_ast_get_num_children(ast);
1048 
1049 		size = zend_ast_size(children);
1050 		for (i = 0; i < children; i++) {
1051 			if (ast->child[i]) {
1052 				size += zend_ast_tree_size(ast->child[i]);
1053 			}
1054 		}
1055 	}
1056 	return size;
1057 }
1058 
zend_ast_tree_copy(zend_ast * ast,void * buf)1059 static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
1060 {
1061 	if (ast->kind == ZEND_AST_ZVAL) {
1062 		zend_ast_zval *new = (zend_ast_zval*)buf;
1063 		new->kind = ZEND_AST_ZVAL;
1064 		new->attr = ast->attr;
1065 		ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
1066 		Z_LINENO(new->val) = zend_ast_get_lineno(ast);
1067 		buf = (void*)((char*)buf + sizeof(zend_ast_zval));
1068 	} else if (ast->kind == ZEND_AST_CONSTANT) {
1069 		zend_ast_zval *new = (zend_ast_zval*)buf;
1070 		new->kind = ZEND_AST_CONSTANT;
1071 		new->attr = ast->attr;
1072 		ZVAL_STR_COPY(&new->val, zend_ast_get_constant_name(ast));
1073 		Z_LINENO(new->val) = zend_ast_get_lineno(ast);
1074 		buf = (void*)((char*)buf + sizeof(zend_ast_zval));
1075 	} else if (zend_ast_is_list(ast)) {
1076 		zend_ast_list *list = zend_ast_get_list(ast);
1077 		zend_ast_list *new = (zend_ast_list*)buf;
1078 		uint32_t i;
1079 		new->kind = list->kind;
1080 		new->attr = list->attr;
1081 		new->children = list->children;
1082 		new->lineno = list->lineno;
1083 		buf = (void*)((char*)buf + zend_ast_list_size(list->children));
1084 		for (i = 0; i < list->children; i++) {
1085 			if (list->child[i]) {
1086 				new->child[i] = (zend_ast*)buf;
1087 				buf = zend_ast_tree_copy(list->child[i], buf);
1088 			} else {
1089 				new->child[i] = NULL;
1090 			}
1091 		}
1092 	} else {
1093 		uint32_t i, children = zend_ast_get_num_children(ast);
1094 		zend_ast *new = (zend_ast*)buf;
1095 		new->kind = ast->kind;
1096 		new->attr = ast->attr;
1097 		new->lineno = ast->lineno;
1098 		buf = (void*)((char*)buf + zend_ast_size(children));
1099 		for (i = 0; i < children; i++) {
1100 			if (ast->child[i]) {
1101 				new->child[i] = (zend_ast*)buf;
1102 				buf = zend_ast_tree_copy(ast->child[i], buf);
1103 			} else {
1104 				new->child[i] = NULL;
1105 			}
1106 		}
1107 	}
1108 	return buf;
1109 }
1110 
zend_ast_copy(zend_ast * ast)1111 ZEND_API zend_ast_ref * ZEND_FASTCALL zend_ast_copy(zend_ast *ast)
1112 {
1113 	size_t tree_size;
1114 	zend_ast_ref *ref;
1115 
1116 	ZEND_ASSERT(ast != NULL);
1117 	tree_size = zend_ast_tree_size(ast) + sizeof(zend_ast_ref);
1118 	ref = emalloc(tree_size);
1119 	zend_ast_tree_copy(ast, GC_AST(ref));
1120 	GC_SET_REFCOUNT(ref, 1);
1121 	GC_TYPE_INFO(ref) = GC_CONSTANT_AST;
1122 	return ref;
1123 }
1124 
zend_ast_destroy(zend_ast * ast)1125 ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast)
1126 {
1127 tail_call:
1128 	if (!ast) {
1129 		return;
1130 	}
1131 
1132 	if (EXPECTED(ast->kind >= ZEND_AST_VAR)) {
1133 		uint32_t i, children = zend_ast_get_num_children(ast);
1134 
1135 		for (i = 1; i < children; i++) {
1136 			zend_ast_destroy(ast->child[i]);
1137 		}
1138 		ast = ast->child[0];
1139 		goto tail_call;
1140 	} else if (EXPECTED(ast->kind == ZEND_AST_ZVAL)) {
1141 		zval_ptr_dtor_nogc(zend_ast_get_zval(ast));
1142 	} else if (EXPECTED(zend_ast_is_list(ast))) {
1143 		zend_ast_list *list = zend_ast_get_list(ast);
1144 		if (list->children) {
1145 			uint32_t i;
1146 
1147 			for (i = 1; i < list->children; i++) {
1148 				zend_ast_destroy(list->child[i]);
1149 			}
1150 			ast = list->child[0];
1151 			goto tail_call;
1152 		}
1153 	} else if (EXPECTED(ast->kind == ZEND_AST_CONSTANT)) {
1154 		zend_string_release_ex(zend_ast_get_constant_name(ast), 0);
1155 	} else if (EXPECTED(ast->kind >= ZEND_AST_FUNC_DECL)) {
1156 		zend_ast_decl *decl = (zend_ast_decl *) ast;
1157 
1158 		if (decl->name) {
1159 		    zend_string_release_ex(decl->name, 0);
1160 		}
1161 		if (decl->doc_comment) {
1162 			zend_string_release_ex(decl->doc_comment, 0);
1163 		}
1164 		zend_ast_destroy(decl->child[0]);
1165 		zend_ast_destroy(decl->child[1]);
1166 		zend_ast_destroy(decl->child[2]);
1167 		zend_ast_destroy(decl->child[3]);
1168 		ast = decl->child[4];
1169 		goto tail_call;
1170 	}
1171 }
1172 
zend_ast_ref_destroy(zend_ast_ref * ast)1173 ZEND_API void ZEND_FASTCALL zend_ast_ref_destroy(zend_ast_ref *ast)
1174 {
1175 	zend_ast_destroy(GC_AST(ast));
1176 	efree(ast);
1177 }
1178 
zend_ast_apply(zend_ast * ast,zend_ast_apply_func fn,void * context)1179 ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn, void *context) {
1180 	if (zend_ast_is_list(ast)) {
1181 		zend_ast_list *list = zend_ast_get_list(ast);
1182 		uint32_t i;
1183 		for (i = 0; i < list->children; ++i) {
1184 			fn(&list->child[i], context);
1185 		}
1186 	} else {
1187 		uint32_t i, children = zend_ast_get_num_children(ast);
1188 		for (i = 0; i < children; ++i) {
1189 			fn(&ast->child[i], context);
1190 		}
1191 	}
1192 }
1193 
1194 /*
1195  * Operator Precedence
1196  * ====================
1197  * priority  associativity  operators
1198  * ----------------------------------
1199  *   10     left            include, include_once, eval, require, require_once
1200  *   20     left            ,
1201  *   30     left            or
1202  *   40     left            xor
1203  *   50     left            and
1204  *   60     right           print
1205  *   70     right           yield
1206  *   80     right           =>
1207  *   85     right           yield from
1208  *   90     right           = += -= *= /= .= %= &= |= ^= <<= >>= **=
1209  *  100     left            ? :
1210  *  110     right           ??
1211  *  120     left            ||
1212  *  130     left            &&
1213  *  140     left            |
1214  *  150     left            ^
1215  *  160     left            &
1216  *  170     non-associative == != === !==
1217  *  180     non-associative < <= > >= <=>
1218  *  185     left            .
1219  *  190     left            << >>
1220  *  200     left            + -
1221  *  210     left            * / %
1222  *  220     right           !
1223  *  230     non-associative instanceof
1224  *  240     right           + - ++ -- ~ (type) @
1225  *  250     right           **
1226  *  260     left            [
1227  *  270     non-associative clone new
1228  */
1229 
1230 static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent);
1231 
zend_ast_export_str(smart_str * str,zend_string * s)1232 static ZEND_COLD void zend_ast_export_str(smart_str *str, zend_string *s)
1233 {
1234 	size_t i;
1235 
1236 	for (i = 0; i < ZSTR_LEN(s); i++) {
1237 		unsigned char c = ZSTR_VAL(s)[i];
1238 		if (c == '\'' || c == '\\') {
1239 			smart_str_appendc(str, '\\');
1240 			smart_str_appendc(str, c);
1241 		} else {
1242 			smart_str_appendc(str, c);
1243 		}
1244 	}
1245 }
1246 
zend_ast_export_qstr(smart_str * str,char quote,zend_string * s)1247 static ZEND_COLD void zend_ast_export_qstr(smart_str *str, char quote, zend_string *s)
1248 {
1249 	size_t i;
1250 
1251 	for (i = 0; i < ZSTR_LEN(s); i++) {
1252 		unsigned char c = ZSTR_VAL(s)[i];
1253 		if (c < ' ') {
1254 			switch (c) {
1255 				case '\n':
1256 					smart_str_appends(str, "\\n");
1257 					break;
1258 				case '\r':
1259 					smart_str_appends(str, "\\r");
1260 					break;
1261 				case '\t':
1262 					smart_str_appends(str, "\\t");
1263 					break;
1264 				case '\f':
1265 					smart_str_appends(str, "\\f");
1266 					break;
1267 				case '\v':
1268 					smart_str_appends(str, "\\v");
1269 					break;
1270 #ifdef ZEND_WIN32
1271 				case VK_ESCAPE:
1272 #else
1273 				case '\e':
1274 #endif
1275 					smart_str_appends(str, "\\e");
1276 					break;
1277 				default:
1278 					smart_str_appends(str, "\\0");
1279 					smart_str_appendc(str, '0' + (c / 8));
1280 					smart_str_appendc(str, '0' + (c % 8));
1281 					break;
1282 			}
1283 		} else {
1284 			if (c == quote || c == '$' || c == '\\') {
1285 				smart_str_appendc(str, '\\');
1286 			}
1287 			smart_str_appendc(str, c);
1288 		}
1289 	}
1290 }
1291 
zend_ast_export_indent(smart_str * str,int indent)1292 static ZEND_COLD void zend_ast_export_indent(smart_str *str, int indent)
1293 {
1294 	while (indent > 0) {
1295 		smart_str_appends(str, "    ");
1296 		indent--;
1297 	}
1298 }
1299 
zend_ast_export_name(smart_str * str,zend_ast * ast,int priority,int indent)1300 static ZEND_COLD void zend_ast_export_name(smart_str *str, zend_ast *ast, int priority, int indent)
1301 {
1302 	if (ast->kind == ZEND_AST_ZVAL) {
1303 		zval *zv = zend_ast_get_zval(ast);
1304 
1305 		if (Z_TYPE_P(zv) == IS_STRING) {
1306 			smart_str_append(str, Z_STR_P(zv));
1307 			return;
1308 		}
1309 	}
1310 	zend_ast_export_ex(str, ast, priority, indent);
1311 }
1312 
zend_ast_export_ns_name(smart_str * str,zend_ast * ast,int priority,int indent)1313 static ZEND_COLD void zend_ast_export_ns_name(smart_str *str, zend_ast *ast, int priority, int indent)
1314 {
1315 	if (ast->kind == ZEND_AST_ZVAL) {
1316 		zval *zv = zend_ast_get_zval(ast);
1317 
1318 		if (Z_TYPE_P(zv) == IS_STRING) {
1319 		    if (ast->attr == ZEND_NAME_FQ) {
1320 				smart_str_appendc(str, '\\');
1321 		    } else if (ast->attr == ZEND_NAME_RELATIVE) {
1322 				smart_str_appends(str, "namespace\\");
1323 		    }
1324 			smart_str_append(str, Z_STR_P(zv));
1325 			return;
1326 		}
1327 	}
1328 	zend_ast_export_ex(str, ast, priority, indent);
1329 }
1330 
zend_ast_valid_var_char(char ch)1331 static ZEND_COLD bool zend_ast_valid_var_char(char ch)
1332 {
1333 	unsigned char c = (unsigned char)ch;
1334 
1335 	if (c != '_' && c < 127 &&
1336 	    (c < '0' || c > '9') &&
1337 	    (c < 'A' || c > 'Z') &&
1338 	    (c < 'a' || c > 'z')) {
1339 		return 0;
1340 	}
1341 	return 1;
1342 }
1343 
zend_ast_valid_var_name(const char * s,size_t len)1344 static ZEND_COLD bool zend_ast_valid_var_name(const char *s, size_t len)
1345 {
1346 	unsigned char c;
1347 	size_t i;
1348 
1349 	if (len == 0) {
1350 		return 0;
1351 	}
1352 	c = (unsigned char)s[0];
1353 	if (c != '_' && c < 127 &&
1354 	    (c < 'A' || c > 'Z') &&
1355 	    (c < 'a' || c > 'z')) {
1356 		return 0;
1357 	}
1358 	for (i = 1; i < len; i++) {
1359 		c = (unsigned char)s[i];
1360 		if (c != '_' && c < 127 &&
1361 		    (c < '0' || c > '9') &&
1362 		    (c < 'A' || c > 'Z') &&
1363 		    (c < 'a' || c > 'z')) {
1364 			return 0;
1365 		}
1366 	}
1367 	return 1;
1368 }
1369 
zend_ast_var_needs_braces(char ch)1370 static ZEND_COLD bool zend_ast_var_needs_braces(char ch)
1371 {
1372 	return ch == '[' || zend_ast_valid_var_char(ch);
1373 }
1374 
zend_ast_export_var(smart_str * str,zend_ast * ast,int priority,int indent)1375 static ZEND_COLD void zend_ast_export_var(smart_str *str, zend_ast *ast, int priority, int indent)
1376 {
1377 	if (ast->kind == ZEND_AST_ZVAL) {
1378 		zval *zv = zend_ast_get_zval(ast);
1379 		if (Z_TYPE_P(zv) == IS_STRING &&
1380 		    zend_ast_valid_var_name(Z_STRVAL_P(zv), Z_STRLEN_P(zv))) {
1381 			smart_str_append(str, Z_STR_P(zv));
1382 			return;
1383 		}
1384 	} else if (ast->kind == ZEND_AST_VAR) {
1385 		zend_ast_export_ex(str, ast, 0, indent);
1386 		return;
1387 	}
1388 	smart_str_appendc(str, '{');
1389 	zend_ast_export_name(str, ast, 0, indent);
1390 	smart_str_appendc(str, '}');
1391 }
1392 
zend_ast_export_list(smart_str * str,zend_ast_list * list,bool separator,int priority,int indent)1393 static ZEND_COLD void zend_ast_export_list(smart_str *str, zend_ast_list *list, bool separator, int priority, int indent)
1394 {
1395 	uint32_t i = 0;
1396 
1397 	while (i < list->children) {
1398 		if (i != 0 && separator) {
1399 			smart_str_appends(str, ", ");
1400 		}
1401 		zend_ast_export_ex(str, list->child[i], priority, indent);
1402 		i++;
1403 	}
1404 }
1405 
zend_ast_export_encaps_list(smart_str * str,char quote,zend_ast_list * list,int indent)1406 static ZEND_COLD void zend_ast_export_encaps_list(smart_str *str, char quote, zend_ast_list *list, int indent)
1407 {
1408 	uint32_t i = 0;
1409 	zend_ast *ast;
1410 
1411 	while (i < list->children) {
1412 		ast = list->child[i];
1413 		if (ast->kind == ZEND_AST_ZVAL) {
1414 			zval *zv = zend_ast_get_zval(ast);
1415 
1416 			ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
1417 			zend_ast_export_qstr(str, quote, Z_STR_P(zv));
1418 		} else if (ast->kind == ZEND_AST_VAR &&
1419 		           ast->child[0]->kind == ZEND_AST_ZVAL &&
1420 		           (i + 1 == list->children ||
1421 		            list->child[i + 1]->kind != ZEND_AST_ZVAL ||
1422 		            !zend_ast_var_needs_braces(
1423 		                *Z_STRVAL_P(
1424 		                    zend_ast_get_zval(list->child[i + 1]))))) {
1425 			zend_ast_export_ex(str, ast, 0, indent);
1426 		} else {
1427 			smart_str_appendc(str, '{');
1428 			zend_ast_export_ex(str, ast, 0, indent);
1429 			smart_str_appendc(str, '}');
1430 		}
1431 		i++;
1432 	}
1433 }
1434 
zend_ast_export_name_list_ex(smart_str * str,zend_ast_list * list,int indent,const char * separator)1435 static ZEND_COLD void zend_ast_export_name_list_ex(smart_str *str, zend_ast_list *list, int indent, const char *separator)
1436 {
1437 	uint32_t i = 0;
1438 
1439 	while (i < list->children) {
1440 		if (i != 0) {
1441 			smart_str_appends(str, separator);
1442 		}
1443 		zend_ast_export_name(str, list->child[i], 0, indent);
1444 		i++;
1445 	}
1446 }
1447 
1448 #define zend_ast_export_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, ", ")
1449 #define zend_ast_export_catch_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, "|")
1450 
zend_ast_export_var_list(smart_str * str,zend_ast_list * list,int indent)1451 static ZEND_COLD void zend_ast_export_var_list(smart_str *str, zend_ast_list *list, int indent)
1452 {
1453 	uint32_t i = 0;
1454 
1455 	while (i < list->children) {
1456 		if (i != 0) {
1457 			smart_str_appends(str, ", ");
1458 		}
1459 		if (list->child[i]->attr & ZEND_BIND_REF) {
1460 			smart_str_appendc(str, '&');
1461 		}
1462 		smart_str_appendc(str, '$');
1463 		zend_ast_export_name(str, list->child[i], 20, indent);
1464 		i++;
1465 	}
1466 }
1467 
zend_ast_export_stmt(smart_str * str,zend_ast * ast,int indent)1468 static ZEND_COLD void zend_ast_export_stmt(smart_str *str, zend_ast *ast, int indent)
1469 {
1470 	if (!ast) {
1471 		return;
1472 	}
1473 
1474 	if (ast->kind == ZEND_AST_STMT_LIST ||
1475 	    ast->kind == ZEND_AST_TRAIT_ADAPTATIONS) {
1476 		zend_ast_list *list = (zend_ast_list*)ast;
1477 		uint32_t i = 0;
1478 
1479 		while (i < list->children) {
1480 			ast = list->child[i];
1481 			zend_ast_export_stmt(str, ast, indent);
1482 			i++;
1483 		}
1484 	} else {
1485 		zend_ast_export_indent(str, indent);
1486 		zend_ast_export_ex(str, ast, 0, indent);
1487 		switch (ast->kind) {
1488 			case ZEND_AST_LABEL:
1489 			case ZEND_AST_IF:
1490 			case ZEND_AST_SWITCH:
1491 			case ZEND_AST_WHILE:
1492 			case ZEND_AST_TRY:
1493 			case ZEND_AST_FOR:
1494 			case ZEND_AST_FOREACH:
1495 			case ZEND_AST_FUNC_DECL:
1496 			case ZEND_AST_METHOD:
1497 			case ZEND_AST_CLASS:
1498 			case ZEND_AST_USE_TRAIT:
1499 			case ZEND_AST_NAMESPACE:
1500 			case ZEND_AST_DECLARE:
1501 				break;
1502 			default:
1503 				smart_str_appendc(str, ';');
1504 				break;
1505 		}
1506 		smart_str_appendc(str, '\n');
1507 	}
1508 }
1509 
zend_ast_export_if_stmt(smart_str * str,zend_ast_list * list,int indent)1510 static ZEND_COLD void zend_ast_export_if_stmt(smart_str *str, zend_ast_list *list, int indent)
1511 {
1512 	uint32_t i;
1513 	zend_ast *ast;
1514 
1515 tail_call:
1516 	i = 0;
1517 	while (i < list->children) {
1518 		ast = list->child[i];
1519 		ZEND_ASSERT(ast->kind == ZEND_AST_IF_ELEM);
1520 		if (ast->child[0]) {
1521 			if (i == 0) {
1522 				smart_str_appends(str, "if (");
1523 			} else {
1524 				zend_ast_export_indent(str, indent);
1525 				smart_str_appends(str, "} elseif (");
1526 			}
1527 			zend_ast_export_ex(str, ast->child[0], 0, indent);
1528 			smart_str_appends(str, ") {\n");
1529 			zend_ast_export_stmt(str, ast->child[1], indent + 1);
1530 		} else {
1531 			zend_ast_export_indent(str, indent);
1532 			smart_str_appends(str, "} else ");
1533 			if (ast->child[1] && ast->child[1]->kind == ZEND_AST_IF) {
1534 				list = (zend_ast_list*)ast->child[1];
1535 				goto tail_call;
1536 			} else {
1537 				smart_str_appends(str, "{\n");
1538 				zend_ast_export_stmt(str, ast->child[1], indent + 1);
1539 			}
1540 		}
1541 		i++;
1542 	}
1543 	zend_ast_export_indent(str, indent);
1544 	smart_str_appendc(str, '}');
1545 }
1546 
zend_ast_export_zval(smart_str * str,zval * zv,int priority,int indent)1547 static ZEND_COLD void zend_ast_export_zval(smart_str *str, zval *zv, int priority, int indent)
1548 {
1549 	ZVAL_DEREF(zv);
1550 	switch (Z_TYPE_P(zv)) {
1551 		case IS_NULL:
1552 			smart_str_appends(str, "null");
1553 			break;
1554 		case IS_FALSE:
1555 			smart_str_appends(str, "false");
1556 			break;
1557 		case IS_TRUE:
1558 			smart_str_appends(str, "true");
1559 			break;
1560 		case IS_LONG:
1561 			smart_str_append_long(str, Z_LVAL_P(zv));
1562 			break;
1563 		case IS_DOUBLE:
1564 			smart_str_append_double(
1565 				str, Z_DVAL_P(zv), (int) EG(precision), /* zero_fraction */ false);
1566 			break;
1567 		case IS_STRING:
1568 			smart_str_appendc(str, '\'');
1569 			zend_ast_export_str(str, Z_STR_P(zv));
1570 			smart_str_appendc(str, '\'');
1571 			break;
1572 		case IS_ARRAY: {
1573 			zend_long idx;
1574 			zend_string *key;
1575 			zval *val;
1576 			bool first = true;
1577 			smart_str_appendc(str, '[');
1578 			ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(zv), idx, key, val) {
1579 				if (first) {
1580 					first = false;
1581 				} else {
1582 					smart_str_appends(str, ", ");
1583 				}
1584 				if (key) {
1585 					smart_str_appendc(str, '\'');
1586 					zend_ast_export_str(str, key);
1587 					smart_str_appends(str, "' => ");
1588 				} else {
1589 					smart_str_append_long(str, idx);
1590 					smart_str_appends(str, " => ");
1591 				}
1592 				zend_ast_export_zval(str, val, 0, indent);
1593 			} ZEND_HASH_FOREACH_END();
1594 			smart_str_appendc(str, ']');
1595 			break;
1596 		}
1597 		case IS_CONSTANT_AST:
1598 			zend_ast_export_ex(str, Z_ASTVAL_P(zv), priority, indent);
1599 			break;
1600 		EMPTY_SWITCH_DEFAULT_CASE();
1601 	}
1602 }
1603 
zend_ast_export_class_no_header(smart_str * str,zend_ast_decl * decl,int indent)1604 static ZEND_COLD void zend_ast_export_class_no_header(smart_str *str, zend_ast_decl *decl, int indent) {
1605 	if (decl->child[0]) {
1606 		smart_str_appends(str, " extends ");
1607 		zend_ast_export_ns_name(str, decl->child[0], 0, indent);
1608 	}
1609 	if (decl->child[1]) {
1610 		smart_str_appends(str, " implements ");
1611 		zend_ast_export_ex(str, decl->child[1], 0, indent);
1612 	}
1613 	smart_str_appends(str, " {\n");
1614 	zend_ast_export_stmt(str, decl->child[2], indent + 1);
1615 	zend_ast_export_indent(str, indent);
1616 	smart_str_appends(str, "}");
1617 }
1618 
zend_ast_export_attribute_group(smart_str * str,zend_ast * ast,int indent)1619 static ZEND_COLD void zend_ast_export_attribute_group(smart_str *str, zend_ast *ast, int indent) {
1620 	zend_ast_list *list = zend_ast_get_list(ast);
1621 	for (uint32_t i = 0; i < list->children; i++) {
1622 		zend_ast *attr = list->child[i];
1623 
1624 		if (i) {
1625 			smart_str_appends(str, ", ");
1626 		}
1627 		zend_ast_export_ns_name(str, attr->child[0], 0, indent);
1628 
1629 		if (attr->child[1]) {
1630 			smart_str_appendc(str, '(');
1631 			zend_ast_export_ex(str, attr->child[1], 0, indent);
1632 			smart_str_appendc(str, ')');
1633 		}
1634 	}
1635 }
1636 
zend_ast_export_attributes(smart_str * str,zend_ast * ast,int indent,bool newlines)1637 static ZEND_COLD void zend_ast_export_attributes(smart_str *str, zend_ast *ast, int indent, bool newlines) {
1638 	zend_ast_list *list = zend_ast_get_list(ast);
1639 	uint32_t i;
1640 
1641 	for (i = 0; i < list->children; i++) {
1642 		smart_str_appends(str, "#[");
1643 		zend_ast_export_attribute_group(str, list->child[i], indent);
1644 		smart_str_appends(str, "]");
1645 
1646 		if (newlines) {
1647 			smart_str_appendc(str, '\n');
1648 			zend_ast_export_indent(str, indent);
1649 		} else {
1650 			smart_str_appendc(str, ' ');
1651 		}
1652 	}
1653 }
1654 
zend_ast_export_visibility(smart_str * str,uint32_t flags)1655 static ZEND_COLD void zend_ast_export_visibility(smart_str *str, uint32_t flags) {
1656 	if (flags & ZEND_ACC_PUBLIC) {
1657 		smart_str_appends(str, "public ");
1658 	} else if (flags & ZEND_ACC_PROTECTED) {
1659 		smart_str_appends(str, "protected ");
1660 	} else if (flags & ZEND_ACC_PRIVATE) {
1661 		smart_str_appends(str, "private ");
1662 	}
1663 }
1664 
zend_ast_export_type(smart_str * str,zend_ast * ast,int indent)1665 static ZEND_COLD void zend_ast_export_type(smart_str *str, zend_ast *ast, int indent) {
1666 	if (ast->kind == ZEND_AST_TYPE_UNION) {
1667 		zend_ast_list *list = zend_ast_get_list(ast);
1668 		for (uint32_t i = 0; i < list->children; i++) {
1669 			if (i != 0) {
1670 				smart_str_appendc(str, '|');
1671 			}
1672 			zend_ast_export_type(str, list->child[i], indent);
1673 		}
1674 		return;
1675 	}
1676 	if (ast->kind == ZEND_AST_TYPE_INTERSECTION) {
1677 		zend_ast_list *list = zend_ast_get_list(ast);
1678 		for (uint32_t i = 0; i < list->children; i++) {
1679 			if (i != 0) {
1680 				smart_str_appendc(str, '&');
1681 			}
1682 			zend_ast_export_type(str, list->child[i], indent);
1683 		}
1684 		return;
1685 	}
1686 	if (ast->attr & ZEND_TYPE_NULLABLE) {
1687 		smart_str_appendc(str, '?');
1688 	}
1689 	zend_ast_export_ns_name(str, ast, 0, indent);
1690 }
1691 
1692 #define BINARY_OP(_op, _p, _pl, _pr) do { \
1693 		op = _op; \
1694 		p = _p; \
1695 		pl = _pl; \
1696 		pr = _pr; \
1697 		goto binary_op; \
1698 	} while (0)
1699 
1700 #define PREFIX_OP(_op, _p, _pl) do { \
1701 		op = _op; \
1702 		p = _p; \
1703 		pl = _pl; \
1704 		goto prefix_op; \
1705 	} while (0)
1706 
1707 #define FUNC_OP(_op) do { \
1708 		op = _op; \
1709 		goto func_op; \
1710 	} while (0)
1711 
1712 #define POSTFIX_OP(_op, _p, _pl) do { \
1713 		op = _op; \
1714 		p = _p; \
1715 		pl = _pl; \
1716 		goto postfix_op; \
1717 	} while (0)
1718 
1719 #define APPEND_NODE_1(_op) do { \
1720 		op = _op; \
1721 		goto append_node_1; \
1722 	} while (0)
1723 
1724 #define APPEND_STR(_op) do { \
1725 		op = _op; \
1726 		goto append_str; \
1727 	} while (0)
1728 
1729 #define APPEND_DEFAULT_VALUE(n) do { \
1730 		p = n; \
1731 		goto append_default_value; \
1732 	} while (0)
1733 
zend_ast_export_ex(smart_str * str,zend_ast * ast,int priority,int indent)1734 static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent)
1735 {
1736 	zend_ast_decl *decl;
1737 	int p, pl, pr;
1738 	const char *op;
1739 
1740 tail_call:
1741 	if (!ast) {
1742 		return;
1743 	}
1744 	switch (ast->kind) {
1745 		/* special nodes */
1746 		case ZEND_AST_ZVAL:
1747 			zend_ast_export_zval(str, zend_ast_get_zval(ast), priority, indent);
1748 			break;
1749 		case ZEND_AST_CONSTANT: {
1750 			zend_string *name = zend_ast_get_constant_name(ast);
1751 			smart_str_appendl(str, ZSTR_VAL(name), ZSTR_LEN(name));
1752 			break;
1753 		}
1754 		case ZEND_AST_CONSTANT_CLASS:
1755 			smart_str_appendl(str, "__CLASS__", sizeof("__CLASS__")-1);
1756 			break;
1757 		case ZEND_AST_ZNODE:
1758 			/* This AST kind is only used for temporary nodes during compilation */
1759 			ZEND_UNREACHABLE();
1760 			break;
1761 
1762 		/* declaration nodes */
1763 		case ZEND_AST_FUNC_DECL:
1764 		case ZEND_AST_CLOSURE:
1765 		case ZEND_AST_ARROW_FUNC:
1766 		case ZEND_AST_METHOD:
1767 			decl = (zend_ast_decl *) ast;
1768 			if (decl->child[4]) {
1769 				bool newlines = !(ast->kind == ZEND_AST_CLOSURE || ast->kind == ZEND_AST_ARROW_FUNC);
1770 				zend_ast_export_attributes(str, decl->child[4], indent, newlines);
1771 			}
1772 
1773 			zend_ast_export_visibility(str, decl->flags);
1774 
1775 			if (decl->flags & ZEND_ACC_STATIC) {
1776 				smart_str_appends(str, "static ");
1777 			}
1778 			if (decl->flags & ZEND_ACC_ABSTRACT) {
1779 				smart_str_appends(str, "abstract ");
1780 			}
1781 			if (decl->flags & ZEND_ACC_FINAL) {
1782 				smart_str_appends(str, "final ");
1783 			}
1784 			if (decl->kind == ZEND_AST_ARROW_FUNC) {
1785 				smart_str_appends(str, "fn");
1786 			} else {
1787 				smart_str_appends(str, "function ");
1788 			}
1789 			if (decl->flags & ZEND_ACC_RETURN_REFERENCE) {
1790 				smart_str_appendc(str, '&');
1791 			}
1792 			if (ast->kind != ZEND_AST_CLOSURE && ast->kind != ZEND_AST_ARROW_FUNC) {
1793 				smart_str_appendl(str, ZSTR_VAL(decl->name), ZSTR_LEN(decl->name));
1794 			}
1795 			smart_str_appendc(str, '(');
1796 			zend_ast_export_ex(str, decl->child[0], 0, indent);
1797 			smart_str_appendc(str, ')');
1798 			zend_ast_export_ex(str, decl->child[1], 0, indent);
1799 			if (decl->child[3]) {
1800 				smart_str_appends(str, ": ");
1801 				zend_ast_export_type(str, decl->child[3], indent);
1802 			}
1803 			if (decl->child[2]) {
1804 				if (decl->kind == ZEND_AST_ARROW_FUNC) {
1805 					zend_ast *body = decl->child[2];
1806 					if (body->kind == ZEND_AST_RETURN) {
1807 						body = body->child[0];
1808 					}
1809 					smart_str_appends(str, " => ");
1810 					zend_ast_export_ex(str, body, 0, indent);
1811 					break;
1812 				}
1813 
1814 				smart_str_appends(str, " {\n");
1815 				zend_ast_export_stmt(str, decl->child[2], indent + 1);
1816 				zend_ast_export_indent(str, indent);
1817 				smart_str_appendc(str, '}');
1818 				if (ast->kind != ZEND_AST_CLOSURE) {
1819 					smart_str_appendc(str, '\n');
1820 				}
1821 			} else {
1822 				smart_str_appends(str, ";\n");
1823 			}
1824 			break;
1825 		case ZEND_AST_CLASS:
1826 			decl = (zend_ast_decl *) ast;
1827 			if (decl->child[3]) {
1828 				zend_ast_export_attributes(str, decl->child[3], indent, 1);
1829 			}
1830 			if (decl->flags & ZEND_ACC_INTERFACE) {
1831 				smart_str_appends(str, "interface ");
1832 			} else if (decl->flags & ZEND_ACC_TRAIT) {
1833 				smart_str_appends(str, "trait ");
1834 			} else if (decl->flags & ZEND_ACC_ENUM) {
1835 				smart_str_appends(str, "enum ");
1836 			} else {
1837 				if (decl->flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
1838 					smart_str_appends(str, "abstract ");
1839 				}
1840 				if (decl->flags & ZEND_ACC_FINAL) {
1841 					smart_str_appends(str, "final ");
1842 				}
1843 				if (decl->flags & ZEND_ACC_READONLY_CLASS) {
1844 					smart_str_appends(str, "readonly ");
1845 				}
1846 				smart_str_appends(str, "class ");
1847 			}
1848 			smart_str_appendl(str, ZSTR_VAL(decl->name), ZSTR_LEN(decl->name));
1849 			if (decl->flags & ZEND_ACC_ENUM && decl->child[4]) {
1850 				smart_str_appends(str, ": ");
1851 				zend_ast_export_type(str, decl->child[4], indent);
1852 			}
1853 			zend_ast_export_class_no_header(str, decl, indent);
1854 			smart_str_appendc(str, '\n');
1855 			break;
1856 
1857 		/* list nodes */
1858 		case ZEND_AST_ARG_LIST:
1859 		case ZEND_AST_EXPR_LIST:
1860 		case ZEND_AST_PARAM_LIST:
1861 simple_list:
1862 			zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
1863 			break;
1864 		case ZEND_AST_ARRAY:
1865 			smart_str_appendc(str, '[');
1866 			zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
1867 			smart_str_appendc(str, ']');
1868 			break;
1869 		case ZEND_AST_ENCAPS_LIST:
1870 			smart_str_appendc(str, '"');
1871 			zend_ast_export_encaps_list(str, '"', (zend_ast_list*)ast, indent);
1872 			smart_str_appendc(str, '"');
1873 			break;
1874 		case ZEND_AST_STMT_LIST:
1875 		case ZEND_AST_TRAIT_ADAPTATIONS:
1876 			zend_ast_export_stmt(str, ast, indent);
1877 			break;
1878 		case ZEND_AST_IF:
1879 			zend_ast_export_if_stmt(str, (zend_ast_list*)ast, indent);
1880 			break;
1881 		case ZEND_AST_SWITCH_LIST:
1882 		case ZEND_AST_CATCH_LIST:
1883 		case ZEND_AST_MATCH_ARM_LIST:
1884 			zend_ast_export_list(str, (zend_ast_list*)ast, 0, 0, indent);
1885 			break;
1886 		case ZEND_AST_CLOSURE_USES:
1887 			smart_str_appends(str, " use(");
1888 			zend_ast_export_var_list(str, (zend_ast_list*)ast, indent);
1889 			smart_str_appendc(str, ')');
1890 			break;
1891 		case ZEND_AST_PROP_GROUP: {
1892 			zend_ast *type_ast = ast->child[0];
1893 			zend_ast *prop_ast = ast->child[1];
1894 
1895 			if (ast->child[2]) {
1896 				zend_ast_export_attributes(str, ast->child[2], indent, 1);
1897 			}
1898 
1899 			zend_ast_export_visibility(str, ast->attr);
1900 
1901 			if (ast->attr & ZEND_ACC_STATIC) {
1902 				smart_str_appends(str, "static ");
1903 			}
1904 			if (ast->attr & ZEND_ACC_READONLY) {
1905 				smart_str_appends(str, "readonly ");
1906 			}
1907 
1908 			if (type_ast) {
1909 				zend_ast_export_type(str, type_ast, indent);
1910 				smart_str_appendc(str, ' ');
1911 			}
1912 
1913 			ast = prop_ast;
1914 			goto simple_list;
1915 		}
1916 
1917 		case ZEND_AST_CONST_DECL:
1918 			smart_str_appends(str, "const ");
1919 			goto simple_list;
1920 		case ZEND_AST_CLASS_CONST_GROUP:
1921 			if (ast->child[1]) {
1922 				zend_ast_export_attributes(str, ast->child[1], indent, 1);
1923 			}
1924 
1925 			zend_ast_export_visibility(str, ast->attr);
1926 			smart_str_appends(str, "const ");
1927 			if (ast->child[2]) {
1928 				zend_ast_export_type(str, ast->child[2], indent);
1929 				smart_str_appendc(str, ' ');
1930 			}
1931 
1932 			ast = ast->child[0];
1933 
1934 			goto simple_list;
1935 		case ZEND_AST_NAME_LIST:
1936 			zend_ast_export_name_list(str, (zend_ast_list*)ast, indent);
1937 			break;
1938 		case ZEND_AST_USE:
1939 			smart_str_appends(str, "use ");
1940 			if (ast->attr == T_FUNCTION) {
1941 				smart_str_appends(str, "function ");
1942 			} else if (ast->attr == T_CONST) {
1943 				smart_str_appends(str, "const ");
1944 			}
1945 			goto simple_list;
1946 
1947 		/* 0 child nodes */
1948 		case ZEND_AST_MAGIC_CONST:
1949 			switch (ast->attr) {
1950 				case T_LINE:     APPEND_STR("__LINE__");
1951 				case T_FILE:     APPEND_STR("__FILE__");
1952 				case T_DIR:      APPEND_STR("__DIR__");
1953 				case T_TRAIT_C:  APPEND_STR("__TRAIT__");
1954 				case T_METHOD_C: APPEND_STR("__METHOD__");
1955 				case T_FUNC_C:   APPEND_STR("__FUNCTION__");
1956 				case T_NS_C:     APPEND_STR("__NAMESPACE__");
1957 				case T_CLASS_C:  APPEND_STR("__CLASS__");
1958 				EMPTY_SWITCH_DEFAULT_CASE();
1959 			}
1960 			break;
1961 		case ZEND_AST_TYPE:
1962 			switch (ast->attr & ~ZEND_TYPE_NULLABLE) {
1963 				case IS_ARRAY:    APPEND_STR("array");
1964 				case IS_CALLABLE: APPEND_STR("callable");
1965 				case IS_STATIC:   APPEND_STR("static");
1966 				case IS_MIXED:    APPEND_STR("mixed");
1967 				EMPTY_SWITCH_DEFAULT_CASE();
1968 			}
1969 			break;
1970 
1971 		/* 1 child node */
1972 		case ZEND_AST_VAR:
1973 			smart_str_appendc(str, '$');
1974 			zend_ast_export_var(str, ast->child[0], 0, indent);
1975 			break;
1976 		case ZEND_AST_CONST:
1977 			zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1978 			break;
1979 		case ZEND_AST_UNPACK:
1980 			smart_str_appends(str, "...");
1981 			ast = ast->child[0];
1982 			goto tail_call;
1983 		case ZEND_AST_UNARY_PLUS:  PREFIX_OP("+", 240, 241);
1984 		case ZEND_AST_UNARY_MINUS: PREFIX_OP("-", 240, 241);
1985 		case ZEND_AST_CAST:
1986 			switch (ast->attr) {
1987 				case IS_NULL:      PREFIX_OP("(unset)",  240, 241);
1988 				case _IS_BOOL:     PREFIX_OP("(bool)",   240, 241);
1989 				case IS_LONG:      PREFIX_OP("(int)",    240, 241);
1990 				case IS_DOUBLE:    PREFIX_OP("(double)", 240, 241);
1991 				case IS_STRING:    PREFIX_OP("(string)", 240, 241);
1992 				case IS_ARRAY:     PREFIX_OP("(array)",  240, 241);
1993 				case IS_OBJECT:    PREFIX_OP("(object)", 240, 241);
1994 				EMPTY_SWITCH_DEFAULT_CASE();
1995 			}
1996 			break;
1997 		case ZEND_AST_EMPTY:
1998 			FUNC_OP("empty");
1999 		case ZEND_AST_ISSET:
2000 			FUNC_OP("isset");
2001 		case ZEND_AST_SILENCE:
2002 			PREFIX_OP("@", 240, 241);
2003 		case ZEND_AST_SHELL_EXEC:
2004 			smart_str_appendc(str, '`');
2005 			if (ast->child[0]->kind == ZEND_AST_ENCAPS_LIST) {
2006 				zend_ast_export_encaps_list(str, '`', (zend_ast_list*)ast->child[0], indent);
2007 			} else {
2008 				zval *zv;
2009 				ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_ZVAL);
2010 				zv = zend_ast_get_zval(ast->child[0]);
2011 				ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
2012 				zend_ast_export_qstr(str, '`', Z_STR_P(zv));
2013 			}
2014 			smart_str_appendc(str, '`');
2015 			break;
2016 		case ZEND_AST_CLONE:
2017 			PREFIX_OP("clone ", 270, 271);
2018 		case ZEND_AST_EXIT:
2019 			if (ast->child[0]) {
2020 				FUNC_OP("exit");
2021 			} else {
2022 				APPEND_STR("exit");
2023 			}
2024 			break;
2025 		case ZEND_AST_PRINT:
2026 			PREFIX_OP("print ", 60, 61);
2027 		case ZEND_AST_INCLUDE_OR_EVAL:
2028 			switch (ast->attr) {
2029 				case ZEND_INCLUDE_ONCE: FUNC_OP("include_once");
2030 				case ZEND_INCLUDE:      FUNC_OP("include");
2031 				case ZEND_REQUIRE_ONCE: FUNC_OP("require_once");
2032 				case ZEND_REQUIRE:      FUNC_OP("require");
2033 				case ZEND_EVAL:         FUNC_OP("eval");
2034 				EMPTY_SWITCH_DEFAULT_CASE();
2035 			}
2036 			break;
2037 		case ZEND_AST_UNARY_OP:
2038 			switch (ast->attr) {
2039 				case ZEND_BW_NOT:   PREFIX_OP("~", 240, 241);
2040 				case ZEND_BOOL_NOT: PREFIX_OP("!", 240, 241);
2041 				EMPTY_SWITCH_DEFAULT_CASE();
2042 			}
2043 			break;
2044 		case ZEND_AST_PRE_INC:
2045 			PREFIX_OP("++", 240, 241);
2046 		case ZEND_AST_PRE_DEC:
2047 			PREFIX_OP("--", 240, 241);
2048 		case ZEND_AST_POST_INC:
2049 			POSTFIX_OP("++", 240, 241);
2050 		case ZEND_AST_POST_DEC:
2051 			POSTFIX_OP("--", 240, 241);
2052 
2053 		case ZEND_AST_GLOBAL:
2054 			APPEND_NODE_1("global");
2055 		case ZEND_AST_UNSET:
2056 			FUNC_OP("unset");
2057 		case ZEND_AST_RETURN:
2058 			APPEND_NODE_1("return");
2059 		case ZEND_AST_LABEL:
2060 			zend_ast_export_name(str, ast->child[0], 0, indent);
2061 			smart_str_appendc(str, ':');
2062 			break;
2063 		case ZEND_AST_REF:
2064 			smart_str_appendc(str, '&');
2065 			ast = ast->child[0];
2066 			goto tail_call;
2067 		case ZEND_AST_HALT_COMPILER:
2068 			APPEND_STR("__HALT_COMPILER()");
2069 		case ZEND_AST_ECHO:
2070 			APPEND_NODE_1("echo");
2071 		case ZEND_AST_THROW:
2072 			APPEND_NODE_1("throw");
2073 		case ZEND_AST_GOTO:
2074 			smart_str_appends(str, "goto ");
2075 			zend_ast_export_name(str, ast->child[0], 0, indent);
2076 			break;
2077 		case ZEND_AST_BREAK:
2078 			APPEND_NODE_1("break");
2079 		case ZEND_AST_CONTINUE:
2080 			APPEND_NODE_1("continue");
2081 
2082 		/* 2 child nodes */
2083 		case ZEND_AST_DIM:
2084 			zend_ast_export_ex(str, ast->child[0], 260, indent);
2085 			smart_str_appendc(str, '[');
2086 			if (ast->child[1]) {
2087 				zend_ast_export_ex(str, ast->child[1], 0, indent);
2088 			}
2089 			smart_str_appendc(str, ']');
2090 			break;
2091 		case ZEND_AST_PROP:
2092 		case ZEND_AST_NULLSAFE_PROP:
2093 			zend_ast_export_ex(str, ast->child[0], 0, indent);
2094 			smart_str_appends(str, ast->kind == ZEND_AST_NULLSAFE_PROP ? "?->" : "->");
2095 			zend_ast_export_var(str, ast->child[1], 0, indent);
2096 			break;
2097 		case ZEND_AST_STATIC_PROP:
2098 			zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2099 			smart_str_appends(str, "::$");
2100 			zend_ast_export_var(str, ast->child[1], 0, indent);
2101 			break;
2102 		case ZEND_AST_CALL:
2103 			zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2104 			smart_str_appendc(str, '(');
2105 			zend_ast_export_ex(str, ast->child[1], 0, indent);
2106 			smart_str_appendc(str, ')');
2107 			break;
2108 		case ZEND_AST_CALLABLE_CONVERT:
2109 			smart_str_appends(str, "...");
2110 			break;
2111 		case ZEND_AST_CLASS_CONST:
2112 			zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2113 			smart_str_appends(str, "::");
2114 			zend_ast_export_name(str, ast->child[1], 0, indent);
2115 			break;
2116 		case ZEND_AST_CLASS_NAME:
2117 			if (ast->child[0] == NULL) {
2118 				/* The const expr representation stores the fetch type instead. */
2119 				switch (ast->attr) {
2120 					case ZEND_FETCH_CLASS_SELF:
2121 						smart_str_appends(str, "self");
2122 						break;
2123 					case ZEND_FETCH_CLASS_PARENT:
2124 						smart_str_appends(str, "parent");
2125 						break;
2126 					EMPTY_SWITCH_DEFAULT_CASE()
2127 				}
2128 			} else {
2129 				zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2130 			}
2131 			smart_str_appends(str, "::class");
2132 			break;
2133 		case ZEND_AST_ASSIGN:            BINARY_OP(" = ",   90, 91, 90);
2134 		case ZEND_AST_ASSIGN_REF:        BINARY_OP(" =& ",  90, 91, 90);
2135 		case ZEND_AST_ASSIGN_OP:
2136 			switch (ast->attr) {
2137 				case ZEND_ADD:    BINARY_OP(" += ",  90, 91, 90);
2138 				case ZEND_SUB:    BINARY_OP(" -= ",  90, 91, 90);
2139 				case ZEND_MUL:    BINARY_OP(" *= ",  90, 91, 90);
2140 				case ZEND_DIV:    BINARY_OP(" /= ",  90, 91, 90);
2141 				case ZEND_MOD:    BINARY_OP(" %= ",  90, 91, 90);
2142 				case ZEND_SL:     BINARY_OP(" <<= ", 90, 91, 90);
2143 				case ZEND_SR:     BINARY_OP(" >>= ", 90, 91, 90);
2144 				case ZEND_CONCAT: BINARY_OP(" .= ",  90, 91, 90);
2145 				case ZEND_BW_OR:  BINARY_OP(" |= ",  90, 91, 90);
2146 				case ZEND_BW_AND: BINARY_OP(" &= ",  90, 91, 90);
2147 				case ZEND_BW_XOR: BINARY_OP(" ^= ",  90, 91, 90);
2148 				case ZEND_POW:    BINARY_OP(" **= ", 90, 91, 90);
2149 				EMPTY_SWITCH_DEFAULT_CASE();
2150 			}
2151 			break;
2152 		case ZEND_AST_ASSIGN_COALESCE: BINARY_OP(" \?\?= ", 90, 91, 90);
2153 		case ZEND_AST_BINARY_OP:
2154 			switch (ast->attr) {
2155 				case ZEND_ADD:                 BINARY_OP(" + ",   200, 200, 201);
2156 				case ZEND_SUB:                 BINARY_OP(" - ",   200, 200, 201);
2157 				case ZEND_MUL:                 BINARY_OP(" * ",   210, 210, 211);
2158 				case ZEND_DIV:                 BINARY_OP(" / ",   210, 210, 211);
2159 				case ZEND_MOD:                 BINARY_OP(" % ",   210, 210, 211);
2160 				case ZEND_SL:                  BINARY_OP(" << ",  190, 190, 191);
2161 				case ZEND_SR:                  BINARY_OP(" >> ",  190, 190, 191);
2162 				case ZEND_CONCAT:              BINARY_OP(" . ",   185, 185, 186);
2163 				case ZEND_BW_OR:               BINARY_OP(" | ",   140, 140, 141);
2164 				case ZEND_BW_AND:              BINARY_OP(" & ",   160, 160, 161);
2165 				case ZEND_BW_XOR:              BINARY_OP(" ^ ",   150, 150, 151);
2166 				case ZEND_IS_IDENTICAL:        BINARY_OP(" === ", 170, 171, 171);
2167 				case ZEND_IS_NOT_IDENTICAL:    BINARY_OP(" !== ", 170, 171, 171);
2168 				case ZEND_IS_EQUAL:            BINARY_OP(" == ",  170, 171, 171);
2169 				case ZEND_IS_NOT_EQUAL:        BINARY_OP(" != ",  170, 171, 171);
2170 				case ZEND_IS_SMALLER:          BINARY_OP(" < ",   180, 181, 181);
2171 				case ZEND_IS_SMALLER_OR_EQUAL: BINARY_OP(" <= ",  180, 181, 181);
2172 				case ZEND_POW:                 BINARY_OP(" ** ",  250, 251, 250);
2173 				case ZEND_BOOL_XOR:            BINARY_OP(" xor ",  40,  40,  41);
2174 				case ZEND_SPACESHIP:           BINARY_OP(" <=> ", 180, 181, 181);
2175 				EMPTY_SWITCH_DEFAULT_CASE();
2176 			}
2177 			break;
2178 		case ZEND_AST_GREATER:                 BINARY_OP(" > ",   180, 181, 181);
2179 		case ZEND_AST_GREATER_EQUAL:           BINARY_OP(" >= ",  180, 181, 181);
2180 		case ZEND_AST_AND:                     BINARY_OP(" && ",  130, 130, 131);
2181 		case ZEND_AST_OR:                      BINARY_OP(" || ",  120, 120, 121);
2182 		case ZEND_AST_ARRAY_ELEM:
2183 			if (ast->child[1]) {
2184 				zend_ast_export_ex(str, ast->child[1], 80, indent);
2185 				smart_str_appends(str, " => ");
2186 			}
2187 			if (ast->attr)
2188 				smart_str_appendc(str, '&');
2189 			zend_ast_export_ex(str, ast->child[0], 80, indent);
2190 			break;
2191 		case ZEND_AST_NEW:
2192 			smart_str_appends(str, "new ");
2193 			if (ast->child[0]->kind == ZEND_AST_CLASS) {
2194 				zend_ast_decl *decl = (zend_ast_decl *) ast->child[0];
2195 				if (decl->child[3]) {
2196 					zend_ast_export_attributes(str, decl->child[3], indent, 0);
2197 				}
2198 				smart_str_appends(str, "class");
2199 				if (!zend_ast_is_list(ast->child[1])
2200 						|| zend_ast_get_list(ast->child[1])->children) {
2201 					smart_str_appendc(str, '(');
2202 					zend_ast_export_ex(str, ast->child[1], 0, indent);
2203 					smart_str_appendc(str, ')');
2204 				}
2205 				zend_ast_export_class_no_header(str, decl, indent);
2206 			} else {
2207 				zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2208 				smart_str_appendc(str, '(');
2209 				zend_ast_export_ex(str, ast->child[1], 0, indent);
2210 				smart_str_appendc(str, ')');
2211 			}
2212 			break;
2213 		case ZEND_AST_INSTANCEOF:
2214 			zend_ast_export_ex(str, ast->child[0], 0, indent);
2215 			smart_str_appends(str, " instanceof ");
2216 			zend_ast_export_ns_name(str, ast->child[1], 0, indent);
2217 			break;
2218 		case ZEND_AST_YIELD:
2219 			if (priority > 70) smart_str_appendc(str, '(');
2220 			smart_str_appends(str, "yield ");
2221 			if (ast->child[0]) {
2222 				if (ast->child[1]) {
2223 					zend_ast_export_ex(str, ast->child[1], 70, indent);
2224 					smart_str_appends(str, " => ");
2225 				}
2226 				zend_ast_export_ex(str, ast->child[0], 70, indent);
2227 			}
2228 			if (priority > 70) smart_str_appendc(str, ')');
2229 			break;
2230 		case ZEND_AST_YIELD_FROM:
2231 			PREFIX_OP("yield from ", 85, 86);
2232 		case ZEND_AST_COALESCE: BINARY_OP(" ?? ", 110, 111, 110);
2233 		case ZEND_AST_STATIC:
2234 			smart_str_appends(str, "static $");
2235 			zend_ast_export_name(str, ast->child[0], 0, indent);
2236 			APPEND_DEFAULT_VALUE(1);
2237 		case ZEND_AST_WHILE:
2238 			smart_str_appends(str, "while (");
2239 			zend_ast_export_ex(str, ast->child[0], 0, indent);
2240 			smart_str_appends(str, ") {\n");
2241 			zend_ast_export_stmt(str, ast->child[1], indent + 1);
2242 			zend_ast_export_indent(str, indent);
2243 			smart_str_appendc(str, '}');
2244 			break;
2245 		case ZEND_AST_DO_WHILE:
2246 			smart_str_appends(str, "do {\n");
2247 			zend_ast_export_stmt(str, ast->child[0], indent + 1);
2248 			zend_ast_export_indent(str, indent);
2249 			smart_str_appends(str, "} while (");
2250 			zend_ast_export_ex(str, ast->child[1], 0, indent);
2251 			smart_str_appendc(str, ')');
2252 			break;
2253 
2254 		case ZEND_AST_IF_ELEM:
2255 			if (ast->child[0]) {
2256 				smart_str_appends(str, "if (");
2257 				zend_ast_export_ex(str, ast->child[0], 0, indent);
2258 				smart_str_appends(str, ") {\n");
2259 				zend_ast_export_stmt(str, ast->child[1], indent + 1);
2260 			} else {
2261 				smart_str_appends(str, "else {\n");
2262 				zend_ast_export_stmt(str, ast->child[1], indent + 1);
2263 			}
2264 			zend_ast_export_indent(str, indent);
2265 			smart_str_appendc(str, '}');
2266 			break;
2267 		case ZEND_AST_SWITCH:
2268 			smart_str_appends(str, "switch (");
2269 			zend_ast_export_ex(str, ast->child[0], 0, indent);
2270 			smart_str_appends(str, ") {\n");
2271 			zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2272 			zend_ast_export_indent(str, indent);
2273 			smart_str_appendc(str, '}');
2274 			break;
2275 		case ZEND_AST_SWITCH_CASE:
2276 			zend_ast_export_indent(str, indent);
2277 			if (ast->child[0]) {
2278 				smart_str_appends(str, "case ");
2279 				zend_ast_export_ex(str, ast->child[0], 0, indent);
2280 				smart_str_appends(str, ":\n");
2281 			} else {
2282 				smart_str_appends(str, "default:\n");
2283 			}
2284 			zend_ast_export_stmt(str, ast->child[1], indent + 1);
2285 			break;
2286 		case ZEND_AST_MATCH:
2287 			smart_str_appends(str, "match (");
2288 			zend_ast_export_ex(str, ast->child[0], 0, indent);
2289 			smart_str_appends(str, ") {\n");
2290 			zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2291 			zend_ast_export_indent(str, indent);
2292 			smart_str_appendc(str, '}');
2293 			break;
2294 		case ZEND_AST_MATCH_ARM:
2295 			zend_ast_export_indent(str, indent);
2296 			if (ast->child[0]) {
2297 				zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent);
2298 				smart_str_appends(str, " => ");
2299 			} else {
2300 				smart_str_appends(str, "default => ");
2301 			}
2302 			zend_ast_export_ex(str, ast->child[1], 0, 0);
2303 			smart_str_appends(str, ",\n");
2304 			break;
2305 		case ZEND_AST_DECLARE:
2306 			smart_str_appends(str, "declare(");
2307 			ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_CONST_DECL);
2308 			zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent);
2309 			smart_str_appendc(str, ')');
2310 			if (ast->child[1]) {
2311 				smart_str_appends(str, " {\n");
2312 				zend_ast_export_stmt(str, ast->child[1], indent + 1);
2313 				zend_ast_export_indent(str, indent);
2314 				smart_str_appendc(str, '}');
2315 			} else {
2316 				smart_str_appendc(str, ';');
2317 			}
2318 			break;
2319 		case ZEND_AST_PROP_ELEM:
2320 			smart_str_appendc(str, '$');
2321 			ZEND_FALLTHROUGH;
2322 		case ZEND_AST_CONST_ELEM:
2323 			zend_ast_export_name(str, ast->child[0], 0, indent);
2324 			APPEND_DEFAULT_VALUE(1);
2325 		case ZEND_AST_USE_TRAIT:
2326 			smart_str_appends(str, "use ");
2327 			zend_ast_export_ex(str, ast->child[0], 0, indent);
2328 			if (ast->child[1]) {
2329 				smart_str_appends(str, " {\n");
2330 				zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2331 				zend_ast_export_indent(str, indent);
2332 				smart_str_appends(str, "}");
2333 			} else {
2334 				smart_str_appends(str, ";");
2335 			}
2336 			break;
2337 		case ZEND_AST_TRAIT_PRECEDENCE:
2338 			zend_ast_export_ex(str, ast->child[0], 0, indent);
2339 			smart_str_appends(str, " insteadof ");
2340 			zend_ast_export_ex(str, ast->child[1], 0, indent);
2341 			break;
2342 		case ZEND_AST_METHOD_REFERENCE:
2343 			if (ast->child[0]) {
2344 				zend_ast_export_name(str, ast->child[0], 0, indent);
2345 				smart_str_appends(str, "::");
2346 			}
2347 			zend_ast_export_name(str, ast->child[1], 0, indent);
2348 			break;
2349 		case ZEND_AST_NAMESPACE:
2350 			smart_str_appends(str, "namespace");
2351 			if (ast->child[0]) {
2352 				smart_str_appendc(str, ' ');
2353 				zend_ast_export_name(str, ast->child[0], 0, indent);
2354 			}
2355 			if (ast->child[1]) {
2356 				smart_str_appends(str, " {\n");
2357 				zend_ast_export_stmt(str, ast->child[1], indent + 1);
2358 				zend_ast_export_indent(str, indent);
2359 				smart_str_appends(str, "}\n");
2360 			} else {
2361 				smart_str_appendc(str, ';');
2362 			}
2363 			break;
2364 		case ZEND_AST_USE_ELEM:
2365 		case ZEND_AST_TRAIT_ALIAS:
2366 			zend_ast_export_name(str, ast->child[0], 0, indent);
2367 			if (ast->attr & ZEND_ACC_PUBLIC) {
2368 				smart_str_appends(str, " as public");
2369 			} else if (ast->attr & ZEND_ACC_PROTECTED) {
2370 				smart_str_appends(str, " as protected");
2371 			} else if (ast->attr & ZEND_ACC_PRIVATE) {
2372 				smart_str_appends(str, " as private");
2373 			} else if (ast->child[1]) {
2374 				smart_str_appends(str, " as");
2375 			}
2376 			if (ast->child[1]) {
2377 				smart_str_appendc(str, ' ');
2378 				zend_ast_export_name(str, ast->child[1], 0, indent);
2379 			}
2380 			break;
2381 		case ZEND_AST_NAMED_ARG:
2382 			smart_str_append(str, zend_ast_get_str(ast->child[0]));
2383 			smart_str_appends(str, ": ");
2384 			ast = ast->child[1];
2385 			goto tail_call;
2386 
2387 		/* 3 child nodes */
2388 		case ZEND_AST_METHOD_CALL:
2389 		case ZEND_AST_NULLSAFE_METHOD_CALL:
2390 			zend_ast_export_ex(str, ast->child[0], 0, indent);
2391 			smart_str_appends(str, ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL ? "?->" : "->");
2392 			zend_ast_export_var(str, ast->child[1], 0, indent);
2393 			smart_str_appendc(str, '(');
2394 			zend_ast_export_ex(str, ast->child[2], 0, indent);
2395 			smart_str_appendc(str, ')');
2396 			break;
2397 		case ZEND_AST_STATIC_CALL:
2398 			zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2399 			smart_str_appends(str, "::");
2400 			zend_ast_export_var(str, ast->child[1], 0, indent);
2401 			smart_str_appendc(str, '(');
2402 			zend_ast_export_ex(str, ast->child[2], 0, indent);
2403 			smart_str_appendc(str, ')');
2404 			break;
2405 		case ZEND_AST_CONDITIONAL:
2406 			if (priority > 100) smart_str_appendc(str, '(');
2407 			zend_ast_export_ex(str, ast->child[0], 100, indent);
2408 			if (ast->child[1]) {
2409 				smart_str_appends(str, " ? ");
2410 				zend_ast_export_ex(str, ast->child[1], 101, indent);
2411 				smart_str_appends(str, " : ");
2412 			} else {
2413 				smart_str_appends(str, " ?: ");
2414 			}
2415 			zend_ast_export_ex(str, ast->child[2], 101, indent);
2416 			if (priority > 100) smart_str_appendc(str, ')');
2417 			break;
2418 
2419 		case ZEND_AST_TRY:
2420 			smart_str_appends(str, "try {\n");
2421 			zend_ast_export_stmt(str, ast->child[0], indent + 1);
2422 			zend_ast_export_indent(str, indent);
2423 			zend_ast_export_ex(str, ast->child[1], 0, indent);
2424 			if (ast->child[2]) {
2425 				smart_str_appends(str, "} finally {\n");
2426 				zend_ast_export_stmt(str, ast->child[2], indent + 1);
2427 				zend_ast_export_indent(str, indent);
2428 			}
2429 			smart_str_appendc(str, '}');
2430 			break;
2431 		case ZEND_AST_CATCH:
2432 			smart_str_appends(str, "} catch (");
2433 			zend_ast_export_catch_name_list(str, zend_ast_get_list(ast->child[0]), indent);
2434 			if (ast->child[1]) {
2435 				smart_str_appends(str, " $");
2436 				zend_ast_export_var(str, ast->child[1], 0, indent);
2437 			}
2438 			smart_str_appends(str, ") {\n");
2439 			zend_ast_export_stmt(str, ast->child[2], indent + 1);
2440 			zend_ast_export_indent(str, indent);
2441 			break;
2442 		case ZEND_AST_PARAM:
2443 			if (ast->child[3]) {
2444 				zend_ast_export_attributes(str, ast->child[3], indent, 0);
2445 			}
2446 			if (ast->child[0]) {
2447 				zend_ast_export_type(str, ast->child[0], indent);
2448 				smart_str_appendc(str, ' ');
2449 			}
2450 			if (ast->attr & ZEND_PARAM_REF) {
2451 				smart_str_appendc(str, '&');
2452 			}
2453 			if (ast->attr & ZEND_PARAM_VARIADIC) {
2454 				smart_str_appends(str, "...");
2455 			}
2456 			smart_str_appendc(str, '$');
2457 			zend_ast_export_name(str, ast->child[1], 0, indent);
2458 			APPEND_DEFAULT_VALUE(2);
2459 		case ZEND_AST_ENUM_CASE:
2460 			if (ast->child[3]) {
2461 				zend_ast_export_attributes(str, ast->child[3], indent, 1);
2462 			}
2463 			smart_str_appends(str, "case ");
2464 			zend_ast_export_name(str, ast->child[0], 0, indent);
2465 			if (ast->child[1]) {
2466 				smart_str_appends(str, " = ");
2467 				zend_ast_export_ex(str, ast->child[1], 0, indent);
2468 			}
2469 			break;
2470 
2471 		/* 4 child nodes */
2472 		case ZEND_AST_FOR:
2473 			smart_str_appends(str, "for (");
2474 			zend_ast_export_ex(str, ast->child[0], 0, indent);
2475 			smart_str_appendc(str, ';');
2476 			if (ast->child[1]) {
2477 				smart_str_appendc(str, ' ');
2478 				zend_ast_export_ex(str, ast->child[1], 0, indent);
2479 			}
2480 			smart_str_appendc(str, ';');
2481 			if (ast->child[2]) {
2482 				smart_str_appendc(str, ' ');
2483 				zend_ast_export_ex(str, ast->child[2], 0, indent);
2484 			}
2485 			smart_str_appends(str, ") {\n");
2486 			zend_ast_export_stmt(str, ast->child[3], indent + 1);
2487 			zend_ast_export_indent(str, indent);
2488 			smart_str_appendc(str, '}');
2489 			break;
2490 		case ZEND_AST_FOREACH:
2491 			smart_str_appends(str, "foreach (");
2492 			zend_ast_export_ex(str, ast->child[0], 0, indent);
2493 			smart_str_appends(str, " as ");
2494 			if (ast->child[2]) {
2495 				zend_ast_export_ex(str, ast->child[2], 0, indent);
2496 				smart_str_appends(str, " => ");
2497 			}
2498 			zend_ast_export_ex(str, ast->child[1], 0, indent);
2499 			smart_str_appends(str, ") {\n");
2500 			zend_ast_export_stmt(str, ast->child[3], indent + 1);
2501 			zend_ast_export_indent(str, indent);
2502 			smart_str_appendc(str, '}');
2503 			break;
2504 		EMPTY_SWITCH_DEFAULT_CASE();
2505 	}
2506 	return;
2507 
2508 binary_op:
2509 	if (priority > p) smart_str_appendc(str, '(');
2510 	zend_ast_export_ex(str, ast->child[0], pl, indent);
2511 	smart_str_appends(str, op);
2512 	zend_ast_export_ex(str, ast->child[1], pr, indent);
2513 	if (priority > p) smart_str_appendc(str, ')');
2514 	return;
2515 
2516 prefix_op:
2517 	if (priority > p) smart_str_appendc(str, '(');
2518 	smart_str_appends(str, op);
2519 	zend_ast_export_ex(str, ast->child[0], pl, indent);
2520 	if (priority > p) smart_str_appendc(str, ')');
2521 	return;
2522 
2523 postfix_op:
2524 	if (priority > p) smart_str_appendc(str, '(');
2525 	zend_ast_export_ex(str, ast->child[0], pl, indent);
2526 	smart_str_appends(str, op);
2527 	if (priority > p) smart_str_appendc(str, ')');
2528 	return;
2529 
2530 func_op:
2531 	smart_str_appends(str, op);
2532 	smart_str_appendc(str, '(');
2533 	zend_ast_export_ex(str, ast->child[0], 0, indent);
2534 	smart_str_appendc(str, ')');
2535 	return;
2536 
2537 append_node_1:
2538 	smart_str_appends(str, op);
2539 	if (ast->child[0]) {
2540 		smart_str_appendc(str, ' ');
2541 		ast = ast->child[0];
2542 		goto tail_call;
2543 	}
2544 	return;
2545 
2546 append_str:
2547 	smart_str_appends(str, op);
2548 	return;
2549 
2550 append_default_value:
2551 	if (ast->child[p]) {
2552 		smart_str_appends(str, " = ");
2553 		ast = ast->child[p];
2554 		goto tail_call;
2555 	}
2556 	return;
2557 }
2558 
zend_ast_export(const char * prefix,zend_ast * ast,const char * suffix)2559 ZEND_API ZEND_COLD zend_string *zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix)
2560 {
2561 	smart_str str = {0};
2562 
2563 	smart_str_appends(&str, prefix);
2564 	zend_ast_export_ex(&str, ast, 0, 0);
2565 	smart_str_appends(&str, suffix);
2566 	smart_str_0(&str);
2567 	return str.s;
2568 }
2569 
zend_ast_with_attributes(zend_ast * ast,zend_ast * attr)2570 zend_ast * ZEND_FASTCALL zend_ast_with_attributes(zend_ast *ast, zend_ast *attr)
2571 {
2572 	ZEND_ASSERT(attr->kind == ZEND_AST_ATTRIBUTE_LIST);
2573 
2574 	switch (ast->kind) {
2575 	case ZEND_AST_FUNC_DECL:
2576 	case ZEND_AST_CLOSURE:
2577 	case ZEND_AST_METHOD:
2578 	case ZEND_AST_ARROW_FUNC:
2579 		((zend_ast_decl *) ast)->child[4] = attr;
2580 		break;
2581 	case ZEND_AST_CLASS:
2582 		((zend_ast_decl *) ast)->child[3] = attr;
2583 		break;
2584 	case ZEND_AST_PROP_GROUP:
2585 		ast->child[2] = attr;
2586 		break;
2587 	case ZEND_AST_PARAM:
2588 	case ZEND_AST_ENUM_CASE:
2589 		ast->child[3] = attr;
2590 		break;
2591 	case ZEND_AST_CLASS_CONST_GROUP:
2592 		ast->child[1] = attr;
2593 		break;
2594 	EMPTY_SWITCH_DEFAULT_CASE()
2595 	}
2596 
2597 	return ast;
2598 }
2599