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