1 
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5 
6 #include "php.h"
7 #include "php_phalcon.h"
8 #include "phalcon.h"
9 
10 #include <ext/standard/php_smart_string.h>
11 #include <zend_smart_str.h>
12 
13 #include "parser.php7.h"
14 #include "scanner.h"
15 #include "volt.h"
16 
17 #include "kernel/main.h"
18 #include "kernel/memory.h"
19 #include "kernel/fcall.h"
20 #include "kernel/exception.h"
21 
22 #define phvolt_add_assoc_stringl(var, index, str, len, copy) add_assoc_stringl(var, index, str, len);
23 
phvolt_ret_literal_zval(zval * ret,int type,phvolt_parser_token * T,phvolt_scanner_state * state)24 static void phvolt_ret_literal_zval(zval *ret, int type, phvolt_parser_token *T, phvolt_scanner_state *state)
25 {
26 	array_init(ret);
27 	add_assoc_long(ret, "type", type);
28 	if (T) {
29 		phvolt_add_assoc_stringl(ret, "value", T->token, T->token_len, 0);
30 		efree(T->token);
31 		efree(T);
32 	}
33 
34 	Z_TRY_ADDREF_P(state->active_file);
35 	add_assoc_zval(ret, "file", state->active_file);
36 	add_assoc_long(ret, "line", state->active_line);
37 }
38 
phvolt_ret_if_statement(zval * ret,zval * expr,zval * true_statements,zval * false_statements,phvolt_scanner_state * state)39 static void phvolt_ret_if_statement(zval *ret, zval *expr, zval *true_statements, zval *false_statements, phvolt_scanner_state *state)
40 {
41 	array_init(ret);
42 	add_assoc_long(ret, "type", PHVOLT_T_IF);
43 	add_assoc_zval(ret, "expr", expr);
44 
45 	if (true_statements) {
46 		add_assoc_zval(ret, "true_statements", true_statements);
47 	}
48 	if (false_statements) {
49 		add_assoc_zval(ret, "false_statements", false_statements);
50 	}
51 
52 	Z_TRY_ADDREF_P(state->active_file);
53 	add_assoc_zval(ret, "file", state->active_file);
54 	add_assoc_long(ret, "line", state->active_line);
55 }
56 
phvolt_ret_elseif_statement(zval * ret,zval * expr,phvolt_scanner_state * state)57 static void phvolt_ret_elseif_statement(zval *ret, zval *expr, phvolt_scanner_state *state)
58 {
59 	array_init(ret);
60 	add_assoc_long(ret, "type", PHVOLT_T_ELSEIF);
61 	add_assoc_zval(ret, "expr", expr);
62 
63 	Z_TRY_ADDREF_P(state->active_file);
64 	add_assoc_zval(ret, "file", state->active_file);
65 	add_assoc_long(ret, "line", state->active_line);
66 }
67 
phvolt_ret_elsefor_statement(zval * ret,phvolt_scanner_state * state)68 static void phvolt_ret_elsefor_statement(zval *ret, phvolt_scanner_state *state)
69 {
70 	array_init(ret);
71 	add_assoc_long(ret, "type", PHVOLT_T_ELSEFOR);
72 
73 	Z_TRY_ADDREF_P(state->active_file);
74 	add_assoc_zval(ret, "file", state->active_file);
75 	add_assoc_long(ret, "line", state->active_line);
76 }
77 
phvolt_ret_switch_statement(zval * ret,zval * expr,zval * case_clauses,phvolt_scanner_state * state)78 static void phvolt_ret_switch_statement(zval *ret, zval *expr, zval *case_clauses, phvolt_scanner_state *state)
79 {
80 	array_init(ret);
81 
82 	add_assoc_long(ret, "type", PHVOLT_T_SWITCH);
83 	add_assoc_zval(ret, "expr", expr);
84 
85 	if (case_clauses) {
86 		add_assoc_zval(ret, "case_clauses", case_clauses);
87 	}
88 
89 	Z_TRY_ADDREF_P(state->active_file);
90 	add_assoc_zval(ret, "file", state->active_file);
91 	add_assoc_long(ret, "line", state->active_line);
92 }
93 
phvolt_ret_case_clause(zval * ret,zval * expr,phvolt_scanner_state * state)94 static void phvolt_ret_case_clause(zval *ret, zval *expr, phvolt_scanner_state *state)
95 {
96 	array_init(ret);
97 
98 	if (expr) {
99 		add_assoc_long(ret, "type", PHVOLT_T_CASE);
100 		add_assoc_zval(ret, "expr", expr);
101 	} else {
102 		add_assoc_long(ret, "type", PHVOLT_T_DEFAULT);
103 	}
104 
105 	Z_TRY_ADDREF_P(state->active_file);
106 	add_assoc_zval(ret, "file", state->active_file);
107 	add_assoc_long(ret, "line", state->active_line);
108 }
109 
phvolt_ret_for_statement(zval * ret,phvolt_parser_token * variable,phvolt_parser_token * key,zval * expr,zval * if_expr,zval * block_statements,phvolt_scanner_state * state)110 static void phvolt_ret_for_statement(zval *ret, phvolt_parser_token *variable, phvolt_parser_token *key, zval *expr, zval *if_expr, zval *block_statements, phvolt_scanner_state *state)
111 {
112 	array_init(ret);
113 	add_assoc_long(ret, "type", PHVOLT_T_FOR);
114 
115 	phvolt_add_assoc_stringl(ret, "variable", variable->token, variable->token_len, 0);
116 	efree(variable->token);
117 	efree(variable);
118 
119 	if (key) {
120 		phvolt_add_assoc_stringl(ret, "key", key->token, key->token_len, 0);
121 		efree(key->token);
122 		efree(key);
123 	}
124 
125 	add_assoc_zval(ret, "expr", expr);
126 	if (if_expr) {
127 		add_assoc_zval(ret, "if_expr", if_expr);
128 	}
129 
130 	add_assoc_zval(ret, "block_statements", block_statements);
131 
132 	Z_TRY_ADDREF_P(state->active_file);
133 	add_assoc_zval(ret, "file", state->active_file);
134 	add_assoc_long(ret, "line", state->active_line);
135 }
136 
phvolt_ret_cache_statement(zval * ret,zval * expr,zval * lifetime,zval * block_statements,phvolt_scanner_state * state)137 static void phvolt_ret_cache_statement(zval *ret, zval *expr, zval *lifetime, zval *block_statements, phvolt_scanner_state *state)
138 {
139 	array_init(ret);
140 
141 	add_assoc_long(ret, "type", PHVOLT_T_CACHE);
142 	add_assoc_zval(ret, "expr", expr);
143 
144 	if (lifetime) {
145 		add_assoc_zval(ret, "lifetime", lifetime);
146 	}
147 	add_assoc_zval(ret, "block_statements", block_statements);
148 
149 	Z_TRY_ADDREF_P(state->active_file);
150 	add_assoc_zval(ret, "file", state->active_file);
151 	add_assoc_long(ret, "line", state->active_line);
152 }
153 
phvolt_ret_raw_statement(zval * ret,zval * statement,phvolt_scanner_state * state)154 static void phvolt_ret_raw_statement(zval *ret, zval *statement, phvolt_scanner_state *state)
155 {
156 	array_init(ret);
157 
158 	add_assoc_long(ret, "type", PHVOLT_T_RAW);
159 	add_assoc_zval(ret, "content", statement);
160 
161 	Z_TRY_ADDREF_P(state->active_file);
162 	add_assoc_zval(ret, "file", state->active_file);
163 	add_assoc_long(ret, "line", state->active_line);
164 }
165 
phvolt_ret_set_statement(zval * ret,zval * assignments)166 static void phvolt_ret_set_statement(zval *ret, zval *assignments)
167 {
168 	array_init(ret);
169 	add_assoc_long(ret, "type", PHVOLT_T_SET);
170 
171 	add_assoc_zval(ret, "assignments", assignments);
172 }
173 
phvolt_ret_set_assignment(zval * ret,zval * assignable_expr,int operator,zval * expr,phvolt_scanner_state * state)174 static void phvolt_ret_set_assignment(zval *ret, zval *assignable_expr, int operator, zval *expr, phvolt_scanner_state *state)
175 {
176 
177 	array_init(ret);
178 
179 	add_assoc_zval(ret, "variable", assignable_expr);
180 	add_assoc_long(ret, "op", operator);
181 	add_assoc_zval(ret, "expr", expr);
182 
183 	Z_TRY_ADDREF_P(state->active_file);
184 	add_assoc_zval(ret, "file", state->active_file);
185 	add_assoc_long(ret, "line", state->active_line);
186 }
187 
phvolt_ret_echo_statement(zval * ret,zval * expr,phvolt_scanner_state * state)188 static void phvolt_ret_echo_statement(zval *ret, zval *expr, phvolt_scanner_state *state)
189 {
190 	array_init(ret);
191 	add_assoc_long(ret, "type", PHVOLT_T_ECHO);
192 	add_assoc_zval(ret, "expr", expr);
193 
194 	Z_TRY_ADDREF_P(state->active_file);
195 	add_assoc_zval(ret, "file", state->active_file);
196 	add_assoc_long(ret, "line", state->active_line);
197 }
198 
phvolt_ret_block_statement(zval * ret,phvolt_parser_token * name,zval * block_statements,phvolt_scanner_state * state)199 static void phvolt_ret_block_statement(zval *ret, phvolt_parser_token *name, zval *block_statements, phvolt_scanner_state *state)
200 {
201 	array_init(ret);
202 
203 	add_assoc_long(ret, "type", PHVOLT_T_BLOCK);
204 
205 	phvolt_add_assoc_stringl(ret, "name", name->token, name->token_len, 0);
206 	efree(name->token);
207 	efree(name);
208 
209 	if (block_statements) {
210 		add_assoc_zval(ret, "block_statements", block_statements);
211 	}
212 
213 	Z_TRY_ADDREF_P(state->active_file);
214 	add_assoc_zval(ret, "file", state->active_file);
215 	add_assoc_long(ret, "line", state->active_line);
216 }
217 
phvolt_ret_macro_statement(zval * ret,phvolt_parser_token * macro_name,zval * parameters,zval * block_statements,phvolt_scanner_state * state)218 static void phvolt_ret_macro_statement(zval *ret, phvolt_parser_token *macro_name, zval *parameters, zval *block_statements, phvolt_scanner_state *state)
219 {
220 	array_init(ret);
221 	add_assoc_long(ret, "type", PHVOLT_T_MACRO);
222 
223 	phvolt_add_assoc_stringl(ret, "name", macro_name->token, macro_name->token_len, 0);
224 	efree(macro_name->token);
225 	efree(macro_name);
226 
227 	if (parameters) {
228 		add_assoc_zval(ret, "parameters", parameters);
229 	}
230 
231 	if (block_statements) {
232 		add_assoc_zval(ret, "block_statements", block_statements);
233 	}
234 
235 	Z_TRY_ADDREF_P(state->active_file);
236 	add_assoc_zval(ret, "file", state->active_file);
237 	add_assoc_long(ret, "line", state->active_line);
238 }
239 
phvolt_ret_macro_parameter(zval * ret,phvolt_parser_token * variable,zval * default_value,phvolt_scanner_state * state)240 static void phvolt_ret_macro_parameter(zval *ret, phvolt_parser_token *variable, zval *default_value, phvolt_scanner_state *state)
241 {
242 	array_init(ret);
243 
244 	phvolt_add_assoc_stringl(ret, "variable", variable->token, variable->token_len, 0);
245 	efree(variable->token);
246 	efree(variable);
247 
248 	if (default_value) {
249 		add_assoc_zval(ret, "default", default_value);
250 	}
251 
252 	Z_TRY_ADDREF_P(state->active_file);
253 	add_assoc_zval(ret, "file", state->active_file);
254 	add_assoc_long(ret, "line", state->active_line);
255 }
256 
phvolt_ret_extends_statement(zval * ret,zval * path,phvolt_scanner_state * state)257 static void phvolt_ret_extends_statement(zval *ret, zval *path, phvolt_scanner_state *state)
258 {
259 	array_init(ret);
260 
261 	add_assoc_long(ret, "type", PHVOLT_T_EXTENDS);
262 	add_assoc_zval(ret, "path", path);
263 
264 	Z_TRY_ADDREF_P(state->active_file);
265 	add_assoc_zval(ret, "file", state->active_file);
266 	add_assoc_long(ret, "line", state->active_line);
267 }
268 
phvolt_ret_include_statement(zval * ret,zval * path,zval * params,phvolt_scanner_state * state)269 static void phvolt_ret_include_statement(zval *ret, zval *path, zval *params, phvolt_scanner_state *state)
270 {
271 	array_init(ret);
272 
273 	add_assoc_long(ret, "type", PHVOLT_T_INCLUDE);
274 
275 	add_assoc_zval(ret, "path", path);
276 	if (params) {
277 		add_assoc_zval(ret, "params", params);
278 	}
279 
280 	Z_TRY_ADDREF_P(state->active_file);
281 	add_assoc_zval(ret, "file", state->active_file);
282 	add_assoc_long(ret, "line", state->active_line);
283 }
284 
phvolt_ret_do_statement(zval * ret,zval * expr,phvolt_scanner_state * state)285 static void phvolt_ret_do_statement(zval *ret, zval *expr, phvolt_scanner_state *state)
286 {
287 	array_init(ret);
288 
289 	add_assoc_long(ret, "type", PHVOLT_T_DO);
290 	add_assoc_zval(ret, "expr", expr);
291 
292 	Z_TRY_ADDREF_P(state->active_file);
293 	add_assoc_zval(ret, "file", state->active_file);
294 	add_assoc_long(ret, "line", state->active_line);
295 }
296 
phvolt_ret_return_statement(zval * ret,zval * expr,phvolt_scanner_state * state)297 static void phvolt_ret_return_statement(zval *ret, zval *expr, phvolt_scanner_state *state)
298 {
299 	array_init(ret);
300 
301 	add_assoc_long(ret, "type", PHVOLT_T_RETURN);
302 	add_assoc_zval(ret, "expr", expr);
303 
304 	Z_TRY_ADDREF_P(state->active_file);
305 	add_assoc_zval(ret, "file", state->active_file);
306 	add_assoc_long(ret, "line", state->active_line);
307 }
308 
phvolt_ret_autoescape_statement(zval * ret,int enable,zval * block_statements,phvolt_scanner_state * state)309 static void phvolt_ret_autoescape_statement(zval *ret, int enable, zval *block_statements, phvolt_scanner_state *state)
310 {
311 	array_init(ret);
312 
313 	add_assoc_long(ret, "type", PHVOLT_T_AUTOESCAPE);
314 	add_assoc_long(ret, "enable", enable);
315 	add_assoc_zval(ret, "block_statements", block_statements);
316 
317 	Z_TRY_ADDREF_P(state->active_file);
318 	add_assoc_zval(ret, "file", state->active_file);
319 	add_assoc_long(ret, "line", state->active_line);
320 }
321 
phvolt_ret_empty_statement(zval * ret,phvolt_scanner_state * state)322 static void phvolt_ret_empty_statement(zval *ret, phvolt_scanner_state *state)
323 {
324 	array_init(ret);
325 	add_assoc_long(ret, "type", PHVOLT_T_EMPTY_STATEMENT);
326 
327 	Z_TRY_ADDREF_P(state->active_file);
328 	add_assoc_zval(ret, "file", state->active_file);
329 	add_assoc_long(ret, "line", state->active_line);
330 }
331 
phvolt_ret_break_statement(zval * ret,phvolt_scanner_state * state)332 static void phvolt_ret_break_statement(zval *ret, phvolt_scanner_state *state)
333 {
334 	array_init(ret);
335 	add_assoc_long(ret, "type", PHVOLT_T_BREAK);
336 
337 	Z_TRY_ADDREF_P(state->active_file);
338 	add_assoc_zval(ret, "file", state->active_file);
339 	add_assoc_long(ret, "line", state->active_line);
340 }
341 
phvolt_ret_continue_statement(zval * ret,phvolt_scanner_state * state)342 static void phvolt_ret_continue_statement(zval *ret, phvolt_scanner_state *state)
343 {
344 	array_init(ret);
345 	add_assoc_long(ret, "type", PHVOLT_T_CONTINUE);
346 
347 	Z_TRY_ADDREF_P(state->active_file);
348 	add_assoc_zval(ret, "file", state->active_file);
349 	add_assoc_long(ret, "line", state->active_line);
350 }
351 
phvolt_ret_zval_list(zval * ret,zval * list_left,zval * right_list)352 static void phvolt_ret_zval_list(zval *ret, zval *list_left, zval *right_list)
353 {
354 	HashTable *list;
355 
356 	array_init(ret);
357 
358 	if (list_left) {
359 
360 		list = Z_ARRVAL_P(list_left);
361 		if (zend_hash_index_exists(list, 0)) {
362 			{
363 				zval *item;
364 				ZEND_HASH_FOREACH_VAL(list, item) {
365 
366 					Z_TRY_ADDREF_P(item);
367 					add_next_index_zval(ret, item);
368 
369 				} ZEND_HASH_FOREACH_END();
370 			}
371 			zval_dtor(list_left);
372 		} else {
373 			add_next_index_zval(ret, list_left);
374 		}
375 	}
376 
377 	add_next_index_zval(ret, right_list);
378 }
379 
phvolt_ret_named_item(zval * ret,phvolt_parser_token * name,zval * expr,phvolt_scanner_state * state)380 static void phvolt_ret_named_item(zval *ret, phvolt_parser_token *name, zval *expr, phvolt_scanner_state *state)
381 {
382 	array_init(ret);
383 	add_assoc_zval(ret, "expr", expr);
384 	if (name != NULL) {
385 		phvolt_add_assoc_stringl(ret, "name", name->token, name->token_len, 0);
386 		efree(name->token);
387 		efree(name);
388 	}
389 
390 	Z_TRY_ADDREF_P(state->active_file);
391 	add_assoc_zval(ret, "file", state->active_file);
392 	add_assoc_long(ret, "line", state->active_line);
393 }
394 
phvolt_ret_expr(zval * ret,int type,zval * left,zval * right,zval * ternary,phvolt_scanner_state * state)395 static void phvolt_ret_expr(zval *ret, int type, zval *left, zval *right, zval *ternary, phvolt_scanner_state *state)
396 {
397 	array_init(ret);
398 	add_assoc_long(ret, "type", type);
399 
400 	if (ternary) {
401 		add_assoc_zval(ret, "ternary", ternary);
402 	}
403 
404 	if (left) {
405 		add_assoc_zval(ret, "left", left);
406 	}
407 
408 	if (right) {
409 		add_assoc_zval(ret, "right", right);
410 	}
411 
412 	Z_TRY_ADDREF_P(state->active_file);
413 	add_assoc_zval(ret, "file", state->active_file);
414 	add_assoc_long(ret, "line", state->active_line);
415 }
416 
phvolt_ret_slice(zval * ret,zval * left,zval * start,zval * end,phvolt_scanner_state * state)417 static void phvolt_ret_slice(zval *ret, zval *left, zval *start, zval *end, phvolt_scanner_state *state)
418 {
419 	array_init(ret);
420 	add_assoc_long(ret, "type", PHVOLT_T_SLICE);
421 	add_assoc_zval(ret, "left", left);
422 
423 	if (start != NULL) {
424 		add_assoc_zval(ret, "start", start);
425 	}
426 
427 	if (end != NULL) {
428 		add_assoc_zval(ret, "end", end);
429 	}
430 
431 	Z_TRY_ADDREF_P(state->active_file);
432 	add_assoc_zval(ret, "file", state->active_file);
433 	add_assoc_long(ret, "line", state->active_line);
434 }
435 
phvolt_ret_func_call(zval * ret,zval * expr,zval * arguments,phvolt_scanner_state * state)436 static void phvolt_ret_func_call(zval *ret, zval *expr, zval *arguments, phvolt_scanner_state *state)
437 {
438 
439 	array_init(ret);
440 	add_assoc_long(ret, "type", PHVOLT_T_FCALL);
441 	add_assoc_zval(ret, "name", expr);
442 
443 	if (arguments) {
444 		add_assoc_zval(ret, "arguments", arguments);
445 	}
446 
447 	Z_TRY_ADDREF_P(state->active_file);
448 	add_assoc_zval(ret, "file", state->active_file);
449 	add_assoc_long(ret, "line", state->active_line);
450 }
451 
phvolt_ret_macro_call_statement(zval * ret,zval * expr,zval * arguments,zval * caller,phvolt_scanner_state * state)452 static void phvolt_ret_macro_call_statement(zval *ret, zval *expr, zval *arguments, zval *caller, phvolt_scanner_state *state)
453 {
454 
455 	array_init(ret);
456 	add_assoc_long(ret, "type", PHVOLT_T_CALL);
457 	add_assoc_zval(ret, "name", expr);
458 
459 	if (arguments) {
460 		add_assoc_zval(ret, "arguments", arguments);
461 	}
462 
463 	if (caller) {
464 		add_assoc_zval(ret, "caller", caller);
465 	}
466 
467 	Z_TRY_ADDREF_P(state->active_file);
468 	add_assoc_zval(ret, "file", state->active_file);
469 	add_assoc_long(ret, "line", state->active_line);
470 }
471