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