1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Bob Weinand <bwoebi@php.net> |
16 | Dmitry Stogov <dmitry@zend.com> |
17 +----------------------------------------------------------------------+
18 */
19
20 /* $Id$ */
21
22 #include "zend_ast.h"
23 #include "zend_API.h"
24 #include "zend_operators.h"
25
zend_ast_create_constant(zval * zv)26 ZEND_API zend_ast *zend_ast_create_constant(zval *zv)
27 {
28 zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zval));
29 ast->kind = ZEND_CONST;
30 ast->children = 0;
31 ast->u.val = (zval*)(ast + 1);
32 INIT_PZVAL_COPY(ast->u.val, zv);
33 return ast;
34 }
35
zend_ast_create_unary(uint kind,zend_ast * op0)36 ZEND_API zend_ast* zend_ast_create_unary(uint kind, zend_ast *op0)
37 {
38 zend_ast *ast = emalloc(sizeof(zend_ast));
39 ast->kind = kind;
40 ast->children = 1;
41 (&ast->u.child)[0] = op0;
42 return ast;
43 }
44
zend_ast_create_binary(uint kind,zend_ast * op0,zend_ast * op1)45 ZEND_API zend_ast* zend_ast_create_binary(uint kind, zend_ast *op0, zend_ast *op1)
46 {
47 zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*));
48 ast->kind = kind;
49 ast->children = 2;
50 (&ast->u.child)[0] = op0;
51 (&ast->u.child)[1] = op1;
52 return ast;
53 }
54
zend_ast_create_ternary(uint kind,zend_ast * op0,zend_ast * op1,zend_ast * op2)55 ZEND_API zend_ast* zend_ast_create_ternary(uint kind, zend_ast *op0, zend_ast *op1, zend_ast *op2)
56 {
57 zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * 2);
58 ast->kind = kind;
59 ast->children = 3;
60 (&ast->u.child)[0] = op0;
61 (&ast->u.child)[1] = op1;
62 (&ast->u.child)[2] = op2;
63 return ast;
64 }
65
zend_ast_create_dynamic(uint kind)66 ZEND_API zend_ast* zend_ast_create_dynamic(uint kind)
67 {
68 zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * 3); /* use 4 children as deafult */
69 ast->kind = kind;
70 ast->children = 0;
71 return ast;
72 }
73
zend_ast_dynamic_add(zend_ast ** ast,zend_ast * op)74 ZEND_API void zend_ast_dynamic_add(zend_ast **ast, zend_ast *op)
75 {
76 if ((*ast)->children >= 4 && (*ast)->children == ((*ast)->children & -(*ast)->children)) {
77 *ast = erealloc(*ast, sizeof(zend_ast) + sizeof(zend_ast*) * ((*ast)->children * 2 + 1));
78 }
79 (&(*ast)->u.child)[(*ast)->children++] = op;
80 }
81
zend_ast_dynamic_shrink(zend_ast ** ast)82 ZEND_API void zend_ast_dynamic_shrink(zend_ast **ast)
83 {
84 *ast = erealloc(*ast, sizeof(zend_ast) + sizeof(zend_ast*) * ((*ast)->children - 1));
85 }
86
zend_ast_is_ct_constant(zend_ast * ast)87 ZEND_API int zend_ast_is_ct_constant(zend_ast *ast)
88 {
89 int i;
90
91 if (ast->kind == ZEND_CONST) {
92 return !IS_CONSTANT_TYPE(Z_TYPE_P(ast->u.val));
93 } else {
94 for (i = 0; i < ast->children; i++) {
95 if ((&ast->u.child)[i]) {
96 if (!zend_ast_is_ct_constant((&ast->u.child)[i])) {
97 return 0;
98 }
99 }
100 }
101 return 1;
102 }
103 }
104
zend_ast_evaluate(zval * result,zend_ast * ast,zend_class_entry * scope TSRMLS_DC)105 ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope TSRMLS_DC)
106 {
107 zval op1, op2;
108
109 switch (ast->kind) {
110 case ZEND_ADD:
111 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
112 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
113 add_function(result, &op1, &op2 TSRMLS_CC);
114 zval_dtor(&op1);
115 zval_dtor(&op2);
116 break;
117 case ZEND_SUB:
118 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
119 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
120 sub_function(result, &op1, &op2 TSRMLS_CC);
121 zval_dtor(&op1);
122 zval_dtor(&op2);
123 break;
124 case ZEND_MUL:
125 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
126 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
127 mul_function(result, &op1, &op2 TSRMLS_CC);
128 zval_dtor(&op1);
129 zval_dtor(&op2);
130 break;
131 case ZEND_POW:
132 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
133 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
134 pow_function(result, &op1, &op2 TSRMLS_CC);
135 zval_dtor(&op1);
136 zval_dtor(&op2);
137 break;
138 case ZEND_DIV:
139 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
140 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
141 div_function(result, &op1, &op2 TSRMLS_CC);
142 zval_dtor(&op1);
143 zval_dtor(&op2);
144 break;
145 case ZEND_MOD:
146 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
147 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
148 mod_function(result, &op1, &op2 TSRMLS_CC);
149 zval_dtor(&op1);
150 zval_dtor(&op2);
151 break;
152 case ZEND_SL:
153 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
154 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
155 shift_left_function(result, &op1, &op2 TSRMLS_CC);
156 zval_dtor(&op1);
157 zval_dtor(&op2);
158 break;
159 case ZEND_SR:
160 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
161 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
162 shift_right_function(result, &op1, &op2 TSRMLS_CC);
163 zval_dtor(&op1);
164 zval_dtor(&op2);
165 break;
166 case ZEND_CONCAT:
167 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
168 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
169 concat_function(result, &op1, &op2 TSRMLS_CC);
170 zval_dtor(&op1);
171 zval_dtor(&op2);
172 break;
173 case ZEND_BW_OR:
174 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
175 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
176 bitwise_or_function(result, &op1, &op2 TSRMLS_CC);
177 zval_dtor(&op1);
178 zval_dtor(&op2);
179 break;
180 case ZEND_BW_AND:
181 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
182 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
183 bitwise_and_function(result, &op1, &op2 TSRMLS_CC);
184 zval_dtor(&op1);
185 zval_dtor(&op2);
186 break;
187 case ZEND_BW_XOR:
188 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
189 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
190 bitwise_xor_function(result, &op1, &op2 TSRMLS_CC);
191 zval_dtor(&op1);
192 zval_dtor(&op2);
193 break;
194 case ZEND_BW_NOT:
195 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
196 bitwise_not_function(result, &op1 TSRMLS_CC);
197 zval_dtor(&op1);
198 break;
199 case ZEND_BOOL_NOT:
200 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
201 boolean_not_function(result, &op1 TSRMLS_CC);
202 zval_dtor(&op1);
203 break;
204 case ZEND_BOOL_XOR:
205 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
206 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
207 boolean_xor_function(result, &op1, &op2 TSRMLS_CC);
208 zval_dtor(&op1);
209 zval_dtor(&op2);
210 break;
211 case ZEND_IS_IDENTICAL:
212 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
213 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
214 is_identical_function(result, &op1, &op2 TSRMLS_CC);
215 zval_dtor(&op1);
216 zval_dtor(&op2);
217 break;
218 case ZEND_IS_NOT_IDENTICAL:
219 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
220 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
221 is_not_identical_function(result, &op1, &op2 TSRMLS_CC);
222 zval_dtor(&op1);
223 zval_dtor(&op2);
224 break;
225 case ZEND_IS_EQUAL:
226 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
227 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
228 is_equal_function(result, &op1, &op2 TSRMLS_CC);
229 zval_dtor(&op1);
230 zval_dtor(&op2);
231 break;
232 case ZEND_IS_NOT_EQUAL:
233 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
234 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
235 is_not_equal_function(result, &op1, &op2 TSRMLS_CC);
236 zval_dtor(&op1);
237 zval_dtor(&op2);
238 break;
239 case ZEND_IS_SMALLER:
240 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
241 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
242 is_smaller_function(result, &op1, &op2 TSRMLS_CC);
243 zval_dtor(&op1);
244 zval_dtor(&op2);
245 break;
246 case ZEND_IS_SMALLER_OR_EQUAL:
247 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
248 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
249 is_smaller_or_equal_function(result, &op1, &op2 TSRMLS_CC);
250 zval_dtor(&op1);
251 zval_dtor(&op2);
252 break;
253 case ZEND_CONST:
254 /* class constants may be updated in-place */
255 if (scope) {
256 if (IS_CONSTANT_TYPE(Z_TYPE_P(ast->u.val))) {
257 zval_update_constant_ex(&ast->u.val, 1, scope TSRMLS_CC);
258 }
259 *result = *ast->u.val;
260 zval_copy_ctor(result);
261 } else {
262 *result = *ast->u.val;
263 zval_copy_ctor(result);
264 if (IS_CONSTANT_TYPE(Z_TYPE_P(result))) {
265 zval_update_constant_ex(&result, 1, scope TSRMLS_CC);
266 }
267 }
268 break;
269 case ZEND_BOOL_AND:
270 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
271 if (zend_is_true(&op1)) {
272 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
273 ZVAL_BOOL(result, zend_is_true(&op2));
274 zval_dtor(&op2);
275 } else {
276 ZVAL_BOOL(result, 0);
277 }
278 zval_dtor(&op1);
279 break;
280 case ZEND_BOOL_OR:
281 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
282 if (zend_is_true(&op1)) {
283 ZVAL_BOOL(result, 1);
284 } else {
285 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
286 ZVAL_BOOL(result, zend_is_true(&op2));
287 zval_dtor(&op2);
288 }
289 zval_dtor(&op1);
290 break;
291 case ZEND_SELECT:
292 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
293 if (zend_is_true(&op1)) {
294 if (!(&ast->u.child)[1]) {
295 *result = op1;
296 } else {
297 zend_ast_evaluate(result, (&ast->u.child)[1], scope TSRMLS_CC);
298 zval_dtor(&op1);
299 }
300 } else {
301 zend_ast_evaluate(result, (&ast->u.child)[2], scope TSRMLS_CC);
302 zval_dtor(&op1);
303 }
304 break;
305 case ZEND_UNARY_PLUS:
306 ZVAL_LONG(&op1, 0);
307 zend_ast_evaluate(&op2, (&ast->u.child)[0], scope TSRMLS_CC);
308 add_function(result, &op1, &op2 TSRMLS_CC);
309 zval_dtor(&op2);
310 break;
311 case ZEND_UNARY_MINUS:
312 ZVAL_LONG(&op1, 0);
313 zend_ast_evaluate(&op2, (&ast->u.child)[0], scope TSRMLS_CC);
314 sub_function(result, &op1, &op2 TSRMLS_CC);
315 zval_dtor(&op2);
316 break;
317 case ZEND_INIT_ARRAY:
318 INIT_PZVAL(result);
319 array_init(result);
320 {
321 int i;
322 zend_bool has_key;
323 for (i = 0; i < ast->children; i+=2) {
324 zval *expr;
325 MAKE_STD_ZVAL(expr);
326 if ((has_key = !!(&ast->u.child)[i])) {
327 zend_ast_evaluate(&op1, (&ast->u.child)[i], scope TSRMLS_CC);
328 }
329 zend_ast_evaluate(expr, (&ast->u.child)[i+1], scope TSRMLS_CC);
330 zend_do_add_static_array_element(result, has_key?&op1:NULL, expr);
331 }
332 }
333 break;
334 case ZEND_FETCH_DIM_R:
335 zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
336 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
337 {
338 zval *tmp;
339 zend_fetch_dimension_by_zval(&tmp, &op1, &op2 TSRMLS_CC);
340 ZVAL_ZVAL(result, tmp, 1, 1);
341 }
342 zval_dtor(&op1);
343 zval_dtor(&op2);
344 break;
345 default:
346 zend_error(E_ERROR, "Unsupported constant expression");
347 }
348 }
349
zend_ast_copy(zend_ast * ast)350 ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
351 {
352 if (ast == NULL) {
353 return NULL;
354 } else if (ast->kind == ZEND_CONST) {
355 zend_ast *copy = zend_ast_create_constant(ast->u.val);
356 zval_copy_ctor(copy->u.val);
357 return copy;
358 } else if (ast->children) {
359 zend_ast *new = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
360 int i;
361 new->kind = ast->kind;
362 new->children = ast->children;
363 for (i = 0; i < ast->children; i++) {
364 (&new->u.child)[i] = zend_ast_copy((&ast->u.child)[i]);
365 }
366 return new;
367 }
368 return zend_ast_create_dynamic(ast->kind);
369 }
370
zend_ast_destroy(zend_ast * ast)371 ZEND_API void zend_ast_destroy(zend_ast *ast)
372 {
373 int i;
374
375 if (ast->kind == ZEND_CONST) {
376 zval_dtor(ast->u.val);
377 } else {
378 for (i = 0; i < ast->children; i++) {
379 if ((&ast->u.child)[i]) {
380 zend_ast_destroy((&ast->u.child)[i]);
381 }
382 }
383 }
384 efree(ast);
385 }
386