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