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