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 #include "zend_enum.h"
28
29 ZEND_API zend_ast_process_t zend_ast_process = NULL;
30
zend_ast_alloc(size_t size)31 static inline void *zend_ast_alloc(size_t size) {
32 return zend_arena_alloc(&CG(ast_arena), size);
33 }
34
zend_ast_realloc(void * old,size_t old_size,size_t new_size)35 static inline void *zend_ast_realloc(void *old, size_t old_size, size_t new_size) {
36 void *new = zend_ast_alloc(new_size);
37 memcpy(new, old, old_size);
38 return new;
39 }
40
zend_ast_list_size(uint32_t children)41 static inline size_t zend_ast_list_size(uint32_t children) {
42 return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
43 }
44
zend_ast_create_znode(znode * node)45 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(znode *node) {
46 zend_ast_znode *ast;
47
48 ast = zend_ast_alloc(sizeof(zend_ast_znode));
49 ast->kind = ZEND_AST_ZNODE;
50 ast->attr = 0;
51 ast->lineno = CG(zend_lineno);
52 ast->node = *node;
53 return (zend_ast *) ast;
54 }
55
zend_ast_create_zval_int(zval * zv,uint32_t attr,uint32_t lineno)56 static zend_always_inline zend_ast * zend_ast_create_zval_int(zval *zv, uint32_t attr, uint32_t lineno) {
57 zend_ast_zval *ast;
58
59 ast = zend_ast_alloc(sizeof(zend_ast_zval));
60 ast->kind = ZEND_AST_ZVAL;
61 ast->attr = attr;
62 ZVAL_COPY_VALUE(&ast->val, zv);
63 Z_LINENO(ast->val) = lineno;
64 return (zend_ast *) ast;
65 }
66
zend_ast_create_zval_with_lineno(zval * zv,uint32_t lineno)67 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_with_lineno(zval *zv, uint32_t lineno) {
68 return zend_ast_create_zval_int(zv, 0, lineno);
69 }
70
zend_ast_create_zval_ex(zval * zv,zend_ast_attr attr)71 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) {
72 return zend_ast_create_zval_int(zv, attr, CG(zend_lineno));
73 }
74
zend_ast_create_zval(zval * zv)75 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval(zval *zv) {
76 return zend_ast_create_zval_int(zv, 0, CG(zend_lineno));
77 }
78
zend_ast_create_zval_from_str(zend_string * str)79 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_str(zend_string *str) {
80 zval zv;
81 ZVAL_STR(&zv, str);
82 return zend_ast_create_zval_int(&zv, 0, CG(zend_lineno));
83 }
84
zend_ast_create_zval_from_long(zend_long lval)85 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_long(zend_long lval) {
86 zval zv;
87 ZVAL_LONG(&zv, lval);
88 return zend_ast_create_zval_int(&zv, 0, CG(zend_lineno));
89 }
90
zend_ast_create_constant(zend_string * name,zend_ast_attr attr)91 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_constant(zend_string *name, zend_ast_attr attr) {
92 zend_ast_zval *ast;
93
94 ast = zend_ast_alloc(sizeof(zend_ast_zval));
95 ast->kind = ZEND_AST_CONSTANT;
96 ast->attr = attr;
97 ZVAL_STR(&ast->val, name);
98 Z_LINENO(ast->val) = CG(zend_lineno);
99 return (zend_ast *) ast;
100 }
101
zend_ast_create_class_const_or_name(zend_ast * class_name,zend_ast * name)102 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_class_const_or_name(zend_ast *class_name, zend_ast *name) {
103 zend_string *name_str = zend_ast_get_str(name);
104 if (zend_string_equals_ci(name_str, ZSTR_KNOWN(ZEND_STR_CLASS))) {
105 zend_string_release(name_str);
106 return zend_ast_create(ZEND_AST_CLASS_NAME, class_name);
107 } else {
108 return zend_ast_create(ZEND_AST_CLASS_CONST, class_name, name);
109 }
110 }
111
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)112 ZEND_API zend_ast *zend_ast_create_decl(
113 zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment,
114 zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4
115 ) {
116 zend_ast_decl *ast;
117
118 ast = zend_ast_alloc(sizeof(zend_ast_decl));
119 ast->kind = kind;
120 ast->attr = 0;
121 ast->start_lineno = start_lineno;
122 ast->end_lineno = CG(zend_lineno);
123 ast->flags = flags;
124 ast->doc_comment = doc_comment;
125 ast->name = name;
126 ast->child[0] = child0;
127 ast->child[1] = child1;
128 ast->child[2] = child2;
129 ast->child[3] = child3;
130 ast->child[4] = child4;
131
132 return (zend_ast *) ast;
133 }
134
135 #if ZEND_AST_SPEC
zend_ast_create_0(zend_ast_kind kind)136 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_0(zend_ast_kind kind) {
137 zend_ast *ast;
138
139 ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 0);
140 ast = zend_ast_alloc(zend_ast_size(0));
141 ast->kind = kind;
142 ast->attr = 0;
143 ast->lineno = CG(zend_lineno);
144
145 return ast;
146 }
147
zend_ast_create_1(zend_ast_kind kind,zend_ast * child)148 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_1(zend_ast_kind kind, zend_ast *child) {
149 zend_ast *ast;
150 uint32_t lineno;
151
152 ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 1);
153 ast = zend_ast_alloc(zend_ast_size(1));
154 ast->kind = kind;
155 ast->attr = 0;
156 ast->child[0] = child;
157 if (child) {
158 lineno = zend_ast_get_lineno(child);
159 } else {
160 lineno = CG(zend_lineno);
161 }
162 ast->lineno = lineno;
163
164 return ast;
165 }
166
zend_ast_create_2(zend_ast_kind kind,zend_ast * child1,zend_ast * child2)167 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
168 zend_ast *ast;
169 uint32_t lineno;
170
171 ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 2);
172 ast = zend_ast_alloc(zend_ast_size(2));
173 ast->kind = kind;
174 ast->attr = 0;
175 ast->child[0] = child1;
176 ast->child[1] = child2;
177 if (child1) {
178 lineno = zend_ast_get_lineno(child1);
179 } else if (child2) {
180 lineno = zend_ast_get_lineno(child2);
181 } else {
182 lineno = CG(zend_lineno);
183 }
184 ast->lineno = lineno;
185
186 return ast;
187 }
188
zend_ast_create_3(zend_ast_kind kind,zend_ast * child1,zend_ast * child2,zend_ast * child3)189 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_3(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3) {
190 zend_ast *ast;
191 uint32_t lineno;
192
193 ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 3);
194 ast = zend_ast_alloc(zend_ast_size(3));
195 ast->kind = kind;
196 ast->attr = 0;
197 ast->child[0] = child1;
198 ast->child[1] = child2;
199 ast->child[2] = child3;
200 if (child1) {
201 lineno = zend_ast_get_lineno(child1);
202 } else if (child2) {
203 lineno = zend_ast_get_lineno(child2);
204 } else if (child3) {
205 lineno = zend_ast_get_lineno(child3);
206 } else {
207 lineno = CG(zend_lineno);
208 }
209 ast->lineno = lineno;
210
211 return ast;
212 }
213
zend_ast_create_4(zend_ast_kind kind,zend_ast * child1,zend_ast * child2,zend_ast * child3,zend_ast * child4)214 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) {
215 zend_ast *ast;
216 uint32_t lineno;
217
218 ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 4);
219 ast = zend_ast_alloc(zend_ast_size(4));
220 ast->kind = kind;
221 ast->attr = 0;
222 ast->child[0] = child1;
223 ast->child[1] = child2;
224 ast->child[2] = child3;
225 ast->child[3] = child4;
226 if (child1) {
227 lineno = zend_ast_get_lineno(child1);
228 } else if (child2) {
229 lineno = zend_ast_get_lineno(child2);
230 } else if (child3) {
231 lineno = zend_ast_get_lineno(child3);
232 } else if (child4) {
233 lineno = zend_ast_get_lineno(child4);
234 } else {
235 lineno = CG(zend_lineno);
236 }
237 ast->lineno = lineno;
238
239 return ast;
240 }
241
zend_ast_create_5(zend_ast_kind kind,zend_ast * child1,zend_ast * child2,zend_ast * child3,zend_ast * child4,zend_ast * child5)242 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) {
243 zend_ast *ast;
244 uint32_t lineno;
245
246 ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 5);
247 ast = zend_ast_alloc(zend_ast_size(5));
248 ast->kind = kind;
249 ast->attr = 0;
250 ast->child[0] = child1;
251 ast->child[1] = child2;
252 ast->child[2] = child3;
253 ast->child[3] = child4;
254 ast->child[4] = child5;
255 if (child1) {
256 lineno = zend_ast_get_lineno(child1);
257 } else if (child2) {
258 lineno = zend_ast_get_lineno(child2);
259 } else if (child3) {
260 lineno = zend_ast_get_lineno(child3);
261 } else if (child4) {
262 lineno = zend_ast_get_lineno(child4);
263 } else if (child5) {
264 lineno = zend_ast_get_lineno(child5);
265 } else {
266 lineno = CG(zend_lineno);
267 }
268 ast->lineno = lineno;
269
270 return ast;
271 }
272
zend_ast_create_va(zend_ast_kind kind,zend_ast_attr attr,va_list * va)273 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_va(
274 zend_ast_kind kind, zend_ast_attr attr, va_list *va) {
275 uint32_t lineno = (uint32_t)-1;
276 uint32_t children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
277 zend_ast *ast = zend_ast_alloc(zend_ast_size(children));
278 ast->kind = kind;
279 ast->attr = attr;
280 for (uint32_t i = 0; i < children; i++) {
281 ast->child[i] = va_arg(*va, zend_ast *);
282 if (lineno != (uint32_t)-1 && ast->child[i]) {
283 lineno = zend_ast_get_lineno(ast->child[i]);
284 }
285 }
286 if (lineno == (uint32_t)-1) {
287 lineno = CG(zend_lineno);
288 }
289 ast->lineno = lineno;
290 return ast;
291 }
292
zend_ast_create_n(unsigned kind,...)293 ZEND_API zend_ast * zend_ast_create_n(unsigned kind, ...) {
294 va_list va;
295 va_start(va, kind);
296 zend_ast *ast = zend_ast_create_va(kind, 0, &va);
297 va_end(va);
298 return ast;
299 }
300
zend_ast_create_ex_n(zend_ast_kind kind,unsigned attr,...)301 ZEND_API zend_ast * zend_ast_create_ex_n(
302 zend_ast_kind kind, unsigned attr, ...) {
303 va_list va;
304 va_start(va, attr);
305 zend_ast *ast = zend_ast_create_va(kind, attr, &va);
306 va_end(va);
307 return ast;
308 }
309
zend_ast_create_list_0(zend_ast_kind kind)310 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_0(zend_ast_kind kind) {
311 zend_ast *ast;
312 zend_ast_list *list;
313
314 ast = zend_ast_alloc(zend_ast_list_size(4));
315 list = (zend_ast_list *) ast;
316 list->kind = kind;
317 list->attr = 0;
318 list->lineno = CG(zend_lineno);
319 list->children = 0;
320
321 return ast;
322 }
323
zend_ast_create_list_1(zend_ast_kind kind,zend_ast * child)324 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_1(zend_ast_kind kind, zend_ast *child) {
325 zend_ast *ast;
326 zend_ast_list *list;
327 uint32_t lineno;
328
329 ast = zend_ast_alloc(zend_ast_list_size(4));
330 list = (zend_ast_list *) ast;
331 list->kind = kind;
332 list->attr = 0;
333 list->children = 1;
334 list->child[0] = child;
335 if (child) {
336 lineno = zend_ast_get_lineno(child);
337 if (lineno > CG(zend_lineno)) {
338 lineno = CG(zend_lineno);
339 }
340 } else {
341 lineno = CG(zend_lineno);
342 }
343 list->lineno = lineno;
344
345 return ast;
346 }
347
zend_ast_create_list_2(zend_ast_kind kind,zend_ast * child1,zend_ast * child2)348 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
349 zend_ast *ast;
350 zend_ast_list *list;
351 uint32_t lineno;
352
353 ast = zend_ast_alloc(zend_ast_list_size(4));
354 list = (zend_ast_list *) ast;
355 list->kind = kind;
356 list->attr = 0;
357 list->children = 2;
358 list->child[0] = child1;
359 list->child[1] = child2;
360 if (child1) {
361 lineno = zend_ast_get_lineno(child1);
362 if (lineno > CG(zend_lineno)) {
363 lineno = CG(zend_lineno);
364 }
365 } else if (child2) {
366 lineno = zend_ast_get_lineno(child2);
367 if (lineno > CG(zend_lineno)) {
368 lineno = CG(zend_lineno);
369 }
370 } else {
371 list->children = 0;
372 lineno = CG(zend_lineno);
373 }
374 list->lineno = lineno;
375
376 return ast;
377 }
378 #else
zend_ast_create_from_va_list(zend_ast_kind kind,zend_ast_attr attr,va_list va)379 static zend_ast *zend_ast_create_from_va_list(zend_ast_kind kind, zend_ast_attr attr, va_list va) {
380 uint32_t i, children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
381 zend_ast *ast;
382
383 ast = zend_ast_alloc(zend_ast_size(children));
384 ast->kind = kind;
385 ast->attr = attr;
386 ast->lineno = (uint32_t) -1;
387
388 for (i = 0; i < children; ++i) {
389 ast->child[i] = va_arg(va, zend_ast *);
390 if (ast->child[i] != NULL) {
391 uint32_t lineno = zend_ast_get_lineno(ast->child[i]);
392 if (lineno < ast->lineno) {
393 ast->lineno = lineno;
394 }
395 }
396 }
397
398 if (ast->lineno == UINT_MAX) {
399 ast->lineno = CG(zend_lineno);
400 }
401
402 return ast;
403 }
404
zend_ast_create_ex(zend_ast_kind kind,zend_ast_attr attr,...)405 ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...) {
406 va_list va;
407 zend_ast *ast;
408
409 va_start(va, attr);
410 ast = zend_ast_create_from_va_list(kind, attr, va);
411 va_end(va);
412
413 return ast;
414 }
415
zend_ast_create(zend_ast_kind kind,...)416 ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...) {
417 va_list va;
418 zend_ast *ast;
419
420 va_start(va, kind);
421 ast = zend_ast_create_from_va_list(kind, 0, va);
422 va_end(va);
423
424 return ast;
425 }
426
zend_ast_create_list(uint32_t init_children,zend_ast_kind kind,...)427 ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...) {
428 zend_ast *ast;
429 zend_ast_list *list;
430
431 ast = zend_ast_alloc(zend_ast_list_size(4));
432 list = (zend_ast_list *) ast;
433 list->kind = kind;
434 list->attr = 0;
435 list->lineno = CG(zend_lineno);
436 list->children = 0;
437
438 {
439 va_list va;
440 uint32_t i;
441 va_start(va, kind);
442 for (i = 0; i < init_children; ++i) {
443 zend_ast *child = va_arg(va, zend_ast *);
444 ast = zend_ast_list_add(ast, child);
445 if (child != NULL) {
446 uint32_t lineno = zend_ast_get_lineno(child);
447 if (lineno < ast->lineno) {
448 ast->lineno = lineno;
449 }
450 }
451 }
452 va_end(va);
453 }
454
455 return ast;
456 }
457 #endif
458
zend_ast_create_concat_op(zend_ast * op0,zend_ast * op1)459 zend_ast *zend_ast_create_concat_op(zend_ast *op0, zend_ast *op1) {
460 if (op0->kind == ZEND_AST_ZVAL && op1->kind == ZEND_AST_ZVAL) {
461 zval *zv0 = zend_ast_get_zval(op0);
462 zval *zv1 = zend_ast_get_zval(op1);
463 if (!zend_binary_op_produces_error(ZEND_CONCAT, zv0, zv1) &&
464 concat_function(zv0, zv0, zv1) == SUCCESS) {
465 zval_ptr_dtor_nogc(zv1);
466 return zend_ast_create_zval(zv0);
467 }
468 }
469 return zend_ast_create_binary_op(ZEND_CONCAT, op0, op1);
470 }
471
is_power_of_two(uint32_t n)472 static inline bool is_power_of_two(uint32_t n) {
473 return ((n != 0) && (n == (n & (~n + 1))));
474 }
475
zend_ast_list_add(zend_ast * ast,zend_ast * op)476 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *ast, zend_ast *op) {
477 zend_ast_list *list = zend_ast_get_list(ast);
478 if (list->children >= 4 && is_power_of_two(list->children)) {
479 list = zend_ast_realloc(list,
480 zend_ast_list_size(list->children), zend_ast_list_size(list->children * 2));
481 }
482 list->child[list->children++] = op;
483 return (zend_ast *) list;
484 }
485
zend_ast_add_array_element(zval * result,zval * offset,zval * expr)486 static zend_result zend_ast_add_array_element(zval *result, zval *offset, zval *expr)
487 {
488 if (Z_TYPE_P(offset) == IS_UNDEF) {
489 if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), expr)) {
490 zend_throw_error(NULL,
491 "Cannot add element to the array as the next element is already occupied");
492 return FAILURE;
493 }
494 return SUCCESS;
495 }
496
497 if (array_set_zval_key(Z_ARRVAL_P(result), offset, expr) == FAILURE) {
498 return FAILURE;
499 }
500
501 zval_ptr_dtor_nogc(offset);
502 zval_ptr_dtor_nogc(expr);
503 return SUCCESS;
504 }
505
zend_ast_add_unpacked_element(zval * result,zval * expr)506 static zend_result zend_ast_add_unpacked_element(zval *result, zval *expr) {
507 if (EXPECTED(Z_TYPE_P(expr) == IS_ARRAY)) {
508 HashTable *ht = Z_ARRVAL_P(expr);
509 zval *val;
510 zend_string *key;
511
512 ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
513 if (key) {
514 zend_hash_update(Z_ARRVAL_P(result), key, val);
515 } else {
516 if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), val)) {
517 zend_throw_error(NULL,
518 "Cannot add element to the array as the next element is already occupied");
519 return FAILURE;
520 }
521 }
522 Z_TRY_ADDREF_P(val);
523 } ZEND_HASH_FOREACH_END();
524 return SUCCESS;
525 }
526
527 zend_throw_error(NULL, "Only arrays can be unpacked in constant expression");
528 return FAILURE;
529 }
530
zend_ast_fetch_class(zend_ast * ast,zend_class_entry * scope)531 static zend_class_entry *zend_ast_fetch_class(zend_ast *ast, zend_class_entry *scope)
532 {
533 return zend_fetch_class_with_scope(zend_ast_get_str(ast), (ast->attr >> ZEND_CONST_EXPR_NEW_FETCH_TYPE_SHIFT) | ZEND_FETCH_CLASS_EXCEPTION, scope);
534 }
535
536 ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
537 zval *result,
538 zend_ast *ast,
539 zend_class_entry *scope,
540 bool *short_circuited_ptr,
541 zend_ast_evaluate_ctx *ctx
542 );
543
zend_ast_evaluate_ex(zval * result,zend_ast * ast,zend_class_entry * scope,bool * short_circuited_ptr,zend_ast_evaluate_ctx * ctx)544 ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_ex(
545 zval *result,
546 zend_ast *ast,
547 zend_class_entry *scope,
548 bool *short_circuited_ptr,
549 zend_ast_evaluate_ctx *ctx
550 ) {
551 zend_string *previous_filename;
552 zend_long previous_lineno;
553 if (scope) {
554 previous_filename = EG(filename_override);
555 previous_lineno = EG(lineno_override);
556 EG(filename_override) = scope->info.user.filename;
557 EG(lineno_override) = zend_ast_get_lineno(ast);
558 }
559 zend_result r = zend_ast_evaluate_inner(result, ast, scope, short_circuited_ptr, ctx);
560 if (scope) {
561 EG(filename_override) = previous_filename;
562 EG(lineno_override) = previous_lineno;
563 }
564 return r;
565 }
566
zend_ast_evaluate_inner(zval * result,zend_ast * ast,zend_class_entry * scope,bool * short_circuited_ptr,zend_ast_evaluate_ctx * ctx)567 ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
568 zval *result,
569 zend_ast *ast,
570 zend_class_entry *scope,
571 bool *short_circuited_ptr,
572 zend_ast_evaluate_ctx *ctx
573 ) {
574 zval op1, op2;
575 zend_result ret = SUCCESS;
576 bool short_circuited;
577 *short_circuited_ptr = false;
578
579 switch (ast->kind) {
580 case ZEND_AST_BINARY_OP:
581 if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
582 ret = FAILURE;
583 } else if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
584 zval_ptr_dtor_nogc(&op1);
585 ret = FAILURE;
586 } else {
587 binary_op_type op = get_binary_op(ast->attr);
588 ret = op(result, &op1, &op2);
589 zval_ptr_dtor_nogc(&op1);
590 zval_ptr_dtor_nogc(&op2);
591 }
592 break;
593 case ZEND_AST_GREATER:
594 case ZEND_AST_GREATER_EQUAL:
595 if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
596 ret = FAILURE;
597 } else if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
598 zval_ptr_dtor_nogc(&op1);
599 ret = FAILURE;
600 } else {
601 /* op1 > op2 is the same as op2 < op1 */
602 binary_op_type op = ast->kind == ZEND_AST_GREATER
603 ? is_smaller_function : is_smaller_or_equal_function;
604 ret = op(result, &op2, &op1);
605 zval_ptr_dtor_nogc(&op1);
606 zval_ptr_dtor_nogc(&op2);
607 }
608 break;
609 case ZEND_AST_UNARY_OP:
610 if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
611 ret = FAILURE;
612 } else {
613 unary_op_type op = get_unary_op(ast->attr);
614 ret = op(result, &op1);
615 zval_ptr_dtor_nogc(&op1);
616 }
617 break;
618 case ZEND_AST_ZVAL:
619 {
620 zval *zv = zend_ast_get_zval(ast);
621
622 ZVAL_COPY(result, zv);
623 break;
624 }
625 case ZEND_AST_CONSTANT:
626 {
627 zend_string *name = zend_ast_get_constant_name(ast);
628 zval *zv = zend_get_constant_ex(name, scope, ast->attr);
629
630 if (UNEXPECTED(zv == NULL)) {
631 ZVAL_UNDEF(result);
632 return FAILURE;
633 }
634 ZVAL_COPY_OR_DUP(result, zv);
635 break;
636 }
637 case ZEND_AST_CONSTANT_CLASS:
638 if (scope) {
639 ZVAL_STR_COPY(result, scope->name);
640 } else {
641 ZVAL_EMPTY_STRING(result);
642 }
643 break;
644 case ZEND_AST_CLASS_NAME:
645 if (!scope) {
646 zend_throw_error(NULL, "Cannot use \"self\" when no class scope is active");
647 return FAILURE;
648 }
649 if (ast->attr == ZEND_FETCH_CLASS_SELF) {
650 ZVAL_STR_COPY(result, scope->name);
651 } else if (ast->attr == ZEND_FETCH_CLASS_PARENT) {
652 if (!scope->parent) {
653 zend_throw_error(NULL,
654 "Cannot use \"parent\" when current class scope has no parent");
655 return FAILURE;
656 }
657 ZVAL_STR_COPY(result, scope->parent->name);
658 } else {
659 ZEND_ASSERT(0 && "Should have errored during compilation");
660 }
661 break;
662 case ZEND_AST_AND:
663 if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
664 ret = FAILURE;
665 break;
666 }
667 if (zend_is_true(&op1)) {
668 if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
669 zval_ptr_dtor_nogc(&op1);
670 ret = FAILURE;
671 break;
672 }
673 ZVAL_BOOL(result, zend_is_true(&op2));
674 zval_ptr_dtor_nogc(&op2);
675 } else {
676 ZVAL_FALSE(result);
677 }
678 zval_ptr_dtor_nogc(&op1);
679 break;
680 case ZEND_AST_OR:
681 if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
682 ret = FAILURE;
683 break;
684 }
685 if (zend_is_true(&op1)) {
686 ZVAL_TRUE(result);
687 } else {
688 if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
689 zval_ptr_dtor_nogc(&op1);
690 ret = FAILURE;
691 break;
692 }
693 ZVAL_BOOL(result, zend_is_true(&op2));
694 zval_ptr_dtor_nogc(&op2);
695 }
696 zval_ptr_dtor_nogc(&op1);
697 break;
698 case ZEND_AST_CONDITIONAL:
699 if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
700 ret = FAILURE;
701 break;
702 }
703 if (zend_is_true(&op1)) {
704 if (!ast->child[1]) {
705 *result = op1;
706 } else {
707 if (UNEXPECTED(zend_ast_evaluate_ex(result, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
708 zval_ptr_dtor_nogc(&op1);
709 ret = FAILURE;
710 break;
711 }
712 zval_ptr_dtor_nogc(&op1);
713 }
714 } else {
715 if (UNEXPECTED(zend_ast_evaluate_ex(result, ast->child[2], scope, &short_circuited, ctx) != SUCCESS)) {
716 zval_ptr_dtor_nogc(&op1);
717 ret = FAILURE;
718 break;
719 }
720 zval_ptr_dtor_nogc(&op1);
721 }
722 break;
723 case ZEND_AST_COALESCE:
724 if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
725 ret = FAILURE;
726 break;
727 }
728 if (Z_TYPE(op1) > IS_NULL) {
729 *result = op1;
730 } else {
731 if (UNEXPECTED(zend_ast_evaluate_ex(result, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
732 zval_ptr_dtor_nogc(&op1);
733 ret = FAILURE;
734 break;
735 }
736 zval_ptr_dtor_nogc(&op1);
737 }
738 break;
739 case ZEND_AST_UNARY_PLUS:
740 if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
741 ret = FAILURE;
742 } else {
743 ZVAL_LONG(&op1, 0);
744 ret = add_function(result, &op1, &op2);
745 zval_ptr_dtor_nogc(&op2);
746 }
747 break;
748 case ZEND_AST_UNARY_MINUS:
749 if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
750 ret = FAILURE;
751 } else {
752 ZVAL_LONG(&op1, -1);
753 ret = mul_function(result, &op1, &op2);
754 zval_ptr_dtor_nogc(&op2);
755 }
756 break;
757 case ZEND_AST_ARRAY:
758 {
759 uint32_t i;
760 zend_ast_list *list = zend_ast_get_list(ast);
761
762 if (!list->children) {
763 ZVAL_EMPTY_ARRAY(result);
764 break;
765 }
766 array_init(result);
767 for (i = 0; i < list->children; i++) {
768 zend_ast *elem = list->child[i];
769 if (elem->kind == ZEND_AST_UNPACK) {
770 if (UNEXPECTED(zend_ast_evaluate_ex(&op1, elem->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
771 zval_ptr_dtor_nogc(result);
772 return FAILURE;
773 }
774 if (UNEXPECTED(zend_ast_add_unpacked_element(result, &op1) != SUCCESS)) {
775 zval_ptr_dtor_nogc(&op1);
776 zval_ptr_dtor_nogc(result);
777 return FAILURE;
778 }
779 zval_ptr_dtor_nogc(&op1);
780 continue;
781 }
782 if (elem->child[1]) {
783 if (UNEXPECTED(zend_ast_evaluate_ex(&op1, elem->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
784 zval_ptr_dtor_nogc(result);
785 return FAILURE;
786 }
787 } else {
788 ZVAL_UNDEF(&op1);
789 }
790 if (UNEXPECTED(zend_ast_evaluate_ex(&op2, elem->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
791 zval_ptr_dtor_nogc(&op1);
792 zval_ptr_dtor_nogc(result);
793 return FAILURE;
794 }
795 if (UNEXPECTED(zend_ast_add_array_element(result, &op1, &op2) != SUCCESS)) {
796 zval_ptr_dtor_nogc(&op1);
797 zval_ptr_dtor_nogc(&op2);
798 zval_ptr_dtor_nogc(result);
799 return FAILURE;
800 }
801 }
802 }
803 break;
804 case ZEND_AST_DIM:
805 if (ast->child[1] == NULL) {
806 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
807 }
808
809 if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
810 ret = FAILURE;
811 break;
812 }
813 if (short_circuited) {
814 *short_circuited_ptr = true;
815 ZVAL_NULL(result);
816 return SUCCESS;
817 }
818
819 // DIM on objects is disallowed because it allows executing arbitrary expressions
820 if (Z_TYPE(op1) == IS_OBJECT) {
821 zval_ptr_dtor_nogc(&op1);
822 zend_throw_error(NULL, "Cannot use [] on objects in constant expression");
823 ret = FAILURE;
824 break;
825 }
826
827 if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
828 zval_ptr_dtor_nogc(&op1);
829 ret = FAILURE;
830 break;
831 }
832
833 zend_fetch_dimension_const(result, &op1, &op2, (ast->attr & ZEND_DIM_IS) ? BP_VAR_IS : BP_VAR_R);
834
835 zval_ptr_dtor_nogc(&op1);
836 zval_ptr_dtor_nogc(&op2);
837 if (UNEXPECTED(EG(exception))) {
838 return FAILURE;
839 }
840
841 break;
842 case ZEND_AST_CONST_ENUM_INIT:
843 {
844 // Preloading will attempt to resolve constants but objects can't be stored in shm
845 // Aborting here to store the const AST instead
846 if (CG(in_compilation)) {
847 return FAILURE;
848 }
849
850 zend_ast *class_name_ast = ast->child[0];
851 zend_string *class_name = zend_ast_get_str(class_name_ast);
852
853 zend_ast *case_name_ast = ast->child[1];
854 zend_string *case_name = zend_ast_get_str(case_name_ast);
855
856 zend_ast *case_value_ast = ast->child[2];
857
858 zval case_value_zv;
859 ZVAL_UNDEF(&case_value_zv);
860 if (case_value_ast != NULL) {
861 if (UNEXPECTED(zend_ast_evaluate_ex(&case_value_zv, case_value_ast, scope, &short_circuited, ctx) != SUCCESS)) {
862 return FAILURE;
863 }
864 }
865
866 zend_class_entry *ce = zend_lookup_class(class_name);
867 zend_enum_new(result, ce, case_name, case_value_ast != NULL ? &case_value_zv : NULL);
868 zval_ptr_dtor_nogc(&case_value_zv);
869 break;
870 }
871 case ZEND_AST_CLASS_CONST:
872 {
873 zend_string *class_name = zend_ast_get_str(ast->child[0]);
874 if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
875 return FAILURE;
876 }
877 if (UNEXPECTED(Z_TYPE(op2) != IS_STRING)) {
878 zend_invalid_class_constant_type_error(Z_TYPE(op2));
879 zval_ptr_dtor_nogc(&op2);
880 return FAILURE;
881 }
882 zend_string *const_name = Z_STR(op2);
883
884 zend_string *previous_filename;
885 zend_long previous_lineno;
886 if (scope) {
887 previous_filename = EG(filename_override);
888 previous_lineno = EG(lineno_override);
889 EG(filename_override) = scope->info.user.filename;
890 EG(lineno_override) = zend_ast_get_lineno(ast);
891 }
892 zval *zv = zend_get_class_constant_ex(class_name, const_name, scope, ast->attr);
893 if (scope) {
894 EG(filename_override) = previous_filename;
895 EG(lineno_override) = previous_lineno;
896 }
897
898 if (UNEXPECTED(zv == NULL)) {
899 ZVAL_UNDEF(result);
900 zval_ptr_dtor_nogc(&op2);
901 return FAILURE;
902 }
903 ZVAL_COPY_OR_DUP(result, zv);
904 zval_ptr_dtor_nogc(&op2);
905 break;
906 }
907 case ZEND_AST_NEW:
908 {
909 zend_class_entry *ce = zend_ast_fetch_class(ast->child[0], scope);
910 if (!ce) {
911 return FAILURE;
912 }
913
914 if (object_init_ex(result, ce) != SUCCESS) {
915 return FAILURE;
916 }
917
918 /* Even if there is no constructor, the object can have cause side-effects in various ways (__toString(), __get(), __isset(), etc). */
919 ctx->had_side_effects = true;
920
921 zend_ast_list *args_ast = zend_ast_get_list(ast->child[1]);
922 if (args_ast->attr) {
923 /* Has named arguments. */
924 HashTable *args = zend_new_array(args_ast->children);
925 for (uint32_t i = 0; i < args_ast->children; i++) {
926 zend_ast *arg_ast = args_ast->child[i];
927 zend_string *name = NULL;
928 zval arg;
929 if (arg_ast->kind == ZEND_AST_NAMED_ARG) {
930 name = zend_ast_get_str(arg_ast->child[0]);
931 arg_ast = arg_ast->child[1];
932 }
933 if (zend_ast_evaluate_ex(&arg, arg_ast, scope, &short_circuited, ctx) == FAILURE) {
934 zend_array_destroy(args);
935 zval_ptr_dtor(result);
936 return FAILURE;
937 }
938 if (name) {
939 if (!zend_hash_add(args, name, &arg)) {
940 zend_throw_error(NULL,
941 "Named parameter $%s overwrites previous argument",
942 ZSTR_VAL(name));
943 zend_array_destroy(args);
944 zval_ptr_dtor(result);
945 return FAILURE;
946 }
947 } else {
948 zend_hash_next_index_insert(args, &arg);
949 }
950 }
951
952 zend_function *ctor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
953 if (ctor) {
954 zend_call_known_function(
955 ctor, Z_OBJ_P(result), Z_OBJCE_P(result), NULL, 0, NULL, args);
956 }
957
958 zend_array_destroy(args);
959 } else {
960 ALLOCA_FLAG(use_heap)
961 zval *args = do_alloca(sizeof(zval) * args_ast->children, use_heap);
962 for (uint32_t i = 0; i < args_ast->children; i++) {
963 if (zend_ast_evaluate_ex(&args[i], args_ast->child[i], scope, &short_circuited, ctx) == FAILURE) {
964 for (uint32_t j = 0; j < i; j++) {
965 zval_ptr_dtor(&args[j]);
966 }
967 free_alloca(args, use_heap);
968 zval_ptr_dtor(result);
969 return FAILURE;
970 }
971 }
972
973 zend_function *ctor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
974 if (ctor) {
975 zend_call_known_instance_method(
976 ctor, Z_OBJ_P(result), NULL, args_ast->children, args);
977 }
978
979 for (uint32_t i = 0; i < args_ast->children; i++) {
980 zval_ptr_dtor(&args[i]);
981 }
982 free_alloca(args, use_heap);
983 }
984
985 if (EG(exception)) {
986 zend_object_store_ctor_failed(Z_OBJ_P(result));
987 zval_ptr_dtor(result);
988 return FAILURE;
989 }
990 return SUCCESS;
991 }
992 case ZEND_AST_PROP:
993 case ZEND_AST_NULLSAFE_PROP:
994 {
995 if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
996 return FAILURE;
997 }
998 if (short_circuited) {
999 *short_circuited_ptr = true;
1000 ZVAL_NULL(result);
1001 return SUCCESS;
1002 }
1003 if (ast->kind == ZEND_AST_NULLSAFE_PROP && Z_TYPE(op1) == IS_NULL) {
1004 *short_circuited_ptr = true;
1005 ZVAL_NULL(result);
1006 return SUCCESS;
1007 }
1008
1009 if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
1010 zval_ptr_dtor_nogc(&op1);
1011 return FAILURE;
1012 }
1013
1014 if (!try_convert_to_string(&op2)) {
1015 zval_ptr_dtor_nogc(&op1);
1016 zval_ptr_dtor_nogc(&op2);
1017 return FAILURE;
1018 }
1019
1020 if (Z_TYPE(op1) != IS_OBJECT) {
1021 zend_wrong_property_read(&op1, &op2);
1022
1023 zval_ptr_dtor_nogc(&op1);
1024 zval_ptr_dtor_nogc(&op2);
1025
1026 ZVAL_NULL(result);
1027 return SUCCESS;
1028 }
1029
1030 zend_object *zobj = Z_OBJ(op1);
1031 if (!(zobj->ce->ce_flags & ZEND_ACC_ENUM)) {
1032 zend_throw_error(NULL, "Fetching properties on non-enums in constant expressions is not allowed");
1033 zval_ptr_dtor_nogc(&op1);
1034 zval_ptr_dtor_nogc(&op2);
1035 return FAILURE;
1036 }
1037
1038 zend_string *name = Z_STR(op2);
1039 zval *property_result = zend_read_property_ex(scope, zobj, name, 0, result);
1040 if (EG(exception)) {
1041 zval_ptr_dtor_nogc(&op1);
1042 zval_ptr_dtor_nogc(&op2);
1043 return FAILURE;
1044 }
1045
1046 if (result != property_result) {
1047 ZVAL_COPY(result, property_result);
1048 }
1049 zval_ptr_dtor_nogc(&op1);
1050 zval_ptr_dtor_nogc(&op2);
1051 return SUCCESS;
1052 }
1053 default:
1054 zend_throw_error(NULL, "Unsupported constant expression");
1055 ret = FAILURE;
1056 }
1057 return ret;
1058 }
1059
zend_ast_evaluate(zval * result,zend_ast * ast,zend_class_entry * scope)1060 ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope)
1061 {
1062 zend_ast_evaluate_ctx ctx = {0};
1063 bool short_circuited;
1064 return zend_ast_evaluate_ex(result, ast, scope, &short_circuited, &ctx);
1065 }
1066
zend_ast_tree_size(zend_ast * ast)1067 static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast)
1068 {
1069 size_t size;
1070
1071 if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
1072 size = sizeof(zend_ast_zval);
1073 } else if (zend_ast_is_list(ast)) {
1074 uint32_t i;
1075 zend_ast_list *list = zend_ast_get_list(ast);
1076
1077 size = zend_ast_list_size(list->children);
1078 for (i = 0; i < list->children; i++) {
1079 if (list->child[i]) {
1080 size += zend_ast_tree_size(list->child[i]);
1081 }
1082 }
1083 } else {
1084 uint32_t i, children = zend_ast_get_num_children(ast);
1085
1086 size = zend_ast_size(children);
1087 for (i = 0; i < children; i++) {
1088 if (ast->child[i]) {
1089 size += zend_ast_tree_size(ast->child[i]);
1090 }
1091 }
1092 }
1093 return size;
1094 }
1095
zend_ast_tree_copy(zend_ast * ast,void * buf)1096 static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
1097 {
1098 if (ast->kind == ZEND_AST_ZVAL) {
1099 zend_ast_zval *new = (zend_ast_zval*)buf;
1100 new->kind = ZEND_AST_ZVAL;
1101 new->attr = ast->attr;
1102 ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
1103 Z_LINENO(new->val) = zend_ast_get_lineno(ast);
1104 buf = (void*)((char*)buf + sizeof(zend_ast_zval));
1105 } else if (ast->kind == ZEND_AST_CONSTANT) {
1106 zend_ast_zval *new = (zend_ast_zval*)buf;
1107 new->kind = ZEND_AST_CONSTANT;
1108 new->attr = ast->attr;
1109 ZVAL_STR_COPY(&new->val, zend_ast_get_constant_name(ast));
1110 Z_LINENO(new->val) = zend_ast_get_lineno(ast);
1111 buf = (void*)((char*)buf + sizeof(zend_ast_zval));
1112 } else if (zend_ast_is_list(ast)) {
1113 zend_ast_list *list = zend_ast_get_list(ast);
1114 zend_ast_list *new = (zend_ast_list*)buf;
1115 uint32_t i;
1116 new->kind = list->kind;
1117 new->attr = list->attr;
1118 new->children = list->children;
1119 new->lineno = list->lineno;
1120 buf = (void*)((char*)buf + zend_ast_list_size(list->children));
1121 for (i = 0; i < list->children; i++) {
1122 if (list->child[i]) {
1123 new->child[i] = (zend_ast*)buf;
1124 buf = zend_ast_tree_copy(list->child[i], buf);
1125 } else {
1126 new->child[i] = NULL;
1127 }
1128 }
1129 } else {
1130 uint32_t i, children = zend_ast_get_num_children(ast);
1131 zend_ast *new = (zend_ast*)buf;
1132 new->kind = ast->kind;
1133 new->attr = ast->attr;
1134 new->lineno = ast->lineno;
1135 buf = (void*)((char*)buf + zend_ast_size(children));
1136 for (i = 0; i < children; i++) {
1137 if (ast->child[i]) {
1138 new->child[i] = (zend_ast*)buf;
1139 buf = zend_ast_tree_copy(ast->child[i], buf);
1140 } else {
1141 new->child[i] = NULL;
1142 }
1143 }
1144 }
1145 return buf;
1146 }
1147
zend_ast_copy(zend_ast * ast)1148 ZEND_API zend_ast_ref * ZEND_FASTCALL zend_ast_copy(zend_ast *ast)
1149 {
1150 size_t tree_size;
1151 zend_ast_ref *ref;
1152
1153 ZEND_ASSERT(ast != NULL);
1154 tree_size = zend_ast_tree_size(ast) + sizeof(zend_ast_ref);
1155 ref = emalloc(tree_size);
1156 zend_ast_tree_copy(ast, GC_AST(ref));
1157 GC_SET_REFCOUNT(ref, 1);
1158 GC_TYPE_INFO(ref) = GC_CONSTANT_AST;
1159 return ref;
1160 }
1161
zend_ast_destroy(zend_ast * ast)1162 ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast)
1163 {
1164 tail_call:
1165 if (!ast) {
1166 return;
1167 }
1168
1169 if (EXPECTED(ast->kind >= ZEND_AST_VAR)) {
1170 uint32_t i, children = zend_ast_get_num_children(ast);
1171
1172 for (i = 1; i < children; i++) {
1173 zend_ast_destroy(ast->child[i]);
1174 }
1175 ast = ast->child[0];
1176 goto tail_call;
1177 } else if (EXPECTED(ast->kind == ZEND_AST_ZVAL)) {
1178 zval_ptr_dtor_nogc(zend_ast_get_zval(ast));
1179 } else if (EXPECTED(zend_ast_is_list(ast))) {
1180 zend_ast_list *list = zend_ast_get_list(ast);
1181 if (list->children) {
1182 uint32_t i;
1183
1184 for (i = 1; i < list->children; i++) {
1185 zend_ast_destroy(list->child[i]);
1186 }
1187 ast = list->child[0];
1188 goto tail_call;
1189 }
1190 } else if (EXPECTED(ast->kind == ZEND_AST_CONSTANT)) {
1191 zend_string_release_ex(zend_ast_get_constant_name(ast), 0);
1192 } else if (EXPECTED(ast->kind >= ZEND_AST_FUNC_DECL)) {
1193 zend_ast_decl *decl = (zend_ast_decl *) ast;
1194
1195 if (decl->name) {
1196 zend_string_release_ex(decl->name, 0);
1197 }
1198 if (decl->doc_comment) {
1199 zend_string_release_ex(decl->doc_comment, 0);
1200 }
1201 zend_ast_destroy(decl->child[0]);
1202 zend_ast_destroy(decl->child[1]);
1203 zend_ast_destroy(decl->child[2]);
1204 zend_ast_destroy(decl->child[3]);
1205 ast = decl->child[4];
1206 goto tail_call;
1207 }
1208 }
1209
zend_ast_ref_destroy(zend_ast_ref * ast)1210 ZEND_API void ZEND_FASTCALL zend_ast_ref_destroy(zend_ast_ref *ast)
1211 {
1212 zend_ast_destroy(GC_AST(ast));
1213 efree(ast);
1214 }
1215
zend_ast_apply(zend_ast * ast,zend_ast_apply_func fn,void * context)1216 ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn, void *context) {
1217 if (zend_ast_is_list(ast)) {
1218 zend_ast_list *list = zend_ast_get_list(ast);
1219 uint32_t i;
1220 for (i = 0; i < list->children; ++i) {
1221 fn(&list->child[i], context);
1222 }
1223 } else {
1224 uint32_t i, children = zend_ast_get_num_children(ast);
1225 for (i = 0; i < children; ++i) {
1226 fn(&ast->child[i], context);
1227 }
1228 }
1229 }
1230
1231 /*
1232 * Operator Precedence
1233 * ====================
1234 * priority associativity operators
1235 * ----------------------------------
1236 * 10 left include, include_once, eval, require, require_once
1237 * 20 left ,
1238 * 30 left or
1239 * 40 left xor
1240 * 50 left and
1241 * 60 right print
1242 * 70 right yield
1243 * 80 right =>
1244 * 85 right yield from
1245 * 90 right = += -= *= /= .= %= &= |= ^= <<= >>= **=
1246 * 100 left ? :
1247 * 110 right ??
1248 * 120 left ||
1249 * 130 left &&
1250 * 140 left |
1251 * 150 left ^
1252 * 160 left &
1253 * 170 non-associative == != === !==
1254 * 180 non-associative < <= > >= <=>
1255 * 185 left .
1256 * 190 left << >>
1257 * 200 left + -
1258 * 210 left * / %
1259 * 220 right !
1260 * 230 non-associative instanceof
1261 * 240 right + - ++ -- ~ (type) @
1262 * 250 right **
1263 * 260 left [
1264 * 270 non-associative clone new
1265 */
1266
1267 static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent);
1268
zend_ast_export_str(smart_str * str,zend_string * s)1269 static ZEND_COLD void zend_ast_export_str(smart_str *str, zend_string *s)
1270 {
1271 size_t i;
1272
1273 for (i = 0; i < ZSTR_LEN(s); i++) {
1274 unsigned char c = ZSTR_VAL(s)[i];
1275 if (c == '\'' || c == '\\') {
1276 smart_str_appendc(str, '\\');
1277 smart_str_appendc(str, c);
1278 } else {
1279 smart_str_appendc(str, c);
1280 }
1281 }
1282 }
1283
zend_ast_export_qstr(smart_str * str,char quote,zend_string * s)1284 static ZEND_COLD void zend_ast_export_qstr(smart_str *str, char quote, zend_string *s)
1285 {
1286 size_t i;
1287
1288 for (i = 0; i < ZSTR_LEN(s); i++) {
1289 unsigned char c = ZSTR_VAL(s)[i];
1290 if (c < ' ') {
1291 switch (c) {
1292 case '\n':
1293 smart_str_appends(str, "\\n");
1294 break;
1295 case '\r':
1296 smart_str_appends(str, "\\r");
1297 break;
1298 case '\t':
1299 smart_str_appends(str, "\\t");
1300 break;
1301 case '\f':
1302 smart_str_appends(str, "\\f");
1303 break;
1304 case '\v':
1305 smart_str_appends(str, "\\v");
1306 break;
1307 #ifdef ZEND_WIN32
1308 case VK_ESCAPE:
1309 #else
1310 case '\e':
1311 #endif
1312 smart_str_appends(str, "\\e");
1313 break;
1314 default:
1315 smart_str_appends(str, "\\0");
1316 smart_str_appendc(str, '0' + (c / 8));
1317 smart_str_appendc(str, '0' + (c % 8));
1318 break;
1319 }
1320 } else {
1321 if (c == quote || c == '$' || c == '\\') {
1322 smart_str_appendc(str, '\\');
1323 }
1324 smart_str_appendc(str, c);
1325 }
1326 }
1327 }
1328
zend_ast_export_indent(smart_str * str,int indent)1329 static ZEND_COLD void zend_ast_export_indent(smart_str *str, int indent)
1330 {
1331 while (indent > 0) {
1332 smart_str_appends(str, " ");
1333 indent--;
1334 }
1335 }
1336
zend_ast_export_name(smart_str * str,zend_ast * ast,int priority,int indent)1337 static ZEND_COLD void zend_ast_export_name(smart_str *str, zend_ast *ast, int priority, int indent)
1338 {
1339 if (ast->kind == ZEND_AST_ZVAL) {
1340 zval *zv = zend_ast_get_zval(ast);
1341
1342 if (Z_TYPE_P(zv) == IS_STRING) {
1343 smart_str_append(str, Z_STR_P(zv));
1344 return;
1345 }
1346 }
1347 zend_ast_export_ex(str, ast, priority, indent);
1348 }
1349
zend_ast_export_ns_name(smart_str * str,zend_ast * ast,int priority,int indent)1350 static ZEND_COLD void zend_ast_export_ns_name(smart_str *str, zend_ast *ast, int priority, int indent)
1351 {
1352 if (ast->kind == ZEND_AST_ZVAL) {
1353 zval *zv = zend_ast_get_zval(ast);
1354
1355 if (Z_TYPE_P(zv) == IS_STRING) {
1356 if (ast->attr == ZEND_NAME_FQ) {
1357 smart_str_appendc(str, '\\');
1358 } else if (ast->attr == ZEND_NAME_RELATIVE) {
1359 smart_str_appends(str, "namespace\\");
1360 }
1361 smart_str_append(str, Z_STR_P(zv));
1362 return;
1363 }
1364 }
1365 zend_ast_export_ex(str, ast, priority, indent);
1366 }
1367
zend_ast_valid_var_char(char ch)1368 static ZEND_COLD bool zend_ast_valid_var_char(char ch)
1369 {
1370 unsigned char c = (unsigned char)ch;
1371
1372 if (c != '_' && c < 127 &&
1373 (c < '0' || c > '9') &&
1374 (c < 'A' || c > 'Z') &&
1375 (c < 'a' || c > 'z')) {
1376 return 0;
1377 }
1378 return 1;
1379 }
1380
zend_ast_valid_var_name(const char * s,size_t len)1381 static ZEND_COLD bool zend_ast_valid_var_name(const char *s, size_t len)
1382 {
1383 unsigned char c;
1384 size_t i;
1385
1386 if (len == 0) {
1387 return 0;
1388 }
1389 c = (unsigned char)s[0];
1390 if (c != '_' && c < 127 &&
1391 (c < 'A' || c > 'Z') &&
1392 (c < 'a' || c > 'z')) {
1393 return 0;
1394 }
1395 for (i = 1; i < len; i++) {
1396 c = (unsigned char)s[i];
1397 if (c != '_' && c < 127 &&
1398 (c < '0' || c > '9') &&
1399 (c < 'A' || c > 'Z') &&
1400 (c < 'a' || c > 'z')) {
1401 return 0;
1402 }
1403 }
1404 return 1;
1405 }
1406
zend_ast_var_needs_braces(char ch)1407 static ZEND_COLD bool zend_ast_var_needs_braces(char ch)
1408 {
1409 return ch == '[' || zend_ast_valid_var_char(ch);
1410 }
1411
zend_ast_export_var(smart_str * str,zend_ast * ast,int priority,int indent)1412 static ZEND_COLD void zend_ast_export_var(smart_str *str, zend_ast *ast, int priority, int indent)
1413 {
1414 if (ast->kind == ZEND_AST_ZVAL) {
1415 zval *zv = zend_ast_get_zval(ast);
1416 if (Z_TYPE_P(zv) == IS_STRING &&
1417 zend_ast_valid_var_name(Z_STRVAL_P(zv), Z_STRLEN_P(zv))) {
1418 smart_str_append(str, Z_STR_P(zv));
1419 return;
1420 }
1421 } else if (ast->kind == ZEND_AST_VAR) {
1422 zend_ast_export_ex(str, ast, 0, indent);
1423 return;
1424 }
1425 smart_str_appendc(str, '{');
1426 zend_ast_export_name(str, ast, 0, indent);
1427 smart_str_appendc(str, '}');
1428 }
1429
zend_ast_export_list(smart_str * str,zend_ast_list * list,bool separator,int priority,int indent)1430 static ZEND_COLD void zend_ast_export_list(smart_str *str, zend_ast_list *list, bool separator, int priority, int indent)
1431 {
1432 uint32_t i = 0;
1433
1434 while (i < list->children) {
1435 if (i != 0 && separator) {
1436 smart_str_appends(str, ", ");
1437 }
1438 zend_ast_export_ex(str, list->child[i], priority, indent);
1439 i++;
1440 }
1441 }
1442
zend_ast_export_encaps_list(smart_str * str,char quote,zend_ast_list * list,int indent)1443 static ZEND_COLD void zend_ast_export_encaps_list(smart_str *str, char quote, zend_ast_list *list, int indent)
1444 {
1445 uint32_t i = 0;
1446 zend_ast *ast;
1447
1448 while (i < list->children) {
1449 ast = list->child[i];
1450 if (ast->kind == ZEND_AST_ZVAL) {
1451 zval *zv = zend_ast_get_zval(ast);
1452
1453 ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
1454 zend_ast_export_qstr(str, quote, Z_STR_P(zv));
1455 } else if (ast->kind == ZEND_AST_VAR &&
1456 ast->child[0]->kind == ZEND_AST_ZVAL &&
1457 (i + 1 == list->children ||
1458 list->child[i + 1]->kind != ZEND_AST_ZVAL ||
1459 !zend_ast_var_needs_braces(
1460 *Z_STRVAL_P(
1461 zend_ast_get_zval(list->child[i + 1]))))) {
1462 zend_ast_export_ex(str, ast, 0, indent);
1463 } else {
1464 smart_str_appendc(str, '{');
1465 zend_ast_export_ex(str, ast, 0, indent);
1466 smart_str_appendc(str, '}');
1467 }
1468 i++;
1469 }
1470 }
1471
zend_ast_export_name_list_ex(smart_str * str,zend_ast_list * list,int indent,const char * separator)1472 static ZEND_COLD void zend_ast_export_name_list_ex(smart_str *str, zend_ast_list *list, int indent, const char *separator)
1473 {
1474 uint32_t i = 0;
1475
1476 while (i < list->children) {
1477 if (i != 0) {
1478 smart_str_appends(str, separator);
1479 }
1480 zend_ast_export_name(str, list->child[i], 0, indent);
1481 i++;
1482 }
1483 }
1484
1485 #define zend_ast_export_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, ", ")
1486 #define zend_ast_export_catch_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, "|")
1487
zend_ast_export_var_list(smart_str * str,zend_ast_list * list,int indent)1488 static ZEND_COLD void zend_ast_export_var_list(smart_str *str, zend_ast_list *list, int indent)
1489 {
1490 uint32_t i = 0;
1491
1492 while (i < list->children) {
1493 if (i != 0) {
1494 smart_str_appends(str, ", ");
1495 }
1496 if (list->child[i]->attr & ZEND_BIND_REF) {
1497 smart_str_appendc(str, '&');
1498 }
1499 smart_str_appendc(str, '$');
1500 zend_ast_export_name(str, list->child[i], 20, indent);
1501 i++;
1502 }
1503 }
1504
zend_ast_export_stmt(smart_str * str,zend_ast * ast,int indent)1505 static ZEND_COLD void zend_ast_export_stmt(smart_str *str, zend_ast *ast, int indent)
1506 {
1507 if (!ast) {
1508 return;
1509 }
1510
1511 if (ast->kind == ZEND_AST_STMT_LIST ||
1512 ast->kind == ZEND_AST_TRAIT_ADAPTATIONS) {
1513 zend_ast_list *list = (zend_ast_list*)ast;
1514 uint32_t i = 0;
1515
1516 while (i < list->children) {
1517 ast = list->child[i];
1518 zend_ast_export_stmt(str, ast, indent);
1519 i++;
1520 }
1521 } else {
1522 zend_ast_export_indent(str, indent);
1523 zend_ast_export_ex(str, ast, 0, indent);
1524 switch (ast->kind) {
1525 case ZEND_AST_LABEL:
1526 case ZEND_AST_IF:
1527 case ZEND_AST_SWITCH:
1528 case ZEND_AST_WHILE:
1529 case ZEND_AST_TRY:
1530 case ZEND_AST_FOR:
1531 case ZEND_AST_FOREACH:
1532 case ZEND_AST_FUNC_DECL:
1533 case ZEND_AST_METHOD:
1534 case ZEND_AST_CLASS:
1535 case ZEND_AST_USE_TRAIT:
1536 case ZEND_AST_NAMESPACE:
1537 case ZEND_AST_DECLARE:
1538 break;
1539 case ZEND_AST_PROP_GROUP: {
1540 zend_ast *first_prop = zend_ast_get_list(ast->child[1])->child[0];
1541 zend_ast *hook_list = first_prop->child[3];
1542 if (hook_list == NULL) {
1543 smart_str_appendc(str, ';');
1544 }
1545 break;
1546 }
1547 default:
1548 smart_str_appendc(str, ';');
1549 break;
1550 }
1551 smart_str_appendc(str, '\n');
1552 }
1553 }
1554
zend_ast_export_if_stmt(smart_str * str,zend_ast_list * list,int indent)1555 static ZEND_COLD void zend_ast_export_if_stmt(smart_str *str, zend_ast_list *list, int indent)
1556 {
1557 uint32_t i;
1558 zend_ast *ast;
1559
1560 tail_call:
1561 i = 0;
1562 while (i < list->children) {
1563 ast = list->child[i];
1564 ZEND_ASSERT(ast->kind == ZEND_AST_IF_ELEM);
1565 if (ast->child[0]) {
1566 if (i == 0) {
1567 smart_str_appends(str, "if (");
1568 } else {
1569 zend_ast_export_indent(str, indent);
1570 smart_str_appends(str, "} elseif (");
1571 }
1572 zend_ast_export_ex(str, ast->child[0], 0, indent);
1573 smart_str_appends(str, ") {\n");
1574 zend_ast_export_stmt(str, ast->child[1], indent + 1);
1575 } else {
1576 zend_ast_export_indent(str, indent);
1577 smart_str_appends(str, "} else ");
1578 if (ast->child[1] && ast->child[1]->kind == ZEND_AST_IF) {
1579 list = (zend_ast_list*)ast->child[1];
1580 goto tail_call;
1581 } else {
1582 smart_str_appends(str, "{\n");
1583 zend_ast_export_stmt(str, ast->child[1], indent + 1);
1584 }
1585 }
1586 i++;
1587 }
1588 zend_ast_export_indent(str, indent);
1589 smart_str_appendc(str, '}');
1590 }
1591
zend_ast_export_zval(smart_str * str,zval * zv,int priority,int indent)1592 static ZEND_COLD void zend_ast_export_zval(smart_str *str, zval *zv, int priority, int indent)
1593 {
1594 ZVAL_DEREF(zv);
1595 switch (Z_TYPE_P(zv)) {
1596 case IS_NULL:
1597 smart_str_appends(str, "null");
1598 break;
1599 case IS_FALSE:
1600 smart_str_appends(str, "false");
1601 break;
1602 case IS_TRUE:
1603 smart_str_appends(str, "true");
1604 break;
1605 case IS_LONG:
1606 smart_str_append_long(str, Z_LVAL_P(zv));
1607 break;
1608 case IS_DOUBLE:
1609 smart_str_append_double(
1610 str, Z_DVAL_P(zv), (int) EG(precision), /* zero_fraction */ false);
1611 break;
1612 case IS_STRING:
1613 smart_str_appendc(str, '\'');
1614 zend_ast_export_str(str, Z_STR_P(zv));
1615 smart_str_appendc(str, '\'');
1616 break;
1617 case IS_ARRAY: {
1618 zend_long idx;
1619 zend_string *key;
1620 zval *val;
1621 bool first = true;
1622 smart_str_appendc(str, '[');
1623 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(zv), idx, key, val) {
1624 if (first) {
1625 first = false;
1626 } else {
1627 smart_str_appends(str, ", ");
1628 }
1629 if (key) {
1630 smart_str_appendc(str, '\'');
1631 zend_ast_export_str(str, key);
1632 smart_str_appends(str, "' => ");
1633 } else {
1634 smart_str_append_long(str, idx);
1635 smart_str_appends(str, " => ");
1636 }
1637 zend_ast_export_zval(str, val, 0, indent);
1638 } ZEND_HASH_FOREACH_END();
1639 smart_str_appendc(str, ']');
1640 break;
1641 }
1642 case IS_CONSTANT_AST:
1643 zend_ast_export_ex(str, Z_ASTVAL_P(zv), priority, indent);
1644 break;
1645 EMPTY_SWITCH_DEFAULT_CASE();
1646 }
1647 }
1648
zend_ast_export_class_no_header(smart_str * str,zend_ast_decl * decl,int indent)1649 static ZEND_COLD void zend_ast_export_class_no_header(smart_str *str, zend_ast_decl *decl, int indent) {
1650 if (decl->child[0]) {
1651 smart_str_appends(str, " extends ");
1652 zend_ast_export_ns_name(str, decl->child[0], 0, indent);
1653 }
1654 if (decl->child[1]) {
1655 smart_str_appends(str, " implements ");
1656 zend_ast_export_ex(str, decl->child[1], 0, indent);
1657 }
1658 smart_str_appends(str, " {\n");
1659 zend_ast_export_stmt(str, decl->child[2], indent + 1);
1660 zend_ast_export_indent(str, indent);
1661 smart_str_appends(str, "}");
1662 }
1663
zend_ast_export_attribute_group(smart_str * str,zend_ast * ast,int indent)1664 static ZEND_COLD void zend_ast_export_attribute_group(smart_str *str, zend_ast *ast, int indent) {
1665 zend_ast_list *list = zend_ast_get_list(ast);
1666 for (uint32_t i = 0; i < list->children; i++) {
1667 zend_ast *attr = list->child[i];
1668
1669 if (i) {
1670 smart_str_appends(str, ", ");
1671 }
1672 zend_ast_export_ns_name(str, attr->child[0], 0, indent);
1673
1674 if (attr->child[1]) {
1675 smart_str_appendc(str, '(');
1676 zend_ast_export_ex(str, attr->child[1], 0, indent);
1677 smart_str_appendc(str, ')');
1678 }
1679 }
1680 }
1681
zend_ast_export_attributes(smart_str * str,zend_ast * ast,int indent,bool newlines)1682 static ZEND_COLD void zend_ast_export_attributes(smart_str *str, zend_ast *ast, int indent, bool newlines) {
1683 zend_ast_list *list = zend_ast_get_list(ast);
1684 uint32_t i;
1685
1686 for (i = 0; i < list->children; i++) {
1687 smart_str_appends(str, "#[");
1688 zend_ast_export_attribute_group(str, list->child[i], indent);
1689 smart_str_appends(str, "]");
1690
1691 if (newlines) {
1692 smart_str_appendc(str, '\n');
1693 zend_ast_export_indent(str, indent);
1694 } else {
1695 smart_str_appendc(str, ' ');
1696 }
1697 }
1698 }
1699
zend_ast_export_visibility(smart_str * str,uint32_t flags,zend_modifier_target target)1700 static ZEND_COLD void zend_ast_export_visibility(smart_str *str, uint32_t flags, zend_modifier_target target) {
1701 if (flags & ZEND_ACC_PUBLIC) {
1702 smart_str_appends(str, "public ");
1703 } else if (flags & ZEND_ACC_PROTECTED) {
1704 smart_str_appends(str, "protected ");
1705 } else if (flags & ZEND_ACC_PRIVATE) {
1706 smart_str_appends(str, "private ");
1707 }
1708
1709 if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
1710 if (flags & ZEND_ACC_PRIVATE_SET) {
1711 smart_str_appends(str, "private(set) ");
1712 } else if (flags & ZEND_ACC_PROTECTED_SET) {
1713 smart_str_appends(str, "protected(set) ");
1714 } else if (flags & ZEND_ACC_PUBLIC_SET) {
1715 smart_str_appends(str, "public(set) ");
1716 }
1717 }
1718 }
1719
zend_ast_export_type(smart_str * str,zend_ast * ast,int indent)1720 static ZEND_COLD void zend_ast_export_type(smart_str *str, zend_ast *ast, int indent) {
1721 if (ast->kind == ZEND_AST_TYPE_UNION) {
1722 zend_ast_list *list = zend_ast_get_list(ast);
1723 for (uint32_t i = 0; i < list->children; i++) {
1724 if (i != 0) {
1725 smart_str_appendc(str, '|');
1726 }
1727 zend_ast_export_type(str, list->child[i], indent);
1728 }
1729 return;
1730 }
1731 if (ast->kind == ZEND_AST_TYPE_INTERSECTION) {
1732 zend_ast_list *list = zend_ast_get_list(ast);
1733 for (uint32_t i = 0; i < list->children; i++) {
1734 if (i != 0) {
1735 smart_str_appendc(str, '&');
1736 }
1737 zend_ast_export_type(str, list->child[i], indent);
1738 }
1739 return;
1740 }
1741 if (ast->attr & ZEND_TYPE_NULLABLE) {
1742 smart_str_appendc(str, '?');
1743 }
1744 zend_ast_export_ns_name(str, ast, 0, indent);
1745 }
1746
1747 #define BINARY_OP(_op, _p, _pl, _pr) do { \
1748 op = _op; \
1749 p = _p; \
1750 pl = _pl; \
1751 pr = _pr; \
1752 goto binary_op; \
1753 } while (0)
1754
1755 #define PREFIX_OP(_op, _p, _pl) do { \
1756 op = _op; \
1757 p = _p; \
1758 pl = _pl; \
1759 goto prefix_op; \
1760 } while (0)
1761
1762 #define FUNC_OP(_op) do { \
1763 op = _op; \
1764 goto func_op; \
1765 } while (0)
1766
1767 #define POSTFIX_OP(_op, _p, _pl) do { \
1768 op = _op; \
1769 p = _p; \
1770 pl = _pl; \
1771 goto postfix_op; \
1772 } while (0)
1773
1774 #define APPEND_NODE_1(_op) do { \
1775 op = _op; \
1776 goto append_node_1; \
1777 } while (0)
1778
1779 #define APPEND_STR(_op) do { \
1780 op = _op; \
1781 goto append_str; \
1782 } while (0)
1783
1784 #define APPEND_DEFAULT_VALUE(n) do { \
1785 p = n; \
1786 goto append_default_value; \
1787 } while (0)
1788
zend_ast_export_ex(smart_str * str,zend_ast * ast,int priority,int indent)1789 static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent)
1790 {
1791 zend_ast_decl *decl;
1792 int p, pl, pr;
1793 const char *op;
1794
1795 tail_call:
1796 if (!ast) {
1797 return;
1798 }
1799 switch (ast->kind) {
1800 /* special nodes */
1801 case ZEND_AST_ZVAL:
1802 zend_ast_export_zval(str, zend_ast_get_zval(ast), priority, indent);
1803 break;
1804 case ZEND_AST_CONSTANT: {
1805 zend_string *name = zend_ast_get_constant_name(ast);
1806 smart_str_appendl(str, ZSTR_VAL(name), ZSTR_LEN(name));
1807 break;
1808 }
1809 case ZEND_AST_CONSTANT_CLASS:
1810 smart_str_appendl(str, "__CLASS__", sizeof("__CLASS__")-1);
1811 break;
1812 case ZEND_AST_ZNODE:
1813 /* This AST kind is only used for temporary nodes during compilation */
1814 ZEND_UNREACHABLE();
1815 break;
1816
1817 /* declaration nodes */
1818 case ZEND_AST_FUNC_DECL:
1819 case ZEND_AST_CLOSURE:
1820 case ZEND_AST_ARROW_FUNC:
1821 case ZEND_AST_METHOD:
1822 decl = (zend_ast_decl *) ast;
1823 if (decl->child[4]) {
1824 bool newlines = !(ast->kind == ZEND_AST_CLOSURE || ast->kind == ZEND_AST_ARROW_FUNC);
1825 zend_ast_export_attributes(str, decl->child[4], indent, newlines);
1826 }
1827
1828 zend_ast_export_visibility(str, decl->flags, ZEND_MODIFIER_TARGET_METHOD);
1829
1830 if (decl->flags & ZEND_ACC_STATIC) {
1831 smart_str_appends(str, "static ");
1832 }
1833 if (decl->flags & ZEND_ACC_ABSTRACT) {
1834 smart_str_appends(str, "abstract ");
1835 }
1836 if (decl->flags & ZEND_ACC_FINAL) {
1837 smart_str_appends(str, "final ");
1838 }
1839 if (decl->kind == ZEND_AST_ARROW_FUNC) {
1840 smart_str_appends(str, "fn");
1841 } else {
1842 smart_str_appends(str, "function ");
1843 }
1844 if (decl->flags & ZEND_ACC_RETURN_REFERENCE) {
1845 smart_str_appendc(str, '&');
1846 }
1847 if (ast->kind != ZEND_AST_CLOSURE && ast->kind != ZEND_AST_ARROW_FUNC) {
1848 smart_str_appendl(str, ZSTR_VAL(decl->name), ZSTR_LEN(decl->name));
1849 }
1850 smart_str_appendc(str, '(');
1851 zend_ast_export_ex(str, decl->child[0], 0, indent);
1852 smart_str_appendc(str, ')');
1853 zend_ast_export_ex(str, decl->child[1], 0, indent);
1854 if (decl->child[3]) {
1855 smart_str_appends(str, ": ");
1856 zend_ast_export_type(str, decl->child[3], indent);
1857 }
1858 if (decl->child[2]) {
1859 if (decl->kind == ZEND_AST_ARROW_FUNC) {
1860 zend_ast *body = decl->child[2];
1861 if (body->kind == ZEND_AST_RETURN) {
1862 body = body->child[0];
1863 }
1864 smart_str_appends(str, " => ");
1865 zend_ast_export_ex(str, body, 0, indent);
1866 break;
1867 }
1868
1869 smart_str_appends(str, " {\n");
1870 zend_ast_export_stmt(str, decl->child[2], indent + 1);
1871 zend_ast_export_indent(str, indent);
1872 smart_str_appendc(str, '}');
1873 if (ast->kind != ZEND_AST_CLOSURE) {
1874 smart_str_appendc(str, '\n');
1875 }
1876 } else {
1877 smart_str_appends(str, ";\n");
1878 }
1879 break;
1880 case ZEND_AST_CLASS:
1881 decl = (zend_ast_decl *) ast;
1882 if (decl->child[3]) {
1883 zend_ast_export_attributes(str, decl->child[3], indent, 1);
1884 }
1885 if (decl->flags & ZEND_ACC_INTERFACE) {
1886 smart_str_appends(str, "interface ");
1887 } else if (decl->flags & ZEND_ACC_TRAIT) {
1888 smart_str_appends(str, "trait ");
1889 } else if (decl->flags & ZEND_ACC_ENUM) {
1890 smart_str_appends(str, "enum ");
1891 } else {
1892 if (decl->flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
1893 smart_str_appends(str, "abstract ");
1894 }
1895 if (decl->flags & ZEND_ACC_FINAL) {
1896 smart_str_appends(str, "final ");
1897 }
1898 if (decl->flags & ZEND_ACC_READONLY_CLASS) {
1899 smart_str_appends(str, "readonly ");
1900 }
1901 smart_str_appends(str, "class ");
1902 }
1903 smart_str_appendl(str, ZSTR_VAL(decl->name), ZSTR_LEN(decl->name));
1904 if (decl->flags & ZEND_ACC_ENUM && decl->child[4]) {
1905 smart_str_appends(str, ": ");
1906 zend_ast_export_type(str, decl->child[4], indent);
1907 }
1908 zend_ast_export_class_no_header(str, decl, indent);
1909 smart_str_appendc(str, '\n');
1910 break;
1911
1912 /* list nodes */
1913 case ZEND_AST_ARG_LIST:
1914 case ZEND_AST_EXPR_LIST:
1915 case ZEND_AST_PARAM_LIST:
1916 simple_list:
1917 zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
1918 break;
1919 case ZEND_AST_ARRAY:
1920 smart_str_appendc(str, '[');
1921 zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
1922 smart_str_appendc(str, ']');
1923 break;
1924 case ZEND_AST_ENCAPS_LIST:
1925 smart_str_appendc(str, '"');
1926 zend_ast_export_encaps_list(str, '"', (zend_ast_list*)ast, indent);
1927 smart_str_appendc(str, '"');
1928 break;
1929 case ZEND_AST_STMT_LIST:
1930 case ZEND_AST_TRAIT_ADAPTATIONS:
1931 zend_ast_export_stmt(str, ast, indent);
1932 break;
1933 case ZEND_AST_IF:
1934 zend_ast_export_if_stmt(str, (zend_ast_list*)ast, indent);
1935 break;
1936 case ZEND_AST_SWITCH_LIST:
1937 case ZEND_AST_CATCH_LIST:
1938 case ZEND_AST_MATCH_ARM_LIST:
1939 zend_ast_export_list(str, (zend_ast_list*)ast, 0, 0, indent);
1940 break;
1941 case ZEND_AST_CLOSURE_USES:
1942 smart_str_appends(str, " use(");
1943 zend_ast_export_var_list(str, (zend_ast_list*)ast, indent);
1944 smart_str_appendc(str, ')');
1945 break;
1946 case ZEND_AST_PROP_GROUP: {
1947 zend_ast *type_ast = ast->child[0];
1948 zend_ast *prop_ast = ast->child[1];
1949
1950 if (ast->child[2]) {
1951 zend_ast_export_attributes(str, ast->child[2], indent, 1);
1952 }
1953
1954 zend_ast_export_visibility(str, ast->attr, ZEND_MODIFIER_TARGET_PROPERTY);
1955
1956 if (ast->attr & ZEND_ACC_STATIC) {
1957 smart_str_appends(str, "static ");
1958 }
1959 if (ast->attr & ZEND_ACC_READONLY) {
1960 smart_str_appends(str, "readonly ");
1961 }
1962
1963 if (type_ast) {
1964 zend_ast_export_type(str, type_ast, indent);
1965 smart_str_appendc(str, ' ');
1966 }
1967
1968 ast = prop_ast;
1969 goto simple_list;
1970 }
1971
1972 case ZEND_AST_CONST_DECL:
1973 smart_str_appends(str, "const ");
1974 goto simple_list;
1975 case ZEND_AST_CLASS_CONST_GROUP:
1976 if (ast->child[1]) {
1977 zend_ast_export_attributes(str, ast->child[1], indent, 1);
1978 }
1979
1980 zend_ast_export_visibility(str, ast->attr, ZEND_MODIFIER_TARGET_CONSTANT);
1981 smart_str_appends(str, "const ");
1982 if (ast->child[2]) {
1983 zend_ast_export_type(str, ast->child[2], indent);
1984 smart_str_appendc(str, ' ');
1985 }
1986
1987 ast = ast->child[0];
1988
1989 goto simple_list;
1990 case ZEND_AST_NAME_LIST:
1991 zend_ast_export_name_list(str, (zend_ast_list*)ast, indent);
1992 break;
1993 case ZEND_AST_USE:
1994 smart_str_appends(str, "use ");
1995 if (ast->attr == T_FUNCTION) {
1996 smart_str_appends(str, "function ");
1997 } else if (ast->attr == T_CONST) {
1998 smart_str_appends(str, "const ");
1999 }
2000 goto simple_list;
2001
2002 /* 0 child nodes */
2003 case ZEND_AST_MAGIC_CONST:
2004 switch (ast->attr) {
2005 case T_LINE: APPEND_STR("__LINE__");
2006 case T_FILE: APPEND_STR("__FILE__");
2007 case T_DIR: APPEND_STR("__DIR__");
2008 case T_TRAIT_C: APPEND_STR("__TRAIT__");
2009 case T_METHOD_C: APPEND_STR("__METHOD__");
2010 case T_FUNC_C: APPEND_STR("__FUNCTION__");
2011 case T_PROPERTY_C: APPEND_STR("__PROPERTY__");
2012 case T_NS_C: APPEND_STR("__NAMESPACE__");
2013 case T_CLASS_C: APPEND_STR("__CLASS__");
2014 EMPTY_SWITCH_DEFAULT_CASE();
2015 }
2016 break;
2017 case ZEND_AST_TYPE:
2018 switch (ast->attr & ~ZEND_TYPE_NULLABLE) {
2019 case IS_ARRAY: APPEND_STR("array");
2020 case IS_CALLABLE: APPEND_STR("callable");
2021 case IS_STATIC: APPEND_STR("static");
2022 case IS_MIXED: APPEND_STR("mixed");
2023 EMPTY_SWITCH_DEFAULT_CASE();
2024 }
2025 break;
2026
2027 /* 1 child node */
2028 case ZEND_AST_VAR:
2029 smart_str_appendc(str, '$');
2030 zend_ast_export_var(str, ast->child[0], 0, indent);
2031 break;
2032 case ZEND_AST_CONST:
2033 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2034 break;
2035 case ZEND_AST_UNPACK:
2036 smart_str_appends(str, "...");
2037 ast = ast->child[0];
2038 goto tail_call;
2039 case ZEND_AST_UNARY_PLUS: PREFIX_OP("+", 240, 241);
2040 case ZEND_AST_UNARY_MINUS: PREFIX_OP("-", 240, 241);
2041 case ZEND_AST_CAST:
2042 switch (ast->attr) {
2043 case IS_NULL: PREFIX_OP("(unset)", 240, 241);
2044 case _IS_BOOL: PREFIX_OP("(bool)", 240, 241);
2045 case IS_LONG: PREFIX_OP("(int)", 240, 241);
2046 case IS_DOUBLE: PREFIX_OP("(double)", 240, 241);
2047 case IS_STRING: PREFIX_OP("(string)", 240, 241);
2048 case IS_ARRAY: PREFIX_OP("(array)", 240, 241);
2049 case IS_OBJECT: PREFIX_OP("(object)", 240, 241);
2050 EMPTY_SWITCH_DEFAULT_CASE();
2051 }
2052 break;
2053 case ZEND_AST_EMPTY:
2054 FUNC_OP("empty");
2055 case ZEND_AST_ISSET:
2056 FUNC_OP("isset");
2057 case ZEND_AST_SILENCE:
2058 PREFIX_OP("@", 240, 241);
2059 case ZEND_AST_SHELL_EXEC:
2060 smart_str_appendc(str, '`');
2061 if (ast->child[0]->kind == ZEND_AST_ENCAPS_LIST) {
2062 zend_ast_export_encaps_list(str, '`', (zend_ast_list*)ast->child[0], indent);
2063 } else {
2064 zval *zv;
2065 ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_ZVAL);
2066 zv = zend_ast_get_zval(ast->child[0]);
2067 ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
2068 zend_ast_export_qstr(str, '`', Z_STR_P(zv));
2069 }
2070 smart_str_appendc(str, '`');
2071 break;
2072 case ZEND_AST_CLONE:
2073 PREFIX_OP("clone ", 270, 271);
2074 case ZEND_AST_EXIT:
2075 if (ast->child[0]) {
2076 FUNC_OP("exit");
2077 } else {
2078 APPEND_STR("exit");
2079 }
2080 break;
2081 case ZEND_AST_PRINT:
2082 PREFIX_OP("print ", 60, 61);
2083 case ZEND_AST_INCLUDE_OR_EVAL:
2084 switch (ast->attr) {
2085 case ZEND_INCLUDE_ONCE: FUNC_OP("include_once");
2086 case ZEND_INCLUDE: FUNC_OP("include");
2087 case ZEND_REQUIRE_ONCE: FUNC_OP("require_once");
2088 case ZEND_REQUIRE: FUNC_OP("require");
2089 case ZEND_EVAL: FUNC_OP("eval");
2090 EMPTY_SWITCH_DEFAULT_CASE();
2091 }
2092 break;
2093 case ZEND_AST_UNARY_OP:
2094 switch (ast->attr) {
2095 case ZEND_BW_NOT: PREFIX_OP("~", 240, 241);
2096 case ZEND_BOOL_NOT: PREFIX_OP("!", 240, 241);
2097 EMPTY_SWITCH_DEFAULT_CASE();
2098 }
2099 break;
2100 case ZEND_AST_PRE_INC:
2101 PREFIX_OP("++", 240, 241);
2102 case ZEND_AST_PRE_DEC:
2103 PREFIX_OP("--", 240, 241);
2104 case ZEND_AST_POST_INC:
2105 POSTFIX_OP("++", 240, 241);
2106 case ZEND_AST_POST_DEC:
2107 POSTFIX_OP("--", 240, 241);
2108
2109 case ZEND_AST_GLOBAL:
2110 APPEND_NODE_1("global");
2111 case ZEND_AST_UNSET:
2112 FUNC_OP("unset");
2113 case ZEND_AST_RETURN:
2114 APPEND_NODE_1("return");
2115 case ZEND_AST_LABEL:
2116 zend_ast_export_name(str, ast->child[0], 0, indent);
2117 smart_str_appendc(str, ':');
2118 break;
2119 case ZEND_AST_REF:
2120 smart_str_appendc(str, '&');
2121 ast = ast->child[0];
2122 goto tail_call;
2123 case ZEND_AST_HALT_COMPILER:
2124 APPEND_STR("__HALT_COMPILER()");
2125 case ZEND_AST_ECHO:
2126 APPEND_NODE_1("echo");
2127 case ZEND_AST_THROW:
2128 APPEND_NODE_1("throw");
2129 case ZEND_AST_GOTO:
2130 smart_str_appends(str, "goto ");
2131 zend_ast_export_name(str, ast->child[0], 0, indent);
2132 break;
2133 case ZEND_AST_BREAK:
2134 APPEND_NODE_1("break");
2135 case ZEND_AST_CONTINUE:
2136 APPEND_NODE_1("continue");
2137
2138 /* 2 child nodes */
2139 case ZEND_AST_DIM:
2140 zend_ast_export_ex(str, ast->child[0], 260, indent);
2141 smart_str_appendc(str, '[');
2142 if (ast->child[1]) {
2143 zend_ast_export_ex(str, ast->child[1], 0, indent);
2144 }
2145 smart_str_appendc(str, ']');
2146 break;
2147 case ZEND_AST_PROP:
2148 case ZEND_AST_NULLSAFE_PROP:
2149 zend_ast_export_ex(str, ast->child[0], 0, indent);
2150 smart_str_appends(str, ast->kind == ZEND_AST_NULLSAFE_PROP ? "?->" : "->");
2151 zend_ast_export_var(str, ast->child[1], 0, indent);
2152 break;
2153 case ZEND_AST_STATIC_PROP:
2154 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2155 smart_str_appends(str, "::$");
2156 zend_ast_export_var(str, ast->child[1], 0, indent);
2157 break;
2158 case ZEND_AST_CALL:
2159 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2160 smart_str_appendc(str, '(');
2161 zend_ast_export_ex(str, ast->child[1], 0, indent);
2162 smart_str_appendc(str, ')');
2163 break;
2164 case ZEND_AST_PARENT_PROPERTY_HOOK_CALL:
2165 smart_str_append(str, Z_STR_P(zend_ast_get_zval(ast->child[0])));
2166 smart_str_appendc(str, '(');
2167 zend_ast_export_ex(str, ast->child[1], 0, indent);
2168 smart_str_appendc(str, ')');
2169 break;
2170 case ZEND_AST_CALLABLE_CONVERT:
2171 smart_str_appends(str, "...");
2172 break;
2173 case ZEND_AST_CLASS_CONST:
2174 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2175 smart_str_appends(str, "::");
2176 zend_ast_export_name(str, ast->child[1], 0, indent);
2177 break;
2178 case ZEND_AST_CLASS_NAME:
2179 if (ast->child[0] == NULL) {
2180 /* The const expr representation stores the fetch type instead. */
2181 switch (ast->attr) {
2182 case ZEND_FETCH_CLASS_SELF:
2183 smart_str_appends(str, "self");
2184 break;
2185 case ZEND_FETCH_CLASS_PARENT:
2186 smart_str_appends(str, "parent");
2187 break;
2188 EMPTY_SWITCH_DEFAULT_CASE()
2189 }
2190 } else {
2191 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2192 }
2193 smart_str_appends(str, "::class");
2194 break;
2195 case ZEND_AST_ASSIGN: BINARY_OP(" = ", 90, 91, 90);
2196 case ZEND_AST_ASSIGN_REF: BINARY_OP(" =& ", 90, 91, 90);
2197 case ZEND_AST_ASSIGN_OP:
2198 switch (ast->attr) {
2199 case ZEND_ADD: BINARY_OP(" += ", 90, 91, 90);
2200 case ZEND_SUB: BINARY_OP(" -= ", 90, 91, 90);
2201 case ZEND_MUL: BINARY_OP(" *= ", 90, 91, 90);
2202 case ZEND_DIV: BINARY_OP(" /= ", 90, 91, 90);
2203 case ZEND_MOD: BINARY_OP(" %= ", 90, 91, 90);
2204 case ZEND_SL: BINARY_OP(" <<= ", 90, 91, 90);
2205 case ZEND_SR: BINARY_OP(" >>= ", 90, 91, 90);
2206 case ZEND_CONCAT: BINARY_OP(" .= ", 90, 91, 90);
2207 case ZEND_BW_OR: BINARY_OP(" |= ", 90, 91, 90);
2208 case ZEND_BW_AND: BINARY_OP(" &= ", 90, 91, 90);
2209 case ZEND_BW_XOR: BINARY_OP(" ^= ", 90, 91, 90);
2210 case ZEND_POW: BINARY_OP(" **= ", 90, 91, 90);
2211 EMPTY_SWITCH_DEFAULT_CASE();
2212 }
2213 break;
2214 case ZEND_AST_ASSIGN_COALESCE: BINARY_OP(" \?\?= ", 90, 91, 90);
2215 case ZEND_AST_BINARY_OP:
2216 switch (ast->attr) {
2217 case ZEND_ADD: BINARY_OP(" + ", 200, 200, 201);
2218 case ZEND_SUB: BINARY_OP(" - ", 200, 200, 201);
2219 case ZEND_MUL: BINARY_OP(" * ", 210, 210, 211);
2220 case ZEND_DIV: BINARY_OP(" / ", 210, 210, 211);
2221 case ZEND_MOD: BINARY_OP(" % ", 210, 210, 211);
2222 case ZEND_SL: BINARY_OP(" << ", 190, 190, 191);
2223 case ZEND_SR: BINARY_OP(" >> ", 190, 190, 191);
2224 case ZEND_CONCAT: BINARY_OP(" . ", 185, 185, 186);
2225 case ZEND_BW_OR: BINARY_OP(" | ", 140, 140, 141);
2226 case ZEND_BW_AND: BINARY_OP(" & ", 160, 160, 161);
2227 case ZEND_BW_XOR: BINARY_OP(" ^ ", 150, 150, 151);
2228 case ZEND_IS_IDENTICAL: BINARY_OP(" === ", 170, 171, 171);
2229 case ZEND_IS_NOT_IDENTICAL: BINARY_OP(" !== ", 170, 171, 171);
2230 case ZEND_IS_EQUAL: BINARY_OP(" == ", 170, 171, 171);
2231 case ZEND_IS_NOT_EQUAL: BINARY_OP(" != ", 170, 171, 171);
2232 case ZEND_IS_SMALLER: BINARY_OP(" < ", 180, 181, 181);
2233 case ZEND_IS_SMALLER_OR_EQUAL: BINARY_OP(" <= ", 180, 181, 181);
2234 case ZEND_POW: BINARY_OP(" ** ", 250, 251, 250);
2235 case ZEND_BOOL_XOR: BINARY_OP(" xor ", 40, 40, 41);
2236 case ZEND_SPACESHIP: BINARY_OP(" <=> ", 180, 181, 181);
2237 EMPTY_SWITCH_DEFAULT_CASE();
2238 }
2239 break;
2240 case ZEND_AST_GREATER: BINARY_OP(" > ", 180, 181, 181);
2241 case ZEND_AST_GREATER_EQUAL: BINARY_OP(" >= ", 180, 181, 181);
2242 case ZEND_AST_AND: BINARY_OP(" && ", 130, 130, 131);
2243 case ZEND_AST_OR: BINARY_OP(" || ", 120, 120, 121);
2244 case ZEND_AST_ARRAY_ELEM:
2245 if (ast->child[1]) {
2246 zend_ast_export_ex(str, ast->child[1], 80, indent);
2247 smart_str_appends(str, " => ");
2248 }
2249 if (ast->attr)
2250 smart_str_appendc(str, '&');
2251 zend_ast_export_ex(str, ast->child[0], 80, indent);
2252 break;
2253 case ZEND_AST_NEW:
2254 smart_str_appends(str, "new ");
2255 if (ast->child[0]->kind == ZEND_AST_CLASS) {
2256 zend_ast_decl *decl = (zend_ast_decl *) ast->child[0];
2257 if (decl->child[3]) {
2258 zend_ast_export_attributes(str, decl->child[3], indent, 0);
2259 }
2260 smart_str_appends(str, "class");
2261 if (!zend_ast_is_list(ast->child[1])
2262 || zend_ast_get_list(ast->child[1])->children) {
2263 smart_str_appendc(str, '(');
2264 zend_ast_export_ex(str, ast->child[1], 0, indent);
2265 smart_str_appendc(str, ')');
2266 }
2267 zend_ast_export_class_no_header(str, decl, indent);
2268 } else {
2269 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2270 smart_str_appendc(str, '(');
2271 zend_ast_export_ex(str, ast->child[1], 0, indent);
2272 smart_str_appendc(str, ')');
2273 }
2274 break;
2275 case ZEND_AST_INSTANCEOF:
2276 zend_ast_export_ex(str, ast->child[0], 0, indent);
2277 smart_str_appends(str, " instanceof ");
2278 zend_ast_export_ns_name(str, ast->child[1], 0, indent);
2279 break;
2280 case ZEND_AST_YIELD:
2281 if (priority > 70) smart_str_appendc(str, '(');
2282 smart_str_appends(str, "yield ");
2283 if (ast->child[0]) {
2284 if (ast->child[1]) {
2285 zend_ast_export_ex(str, ast->child[1], 70, indent);
2286 smart_str_appends(str, " => ");
2287 }
2288 zend_ast_export_ex(str, ast->child[0], 70, indent);
2289 }
2290 if (priority > 70) smart_str_appendc(str, ')');
2291 break;
2292 case ZEND_AST_YIELD_FROM:
2293 PREFIX_OP("yield from ", 85, 86);
2294 case ZEND_AST_COALESCE: BINARY_OP(" ?? ", 110, 111, 110);
2295 case ZEND_AST_STATIC:
2296 smart_str_appends(str, "static $");
2297 zend_ast_export_name(str, ast->child[0], 0, indent);
2298 APPEND_DEFAULT_VALUE(1);
2299 case ZEND_AST_WHILE:
2300 smart_str_appends(str, "while (");
2301 zend_ast_export_ex(str, ast->child[0], 0, indent);
2302 smart_str_appends(str, ") {\n");
2303 zend_ast_export_stmt(str, ast->child[1], indent + 1);
2304 zend_ast_export_indent(str, indent);
2305 smart_str_appendc(str, '}');
2306 break;
2307 case ZEND_AST_DO_WHILE:
2308 smart_str_appends(str, "do {\n");
2309 zend_ast_export_stmt(str, ast->child[0], indent + 1);
2310 zend_ast_export_indent(str, indent);
2311 smart_str_appends(str, "} while (");
2312 zend_ast_export_ex(str, ast->child[1], 0, indent);
2313 smart_str_appendc(str, ')');
2314 break;
2315
2316 case ZEND_AST_IF_ELEM:
2317 if (ast->child[0]) {
2318 smart_str_appends(str, "if (");
2319 zend_ast_export_ex(str, ast->child[0], 0, indent);
2320 smart_str_appends(str, ") {\n");
2321 zend_ast_export_stmt(str, ast->child[1], indent + 1);
2322 } else {
2323 smart_str_appends(str, "else {\n");
2324 zend_ast_export_stmt(str, ast->child[1], indent + 1);
2325 }
2326 zend_ast_export_indent(str, indent);
2327 smart_str_appendc(str, '}');
2328 break;
2329 case ZEND_AST_SWITCH:
2330 smart_str_appends(str, "switch (");
2331 zend_ast_export_ex(str, ast->child[0], 0, indent);
2332 smart_str_appends(str, ") {\n");
2333 zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2334 zend_ast_export_indent(str, indent);
2335 smart_str_appendc(str, '}');
2336 break;
2337 case ZEND_AST_SWITCH_CASE:
2338 zend_ast_export_indent(str, indent);
2339 if (ast->child[0]) {
2340 smart_str_appends(str, "case ");
2341 zend_ast_export_ex(str, ast->child[0], 0, indent);
2342 smart_str_appends(str, ":\n");
2343 } else {
2344 smart_str_appends(str, "default:\n");
2345 }
2346 zend_ast_export_stmt(str, ast->child[1], indent + 1);
2347 break;
2348 case ZEND_AST_MATCH:
2349 smart_str_appends(str, "match (");
2350 zend_ast_export_ex(str, ast->child[0], 0, indent);
2351 smart_str_appends(str, ") {\n");
2352 zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2353 zend_ast_export_indent(str, indent);
2354 smart_str_appendc(str, '}');
2355 break;
2356 case ZEND_AST_MATCH_ARM:
2357 zend_ast_export_indent(str, indent);
2358 if (ast->child[0]) {
2359 zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent);
2360 smart_str_appends(str, " => ");
2361 } else {
2362 smart_str_appends(str, "default => ");
2363 }
2364 zend_ast_export_ex(str, ast->child[1], 0, 0);
2365 smart_str_appends(str, ",\n");
2366 break;
2367 case ZEND_AST_DECLARE:
2368 smart_str_appends(str, "declare(");
2369 ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_CONST_DECL);
2370 zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent);
2371 smart_str_appendc(str, ')');
2372 if (ast->child[1]) {
2373 smart_str_appends(str, " {\n");
2374 zend_ast_export_stmt(str, ast->child[1], indent + 1);
2375 zend_ast_export_indent(str, indent);
2376 smart_str_appendc(str, '}');
2377 } else {
2378 smart_str_appendc(str, ';');
2379 }
2380 break;
2381 case ZEND_AST_PROP_ELEM:
2382 smart_str_appendc(str, '$');
2383 zend_ast_export_name(str, ast->child[0], 0, indent);
2384
2385 zend_ast *default_value = ast->child[1];
2386 if (default_value) {
2387 smart_str_appends(str, " = ");
2388 zend_ast_export_ex(str, default_value, 0, indent + 1);
2389 }
2390
2391 if (ast->child[3]) {
2392 zend_ast_list *hook_list = zend_ast_get_list(ast->child[3]);
2393
2394 smart_str_appends(str, " {");
2395 smart_str_appendc(str, '\n');
2396 indent++;
2397 zend_ast_export_indent(str, indent);
2398
2399 for (uint32_t i = 0; i < hook_list->children; i++) {
2400 zend_ast_decl *hook = (zend_ast_decl *)hook_list->child[i];
2401 zend_ast_export_visibility(str, hook->flags, ZEND_MODIFIER_TARGET_PROPERTY);
2402 if (hook->flags & ZEND_ACC_FINAL) {
2403 smart_str_appends(str, "final ");
2404 }
2405 switch (i) {
2406 case ZEND_PROPERTY_HOOK_GET:
2407 smart_str_appends(str, "get");
2408 break;
2409 case ZEND_PROPERTY_HOOK_SET:
2410 smart_str_appends(str, "set");
2411 break;
2412 }
2413 zend_ast *body = hook->child[2];
2414 if (body == NULL) {
2415 smart_str_appendc(str, ';');
2416 } else if (body->kind == ZEND_AST_PROPERTY_HOOK_SHORT_BODY) {
2417 smart_str_appends(str, " => ");
2418 zend_ast_export_ex(str, body->child[0], 0, indent);
2419 smart_str_appendc(str, ';');
2420 } else {
2421 smart_str_appends(str, " {\n");
2422 zend_ast_export_stmt(str, body, indent + 1);
2423 zend_ast_export_indent(str, indent);
2424 smart_str_appendc(str, '}');
2425 }
2426 if (i < (hook_list->children - 1)) {
2427 smart_str_appendc(str, '\n');
2428 zend_ast_export_indent(str, indent);
2429 }
2430 }
2431 smart_str_appendc(str, '\n');
2432 indent--;
2433 zend_ast_export_indent(str, indent);
2434 smart_str_appendc(str, '}');
2435 }
2436 break;
2437 case ZEND_AST_CONST_ELEM:
2438 zend_ast_export_name(str, ast->child[0], 0, indent);
2439 APPEND_DEFAULT_VALUE(1);
2440 case ZEND_AST_USE_TRAIT:
2441 smart_str_appends(str, "use ");
2442 zend_ast_export_ex(str, ast->child[0], 0, indent);
2443 if (ast->child[1]) {
2444 smart_str_appends(str, " {\n");
2445 zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2446 zend_ast_export_indent(str, indent);
2447 smart_str_appends(str, "}");
2448 } else {
2449 smart_str_appends(str, ";");
2450 }
2451 break;
2452 case ZEND_AST_TRAIT_PRECEDENCE:
2453 zend_ast_export_ex(str, ast->child[0], 0, indent);
2454 smart_str_appends(str, " insteadof ");
2455 zend_ast_export_ex(str, ast->child[1], 0, indent);
2456 break;
2457 case ZEND_AST_METHOD_REFERENCE:
2458 if (ast->child[0]) {
2459 zend_ast_export_name(str, ast->child[0], 0, indent);
2460 smart_str_appends(str, "::");
2461 }
2462 zend_ast_export_name(str, ast->child[1], 0, indent);
2463 break;
2464 case ZEND_AST_NAMESPACE:
2465 smart_str_appends(str, "namespace");
2466 if (ast->child[0]) {
2467 smart_str_appendc(str, ' ');
2468 zend_ast_export_name(str, ast->child[0], 0, indent);
2469 }
2470 if (ast->child[1]) {
2471 smart_str_appends(str, " {\n");
2472 zend_ast_export_stmt(str, ast->child[1], indent + 1);
2473 zend_ast_export_indent(str, indent);
2474 smart_str_appends(str, "}\n");
2475 } else {
2476 smart_str_appendc(str, ';');
2477 }
2478 break;
2479 case ZEND_AST_USE_ELEM:
2480 case ZEND_AST_TRAIT_ALIAS:
2481 zend_ast_export_name(str, ast->child[0], 0, indent);
2482 if (ast->attr & ZEND_ACC_PUBLIC) {
2483 smart_str_appends(str, " as public");
2484 } else if (ast->attr & ZEND_ACC_PROTECTED) {
2485 smart_str_appends(str, " as protected");
2486 } else if (ast->attr & ZEND_ACC_PRIVATE) {
2487 smart_str_appends(str, " as private");
2488 } else if (ast->child[1]) {
2489 smart_str_appends(str, " as");
2490 }
2491 if (ast->child[1]) {
2492 smart_str_appendc(str, ' ');
2493 zend_ast_export_name(str, ast->child[1], 0, indent);
2494 }
2495 break;
2496 case ZEND_AST_NAMED_ARG:
2497 smart_str_append(str, zend_ast_get_str(ast->child[0]));
2498 smart_str_appends(str, ": ");
2499 ast = ast->child[1];
2500 goto tail_call;
2501
2502 /* 3 child nodes */
2503 case ZEND_AST_METHOD_CALL:
2504 case ZEND_AST_NULLSAFE_METHOD_CALL:
2505 zend_ast_export_ex(str, ast->child[0], 0, indent);
2506 smart_str_appends(str, ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL ? "?->" : "->");
2507 zend_ast_export_var(str, ast->child[1], 0, indent);
2508 smart_str_appendc(str, '(');
2509 zend_ast_export_ex(str, ast->child[2], 0, indent);
2510 smart_str_appendc(str, ')');
2511 break;
2512 case ZEND_AST_STATIC_CALL:
2513 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2514 smart_str_appends(str, "::");
2515 zend_ast_export_var(str, ast->child[1], 0, indent);
2516 smart_str_appendc(str, '(');
2517 zend_ast_export_ex(str, ast->child[2], 0, indent);
2518 smart_str_appendc(str, ')');
2519 break;
2520 case ZEND_AST_CONDITIONAL:
2521 if (priority > 100) smart_str_appendc(str, '(');
2522 zend_ast_export_ex(str, ast->child[0], 100, indent);
2523 if (ast->child[1]) {
2524 smart_str_appends(str, " ? ");
2525 zend_ast_export_ex(str, ast->child[1], 101, indent);
2526 smart_str_appends(str, " : ");
2527 } else {
2528 smart_str_appends(str, " ?: ");
2529 }
2530 zend_ast_export_ex(str, ast->child[2], 101, indent);
2531 if (priority > 100) smart_str_appendc(str, ')');
2532 break;
2533
2534 case ZEND_AST_TRY:
2535 smart_str_appends(str, "try {\n");
2536 zend_ast_export_stmt(str, ast->child[0], indent + 1);
2537 zend_ast_export_indent(str, indent);
2538 zend_ast_export_ex(str, ast->child[1], 0, indent);
2539 if (ast->child[2]) {
2540 smart_str_appends(str, "} finally {\n");
2541 zend_ast_export_stmt(str, ast->child[2], indent + 1);
2542 zend_ast_export_indent(str, indent);
2543 }
2544 smart_str_appendc(str, '}');
2545 break;
2546 case ZEND_AST_CATCH:
2547 smart_str_appends(str, "} catch (");
2548 zend_ast_export_catch_name_list(str, zend_ast_get_list(ast->child[0]), indent);
2549 if (ast->child[1]) {
2550 smart_str_appends(str, " $");
2551 zend_ast_export_var(str, ast->child[1], 0, indent);
2552 }
2553 smart_str_appends(str, ") {\n");
2554 zend_ast_export_stmt(str, ast->child[2], indent + 1);
2555 zend_ast_export_indent(str, indent);
2556 break;
2557 case ZEND_AST_PARAM:
2558 if (ast->child[3]) {
2559 zend_ast_export_attributes(str, ast->child[3], indent, 0);
2560 }
2561 if (ast->child[0]) {
2562 zend_ast_export_type(str, ast->child[0], indent);
2563 smart_str_appendc(str, ' ');
2564 }
2565 if (ast->attr & ZEND_PARAM_REF) {
2566 smart_str_appendc(str, '&');
2567 }
2568 if (ast->attr & ZEND_PARAM_VARIADIC) {
2569 smart_str_appends(str, "...");
2570 }
2571 smart_str_appendc(str, '$');
2572 zend_ast_export_name(str, ast->child[1], 0, indent);
2573 APPEND_DEFAULT_VALUE(2);
2574 case ZEND_AST_ENUM_CASE:
2575 if (ast->child[3]) {
2576 zend_ast_export_attributes(str, ast->child[3], indent, 1);
2577 }
2578 smart_str_appends(str, "case ");
2579 zend_ast_export_name(str, ast->child[0], 0, indent);
2580 if (ast->child[1]) {
2581 smart_str_appends(str, " = ");
2582 zend_ast_export_ex(str, ast->child[1], 0, indent);
2583 }
2584 break;
2585
2586 /* 4 child nodes */
2587 case ZEND_AST_FOR:
2588 smart_str_appends(str, "for (");
2589 zend_ast_export_ex(str, ast->child[0], 0, indent);
2590 smart_str_appendc(str, ';');
2591 if (ast->child[1]) {
2592 smart_str_appendc(str, ' ');
2593 zend_ast_export_ex(str, ast->child[1], 0, indent);
2594 }
2595 smart_str_appendc(str, ';');
2596 if (ast->child[2]) {
2597 smart_str_appendc(str, ' ');
2598 zend_ast_export_ex(str, ast->child[2], 0, indent);
2599 }
2600 smart_str_appends(str, ") {\n");
2601 zend_ast_export_stmt(str, ast->child[3], indent + 1);
2602 zend_ast_export_indent(str, indent);
2603 smart_str_appendc(str, '}');
2604 break;
2605 case ZEND_AST_FOREACH:
2606 smart_str_appends(str, "foreach (");
2607 zend_ast_export_ex(str, ast->child[0], 0, indent);
2608 smart_str_appends(str, " as ");
2609 if (ast->child[2]) {
2610 zend_ast_export_ex(str, ast->child[2], 0, indent);
2611 smart_str_appends(str, " => ");
2612 }
2613 zend_ast_export_ex(str, ast->child[1], 0, indent);
2614 smart_str_appends(str, ") {\n");
2615 zend_ast_export_stmt(str, ast->child[3], indent + 1);
2616 zend_ast_export_indent(str, indent);
2617 smart_str_appendc(str, '}');
2618 break;
2619 EMPTY_SWITCH_DEFAULT_CASE();
2620 }
2621 return;
2622
2623 binary_op:
2624 if (priority > p) smart_str_appendc(str, '(');
2625 zend_ast_export_ex(str, ast->child[0], pl, indent);
2626 smart_str_appends(str, op);
2627 zend_ast_export_ex(str, ast->child[1], pr, indent);
2628 if (priority > p) smart_str_appendc(str, ')');
2629 return;
2630
2631 prefix_op:
2632 if (priority > p) smart_str_appendc(str, '(');
2633 smart_str_appends(str, op);
2634 zend_ast_export_ex(str, ast->child[0], pl, indent);
2635 if (priority > p) smart_str_appendc(str, ')');
2636 return;
2637
2638 postfix_op:
2639 if (priority > p) smart_str_appendc(str, '(');
2640 zend_ast_export_ex(str, ast->child[0], pl, indent);
2641 smart_str_appends(str, op);
2642 if (priority > p) smart_str_appendc(str, ')');
2643 return;
2644
2645 func_op:
2646 smart_str_appends(str, op);
2647 smart_str_appendc(str, '(');
2648 zend_ast_export_ex(str, ast->child[0], 0, indent);
2649 smart_str_appendc(str, ')');
2650 return;
2651
2652 append_node_1:
2653 smart_str_appends(str, op);
2654 if (ast->child[0]) {
2655 smart_str_appendc(str, ' ');
2656 ast = ast->child[0];
2657 goto tail_call;
2658 }
2659 return;
2660
2661 append_str:
2662 smart_str_appends(str, op);
2663 return;
2664
2665 append_default_value:
2666 if (ast->child[p]) {
2667 smart_str_appends(str, " = ");
2668 ast = ast->child[p];
2669 goto tail_call;
2670 }
2671 return;
2672 }
2673
zend_ast_export(const char * prefix,zend_ast * ast,const char * suffix)2674 ZEND_API ZEND_COLD zend_string *zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix)
2675 {
2676 smart_str str = {0};
2677
2678 smart_str_appends(&str, prefix);
2679 zend_ast_export_ex(&str, ast, 0, 0);
2680 smart_str_appends(&str, suffix);
2681 smart_str_0(&str);
2682 return str.s;
2683 }
2684
zend_ast_with_attributes(zend_ast * ast,zend_ast * attr)2685 zend_ast * ZEND_FASTCALL zend_ast_with_attributes(zend_ast *ast, zend_ast *attr)
2686 {
2687 ZEND_ASSERT(attr->kind == ZEND_AST_ATTRIBUTE_LIST);
2688
2689 switch (ast->kind) {
2690 case ZEND_AST_FUNC_DECL:
2691 case ZEND_AST_CLOSURE:
2692 case ZEND_AST_METHOD:
2693 case ZEND_AST_ARROW_FUNC:
2694 case ZEND_AST_PROPERTY_HOOK:
2695 ((zend_ast_decl *) ast)->child[4] = attr;
2696 break;
2697 case ZEND_AST_CLASS:
2698 ((zend_ast_decl *) ast)->child[3] = attr;
2699 break;
2700 case ZEND_AST_PROP_GROUP:
2701 ast->child[2] = attr;
2702 break;
2703 case ZEND_AST_PARAM:
2704 case ZEND_AST_ENUM_CASE:
2705 ast->child[3] = attr;
2706 break;
2707 case ZEND_AST_CLASS_CONST_GROUP:
2708 ast->child[1] = attr;
2709 break;
2710 EMPTY_SWITCH_DEFAULT_CASE()
2711 }
2712
2713 return ast;
2714 }
2715