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