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