xref: /PHP-5.6/Zend/zend_ast.c (revision 3537e95d)
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