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