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_str.h>
11 
12 #include "parser.php5.h"
13 #include "scanner.h"
14 #include "volt.h"
15 
16 #include "kernel/main.h"
17 #include "kernel/memory.h"
18 #include "kernel/fcall.h"
19 #include "kernel/exception.h"
20 
21 #define PHVOLT_DEFINE_INIT_ZVAL(var) zval *var; MAKE_STD_ZVAL(var);
22 #define phvolt_add_assoc_stringl(var, index, str, len, copy) add_assoc_stringl(var, index, str, len, copy);
23 #define PHVOLT_ADDREF_P(var) Z_ADDREF_P(var)
24 
phvolt_ret_literal_zval(int type,phvolt_parser_token * T,phvolt_scanner_state * state)25 static zval *phvolt_ret_literal_zval(int type, phvolt_parser_token *T, phvolt_scanner_state *state)
26 {
27 	PHVOLT_DEFINE_INIT_ZVAL(ret);
28 
29 	array_init_size(ret, 5);
30 	add_assoc_long(ret, "type", type);
31 	if (T) {
32 		phvolt_add_assoc_stringl(ret, "value", T->token, T->token_len, 0);
33 		//efree(T->token);
34 		efree(T);
35 	}
36 
37 	PHVOLT_ADDREF_P(state->active_file);
38 
39 	add_assoc_zval(ret, "file", state->active_file);
40 	add_assoc_long(ret, "line", state->active_line);
41 
42 	return ret;
43 }
44 
phvolt_ret_if_statement(zval * expr,zval * true_statements,zval * false_statements,phvolt_scanner_state * state)45 static zval *phvolt_ret_if_statement(zval *expr, zval *true_statements, zval *false_statements, phvolt_scanner_state *state)
46 {
47 	PHVOLT_DEFINE_INIT_ZVAL(ret);
48 
49 	array_init_size(ret, 7);
50 	add_assoc_long(ret, "type", PHVOLT_T_IF);
51 	add_assoc_zval(ret, "expr", expr);
52 
53 	if (true_statements) {
54 		add_assoc_zval(ret, "true_statements", true_statements);
55 	}
56 	if (false_statements) {
57 		add_assoc_zval(ret, "false_statements", false_statements);
58 	}
59 
60 	PHVOLT_ADDREF_P(state->active_file);
61 
62 	add_assoc_zval(ret, "file", state->active_file);
63 	add_assoc_long(ret, "line", state->active_line);
64 
65 	return ret;
66 }
67 
phvolt_ret_elseif_statement(zval * expr,phvolt_scanner_state * state)68 static zval *phvolt_ret_elseif_statement(zval *expr, phvolt_scanner_state *state)
69 {
70 	PHVOLT_DEFINE_INIT_ZVAL(ret);
71 
72 	array_init_size(ret, 5);
73 	add_assoc_long(ret, "type", PHVOLT_T_ELSEIF);
74 	add_assoc_zval(ret, "expr", expr);
75 
76 	PHVOLT_ADDREF_P(state->active_file);
77 
78 	add_assoc_zval(ret, "file", state->active_file);
79 	add_assoc_long(ret, "line", state->active_line);
80 
81 	return ret;
82 }
83 
phvolt_ret_elsefor_statement(phvolt_scanner_state * state)84 static zval *phvolt_ret_elsefor_statement(phvolt_scanner_state *state)
85 {
86 	PHVOLT_DEFINE_INIT_ZVAL(ret);
87 
88 	array_init_size(ret, 4);
89 	add_assoc_long(ret, "type", PHVOLT_T_ELSEFOR);
90 
91 	PHVOLT_ADDREF_P(state->active_file);
92 
93 	add_assoc_zval(ret, "file", state->active_file);
94 	add_assoc_long(ret, "line", state->active_line);
95 
96 	return ret;
97 }
98 
phvolt_ret_switch_statement(zval * expr,zval * case_clauses,phvolt_scanner_state * state)99 static zval *phvolt_ret_switch_statement(zval *expr, zval *case_clauses, phvolt_scanner_state *state)
100 {
101 	PHVOLT_DEFINE_INIT_ZVAL(ret);
102 
103 	array_init_size(ret, 6);
104 
105 	add_assoc_long(ret, "type", PHVOLT_T_SWITCH);
106 	add_assoc_zval(ret, "expr", expr);
107 
108 	if (case_clauses) {
109 		add_assoc_zval(ret, "case_clauses", case_clauses);
110 	}
111 
112 	PHVOLT_ADDREF_P(state->active_file);
113 
114 	add_assoc_zval(ret, "file", state->active_file);
115 	add_assoc_long(ret, "line", state->active_line);
116 
117 	return ret;
118 }
119 
phvolt_ret_case_clause(zval * expr,phvolt_scanner_state * state)120 static zval *phvolt_ret_case_clause(zval *expr, phvolt_scanner_state *state)
121 {
122 	PHVOLT_DEFINE_INIT_ZVAL(ret);
123 
124 	array_init_size(ret, 5);
125 
126 	if (expr) {
127 		add_assoc_long(ret, "type", PHVOLT_T_CASE);
128 		add_assoc_zval(ret, "expr", expr);
129 	} else {
130 		add_assoc_long(ret, "type", PHVOLT_T_DEFAULT);
131 	}
132 
133 	PHVOLT_ADDREF_P(state->active_file);
134 
135 	add_assoc_zval(ret, "file", state->active_file);
136 	add_assoc_long(ret, "line", state->active_line);
137 
138 	return ret;
139 }
140 
phvolt_ret_for_statement(phvolt_parser_token * variable,phvolt_parser_token * key,zval * expr,zval * if_expr,zval * block_statements,phvolt_scanner_state * state)141 static zval *phvolt_ret_for_statement(phvolt_parser_token *variable, phvolt_parser_token *key, zval *expr, zval *if_expr, zval *block_statements, phvolt_scanner_state *state)
142 {
143 	PHVOLT_DEFINE_INIT_ZVAL(ret);
144 
145 	array_init_size(ret, 9);
146 	add_assoc_long(ret, "type", PHVOLT_T_FOR);
147 
148 	phvolt_add_assoc_stringl(ret, "variable", variable->token, variable->token_len, 0);
149 	//efree(variable->token);
150 	efree(variable);
151 
152 	if (key) {
153 		phvolt_add_assoc_stringl(ret, "key", key->token, key->token_len, 0);
154 		//efree(key->token);
155 		efree(key);
156 	}
157 
158 	add_assoc_zval(ret, "expr", expr);
159 	if (if_expr) {
160 		add_assoc_zval(ret, "if_expr", if_expr);
161 	}
162 
163 	add_assoc_zval(ret, "block_statements", block_statements);
164 
165 	PHVOLT_ADDREF_P(state->active_file);
166 
167 	add_assoc_zval(ret, "file", state->active_file);
168 	add_assoc_long(ret, "line", state->active_line);
169 
170 	return ret;
171 }
172 
phvolt_ret_cache_statement(zval * expr,zval * lifetime,zval * block_statements,phvolt_scanner_state * state)173 static zval *phvolt_ret_cache_statement(zval *expr, zval *lifetime, zval *block_statements, phvolt_scanner_state *state)
174 {
175 	PHVOLT_DEFINE_INIT_ZVAL(ret);
176 
177 	array_init(ret);
178 
179 	add_assoc_long(ret, "type", PHVOLT_T_CACHE);
180 	add_assoc_zval(ret, "expr", expr);
181 
182 	if (lifetime) {
183 		add_assoc_zval(ret, "lifetime", lifetime);
184 	}
185 	add_assoc_zval(ret, "block_statements", block_statements);
186 
187 	PHVOLT_ADDREF_P(state->active_file);
188 
189 	add_assoc_zval(ret, "file", state->active_file);
190 	add_assoc_long(ret, "line", state->active_line);
191 
192 	return ret;
193 }
194 
phvolt_ret_raw_statement(zval * statement,phvolt_scanner_state * state)195 static zval *phvolt_ret_raw_statement(zval *statement, phvolt_scanner_state *state)
196 {
197 	PHVOLT_DEFINE_INIT_ZVAL(ret);
198 
199 	array_init(ret);
200 
201 	add_assoc_long(ret, "type", PHVOLT_T_RAW);
202 	add_assoc_zval(ret, "content", statement);
203 
204 	PHVOLT_ADDREF_P(state->active_file);
205 
206 	add_assoc_zval(ret, "file", state->active_file);
207 	add_assoc_long(ret, "line", state->active_line);
208 
209 	return ret;
210 }
211 
phvolt_ret_set_statement(zval * assignments)212 static zval *phvolt_ret_set_statement(zval *assignments)
213 {
214 	PHVOLT_DEFINE_INIT_ZVAL(ret);
215 
216 	array_init_size(ret, 3);
217 	add_assoc_long(ret, "type", PHVOLT_T_SET);
218 
219 	add_assoc_zval(ret, "assignments", assignments);
220 
221 	return ret;
222 }
223 
phvolt_ret_set_assignment(zval * assignable_expr,int operator,zval * expr,phvolt_scanner_state * state)224 static zval *phvolt_ret_set_assignment(zval *assignable_expr, int operator, zval *expr, phvolt_scanner_state *state)
225 {
226 
227 	PHVOLT_DEFINE_INIT_ZVAL(ret);
228 
229 	array_init_size(ret, 5);
230 
231 	add_assoc_zval(ret, "variable", assignable_expr);
232 	add_assoc_long(ret, "op", operator);
233 	add_assoc_zval(ret, "expr", expr);
234 
235 	PHVOLT_ADDREF_P(state->active_file);
236 
237 	add_assoc_zval(ret, "file", state->active_file);
238 	add_assoc_long(ret, "line", state->active_line);
239 
240 	return ret;
241 }
242 
phvolt_ret_echo_statement(zval * expr,phvolt_scanner_state * state)243 static zval *phvolt_ret_echo_statement(zval *expr, phvolt_scanner_state *state)
244 {
245 	PHVOLT_DEFINE_INIT_ZVAL(ret);
246 
247 	array_init_size(ret, 4);
248 	add_assoc_long(ret, "type", PHVOLT_T_ECHO);
249 	add_assoc_zval(ret, "expr", expr);
250 
251 	PHVOLT_ADDREF_P(state->active_file);
252 
253 	add_assoc_zval(ret, "file", state->active_file);
254 	add_assoc_long(ret, "line", state->active_line);
255 
256 	return ret;
257 }
258 
phvolt_ret_block_statement(phvolt_parser_token * name,zval * block_statements,phvolt_scanner_state * state)259 static zval *phvolt_ret_block_statement(phvolt_parser_token *name, zval *block_statements, phvolt_scanner_state *state)
260 {
261 	PHVOLT_DEFINE_INIT_ZVAL(ret);
262 
263 	array_init_size(ret, 6);
264 
265 	add_assoc_long(ret, "type", PHVOLT_T_BLOCK);
266 
267 	phvolt_add_assoc_stringl(ret, "name", name->token, name->token_len, 0);
268 	//efree(name->token);
269 	efree(name);
270 
271 	if (block_statements) {
272 		add_assoc_zval(ret, "block_statements", block_statements);
273 	}
274 
275 	PHVOLT_ADDREF_P(state->active_file);
276 
277 	add_assoc_zval(ret, "file", state->active_file);
278 	add_assoc_long(ret, "line", state->active_line);
279 
280 	return ret;
281 }
282 
phvolt_ret_macro_statement(phvolt_parser_token * macro_name,zval * parameters,zval * block_statements,phvolt_scanner_state * state)283 static zval *phvolt_ret_macro_statement(phvolt_parser_token *macro_name, zval *parameters, zval *block_statements, phvolt_scanner_state *state)
284 {
285 	PHVOLT_DEFINE_INIT_ZVAL(ret);
286 
287 	array_init(ret);
288 	add_assoc_long(ret, "type", PHVOLT_T_MACRO);
289 
290 	phvolt_add_assoc_stringl(ret, "name", macro_name->token, macro_name->token_len, 0);
291 	//efree(macro_name->token);
292 	efree(macro_name);
293 
294 	if (parameters) {
295 		add_assoc_zval(ret, "parameters", parameters);
296 	}
297 
298 	if (block_statements) {
299 		add_assoc_zval(ret, "block_statements", block_statements);
300 	}
301 
302 	PHVOLT_ADDREF_P(state->active_file);
303 
304 	add_assoc_zval(ret, "file", state->active_file);
305 	add_assoc_long(ret, "line", state->active_line);
306 
307 	return ret;
308 }
309 
phvolt_ret_macro_parameter(phvolt_parser_token * variable,zval * default_value,phvolt_scanner_state * state)310 static zval *phvolt_ret_macro_parameter(phvolt_parser_token *variable, zval *default_value, phvolt_scanner_state *state)
311 {
312 	PHVOLT_DEFINE_INIT_ZVAL(ret);
313 
314 	array_init_size(ret, 5);
315 
316 	phvolt_add_assoc_stringl(ret, "variable", variable->token, variable->token_len, 0);
317 	//efree(variable->token);
318 	efree(variable);
319 
320 	if (default_value) {
321 		add_assoc_zval(ret, "default", default_value);
322 	}
323 
324 	PHVOLT_ADDREF_P(state->active_file);
325 
326 	add_assoc_zval(ret, "file", state->active_file);
327 	add_assoc_long(ret, "line", state->active_line);
328 
329 	return ret;
330 }
331 
phvolt_ret_extends_statement(zval * path,phvolt_scanner_state * state)332 static zval *phvolt_ret_extends_statement(zval *path, phvolt_scanner_state *state)
333 {
334 	PHVOLT_DEFINE_INIT_ZVAL(ret);
335 
336 	array_init_size(ret, 4);
337 
338 	add_assoc_long(ret, "type", PHVOLT_T_EXTENDS);
339 	add_assoc_zval(ret, "path", path);
340 
341 	PHVOLT_ADDREF_P(state->active_file);
342 
343 	add_assoc_zval(ret, "file", state->active_file);
344 	add_assoc_long(ret, "line", state->active_line);
345 
346 	return ret;
347 }
348 
phvolt_ret_include_statement(zval * path,zval * params,phvolt_scanner_state * state)349 static zval *phvolt_ret_include_statement(zval *path, zval *params, phvolt_scanner_state *state)
350 {
351 	PHVOLT_DEFINE_INIT_ZVAL(ret);
352 
353 	array_init_size(ret, 5);
354 
355 	add_assoc_long(ret, "type", PHVOLT_T_INCLUDE);
356 
357 	add_assoc_zval(ret, "path", path);
358 	if (params) {
359 		add_assoc_zval(ret, "params", params);
360 	}
361 
362 	PHVOLT_ADDREF_P(state->active_file);
363 
364 	add_assoc_zval(ret, "file", state->active_file);
365 	add_assoc_long(ret, "line", state->active_line);
366 
367 	return ret;
368 }
369 
phvolt_ret_do_statement(zval * expr,phvolt_scanner_state * state)370 static zval *phvolt_ret_do_statement(zval *expr, phvolt_scanner_state *state)
371 {
372 	PHVOLT_DEFINE_INIT_ZVAL(ret);
373 
374 	array_init_size(ret, 5);
375 
376 	add_assoc_long(ret, "type", PHVOLT_T_DO);
377 	add_assoc_zval(ret, "expr", expr);
378 
379 	PHVOLT_ADDREF_P(state->active_file);
380 
381 	add_assoc_zval(ret, "file", state->active_file);
382 	add_assoc_long(ret, "line", state->active_line);
383 
384 	return ret;
385 }
386 
phvolt_ret_return_statement(zval * expr,phvolt_scanner_state * state)387 static zval *phvolt_ret_return_statement(zval *expr, phvolt_scanner_state *state)
388 {
389 	PHVOLT_DEFINE_INIT_ZVAL(ret);
390 
391 	array_init_size(ret, 4);
392 
393 	add_assoc_long(ret, "type", PHVOLT_T_RETURN);
394 	add_assoc_zval(ret, "expr", expr);
395 
396 	PHVOLT_ADDREF_P(state->active_file);
397 
398 	add_assoc_zval(ret, "file", state->active_file);
399 	add_assoc_long(ret, "line", state->active_line);
400 
401 	return ret;
402 }
403 
phvolt_ret_autoescape_statement(int enable,zval * block_statements,phvolt_scanner_state * state)404 static zval *phvolt_ret_autoescape_statement(int enable, zval *block_statements, phvolt_scanner_state *state)
405 {
406 	PHVOLT_DEFINE_INIT_ZVAL(ret);
407 
408 	array_init_size(ret, 5);
409 
410 	add_assoc_long(ret, "type", PHVOLT_T_AUTOESCAPE);
411 	add_assoc_long(ret, "enable", enable);
412 	add_assoc_zval(ret, "block_statements", block_statements);
413 
414 	PHVOLT_ADDREF_P(state->active_file);
415 
416 	add_assoc_zval(ret, "file", state->active_file);
417 	add_assoc_long(ret, "line", state->active_line);
418 
419 	return ret;
420 }
421 
phvolt_ret_empty_statement(phvolt_scanner_state * state)422 static zval *phvolt_ret_empty_statement(phvolt_scanner_state *state)
423 {
424 	PHVOLT_DEFINE_INIT_ZVAL(ret);
425 
426 	array_init_size(ret, 3);
427 	add_assoc_long(ret, "type", PHVOLT_T_EMPTY_STATEMENT);
428 
429 	PHVOLT_ADDREF_P(state->active_file);
430 
431 	add_assoc_zval(ret, "file", state->active_file);
432 	add_assoc_long(ret, "line", state->active_line);
433 
434 	return ret;
435 }
436 
phvolt_ret_break_statement(phvolt_scanner_state * state)437 static zval *phvolt_ret_break_statement(phvolt_scanner_state *state)
438 {
439 	PHVOLT_DEFINE_INIT_ZVAL(ret);
440 
441 	array_init_size(ret, 3);
442 	add_assoc_long(ret, "type", PHVOLT_T_BREAK);
443 
444 	PHVOLT_ADDREF_P(state->active_file);
445 
446 	add_assoc_zval(ret, "file", state->active_file);
447 	add_assoc_long(ret, "line", state->active_line);
448 
449 	return ret;
450 }
451 
phvolt_ret_continue_statement(phvolt_scanner_state * state)452 static zval *phvolt_ret_continue_statement(phvolt_scanner_state *state)
453 {
454 	PHVOLT_DEFINE_INIT_ZVAL(ret);
455 
456 	array_init_size(ret, 3);
457 	add_assoc_long(ret, "type", PHVOLT_T_CONTINUE);
458 
459 	PHVOLT_ADDREF_P(state->active_file);
460 
461 	add_assoc_zval(ret, "file", state->active_file);
462 	add_assoc_long(ret, "line", state->active_line);
463 
464 	return ret;
465 }
466 
phvolt_ret_zval_list(zval * list_left,zval * right_list)467 static zval *phvolt_ret_zval_list(zval *list_left, zval *right_list)
468 {
469 	HashTable *list;
470 
471 	PHVOLT_DEFINE_INIT_ZVAL(ret);
472 
473 	array_init(ret);
474 
475 	if (list_left) {
476 
477 		list = Z_ARRVAL_P(list_left);
478 		if (zend_hash_index_exists(list, 0)) {
479 			{
480 				HashPosition pos;
481 				zend_hash_internal_pointer_reset_ex(list, &pos);
482 				for (;; zend_hash_move_forward_ex(list, &pos)) {
483 
484 					zval ** item;
485 
486 					if (zend_hash_get_current_data_ex(list, (void**) &item, &pos) == FAILURE) {
487 						break;
488 					}
489 
490 					Z_ADDREF_PP(item);
491 					add_next_index_zval(ret, *item);
492 
493 				}
494 				zval_ptr_dtor(&list_left);
495 			}
496 		} else {
497 			add_next_index_zval(ret, list_left);
498 		}
499 	}
500 
501 	add_next_index_zval(ret, right_list);
502 
503 	return ret;
504 }
505 
phvolt_ret_named_item(phvolt_parser_token * name,zval * expr,phvolt_scanner_state * state)506 static zval *phvolt_ret_named_item(phvolt_parser_token *name, zval *expr, phvolt_scanner_state *state)
507 {
508 	PHVOLT_DEFINE_INIT_ZVAL(ret);
509 
510 	array_init(ret);
511 	add_assoc_zval(ret, "expr", expr);
512 	if (name != NULL) {
513 		phvolt_add_assoc_stringl(ret, "name", name->token, name->token_len, 0);
514 		//efree(name->token);
515 		efree(name);
516 	}
517 
518 	PHVOLT_ADDREF_P(state->active_file);
519 
520 	add_assoc_zval(ret, "file", state->active_file);
521 	add_assoc_long(ret, "line", state->active_line);
522 
523 	return ret;
524 }
525 
phvolt_ret_expr(int type,zval * left,zval * right,zval * ternary,phvolt_scanner_state * state)526 static zval *phvolt_ret_expr(int type, zval *left, zval *right, zval *ternary, phvolt_scanner_state *state)
527 {
528 	PHVOLT_DEFINE_INIT_ZVAL(ret);
529 
530 	array_init(ret);
531 	add_assoc_long(ret, "type", type);
532 
533 	if (ternary) {
534 		add_assoc_zval(ret, "ternary", ternary);
535 	}
536 
537 	if (left) {
538 		add_assoc_zval(ret, "left", left);
539 	}
540 
541 	if (right) {
542 		add_assoc_zval(ret, "right", right);
543 	}
544 
545 	PHVOLT_ADDREF_P(state->active_file);
546 
547 	add_assoc_zval(ret, "file", state->active_file);
548 	add_assoc_long(ret, "line", state->active_line);
549 
550 	return ret;
551 }
552 
phvolt_ret_slice(zval * left,zval * start,zval * end,phvolt_scanner_state * state)553 static zval *phvolt_ret_slice(zval *left, zval *start, zval *end, phvolt_scanner_state *state)
554 {
555 	PHVOLT_DEFINE_INIT_ZVAL(ret);
556 
557 	array_init(ret);
558 	add_assoc_long(ret, "type", PHVOLT_T_SLICE);
559 	add_assoc_zval(ret, "left", left);
560 
561 	if (start != NULL) {
562 		add_assoc_zval(ret, "start", start);
563 	}
564 
565 	if (end != NULL) {
566 		add_assoc_zval(ret, "end", end);
567 	}
568 
569 	PHVOLT_ADDREF_P(state->active_file);
570 
571 	add_assoc_zval(ret, "file", state->active_file);
572 	add_assoc_long(ret, "line", state->active_line);
573 
574 	return ret;
575 }
576 
phvolt_ret_func_call(zval * expr,zval * arguments,phvolt_scanner_state * state)577 static zval *phvolt_ret_func_call(zval *expr, zval *arguments, phvolt_scanner_state *state)
578 {
579 
580 	PHVOLT_DEFINE_INIT_ZVAL(ret);
581 
582 	array_init(ret);
583 	add_assoc_long(ret, "type", PHVOLT_T_FCALL);
584 	add_assoc_zval(ret, "name", expr);
585 
586 	if (arguments) {
587 		add_assoc_zval(ret, "arguments", arguments);
588 	}
589 
590 	PHVOLT_ADDREF_P(state->active_file);
591 
592 	add_assoc_zval(ret, "file", state->active_file);
593 	add_assoc_long(ret, "line", state->active_line);
594 
595 	return ret;
596 }
597 
phvolt_ret_macro_call_statement(zval * expr,zval * arguments,zval * caller,phvolt_scanner_state * state)598 static zval *phvolt_ret_macro_call_statement(zval *expr, zval *arguments, zval *caller, phvolt_scanner_state *state)
599 {
600 
601 	PHVOLT_DEFINE_INIT_ZVAL(ret);
602 
603 	array_init(ret);
604 	add_assoc_long(ret, "type", PHVOLT_T_CALL);
605 	add_assoc_zval(ret, "name", expr);
606 
607 	if (arguments) {
608 		add_assoc_zval(ret, "arguments", arguments);
609 	}
610 
611 	if (caller) {
612 		add_assoc_zval(ret, "caller", caller);
613 	}
614 
615 	PHVOLT_ADDREF_P(state->active_file);
616 
617 	add_assoc_zval(ret, "file", state->active_file);
618 	add_assoc_long(ret, "line", state->active_line);
619 
620 	return ret;
621 }
622