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