validate: fix type stack and leaks
[m6w6/ext-psi] / src / types / number.c
1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
25
26 #include "php_psi_stdinc.h"
27
28 #include <assert.h>
29
30 #include "data.h"
31 #include "calc.h"
32 #include "call.h"
33 #include "parser.h"
34
35 struct psi_number *psi_number_init(token_t t, void *num, unsigned flags)
36 {
37 struct psi_number *exp = calloc(1, sizeof(*exp));
38
39 exp->flags = flags;
40 switch (exp->type = t) {
41 case PSI_T_INT8:
42 exp->data.ival.i8 = *(int8_t *) num;
43 break;
44 case PSI_T_UINT8:
45 exp->data.ival.u8 = *(uint8_t *) num;
46 break;
47 case PSI_T_INT16:
48 exp->data.ival.i16 = *(int16_t *) num;
49 break;
50 case PSI_T_UINT16:
51 exp->data.ival.u16 = *(uint16_t *) num;
52 break;
53 case PSI_T_INT32:
54 exp->data.ival.i32 = *(int32_t *) num;
55 break;
56 case PSI_T_UINT32:
57 exp->data.ival.u32 = *(uint32_t *) num;
58 break;
59 case PSI_T_INT64:
60 exp->data.ival.i64 = *(int64_t *) num;
61 break;
62 case PSI_T_UINT64:
63 exp->data.ival.u64 = *(uint64_t *) num;
64 break;
65 case PSI_T_FLOAT:
66 exp->data.ival.dval = *(float *) num;
67 exp->type = PSI_T_DOUBLE;
68 break;
69 case PSI_T_DOUBLE:
70 exp->data.ival.dval = *(double *) num;
71 break;
72 #if HAVE_LONG_DOUBLE
73 case PSI_T_LONG_DOUBLE:
74 exp->data.ival.ldval = *(long double *) num;
75 break;
76 #endif
77 case PSI_T_NULL:
78 break;
79 case PSI_T_QUOTED_CHAR:
80 case PSI_T_NUMBER:
81 case PSI_T_NSNAME:
82 case PSI_T_DEFINE:
83 exp->data.numb = strdup(num);
84 break;
85 case PSI_T_NAME:
86 exp->data.dvar = num;
87 break;
88 case PSI_T_FUNCTION:
89 exp->data.call = num;
90 break;
91 case PSI_T_SIZEOF:
92 exp->data.dtyp = num;
93 break;
94 default:
95 assert(0);
96 }
97
98 return exp;
99 }
100
101 struct psi_number *psi_number_copy(struct psi_number *exp)
102 {
103 struct psi_number *num = calloc(1, sizeof(*num));
104
105 *num = *exp;
106
107 if (num->token) {
108 num->token = psi_token_copy(num->token);
109 }
110 switch (num->type) {
111 case PSI_T_INT8:
112 case PSI_T_UINT8:
113 case PSI_T_INT16:
114 case PSI_T_UINT16:
115 case PSI_T_INT32:
116 case PSI_T_UINT32:
117 case PSI_T_INT64:
118 case PSI_T_UINT64:
119 case PSI_T_DOUBLE:
120 #if HAVE_LONG_DOUBLE
121 case PSI_T_LONG_DOUBLE:
122 #endif
123 case PSI_T_ENUM:
124 case PSI_T_CONST:
125 case PSI_T_NULL:
126 break;
127 case PSI_T_NUMBER:
128 case PSI_T_NSNAME:
129 case PSI_T_DEFINE:
130 case PSI_T_QUOTED_CHAR:
131 num->data.numb = strdup(num->data.numb);
132 break;
133 case PSI_T_NAME:
134 num->data.dvar = psi_decl_var_copy(num->data.dvar);
135 break;
136 case PSI_T_FUNCTION:
137 num->data.call = psi_cpp_macro_call_copy(num->data.call);
138 break;
139 case PSI_T_SIZEOF:
140 num->data.dtyp = psi_decl_type_copy(num->data.dtyp);
141 break;
142 default:
143 assert(0);
144 }
145 return num;
146 }
147
148 void psi_number_free(struct psi_number **exp_ptr)
149 {
150 if (*exp_ptr) {
151 struct psi_number *exp = *exp_ptr;
152
153 *exp_ptr = NULL;
154 if (exp->token) {
155 free(exp->token);
156 }
157 switch (exp->type) {
158 case PSI_T_INT8:
159 case PSI_T_UINT8:
160 case PSI_T_INT16:
161 case PSI_T_UINT16:
162 case PSI_T_INT32:
163 case PSI_T_UINT32:
164 case PSI_T_INT64:
165 case PSI_T_UINT64:
166 case PSI_T_DOUBLE:
167 #if HAVE_LONG_DOUBLE
168 case PSI_T_LONG_DOUBLE:
169 #endif
170 case PSI_T_ENUM:
171 case PSI_T_CONST:
172 case PSI_T_NULL:
173 break;
174 case PSI_T_FUNCTION:
175 psi_cpp_macro_call_free(&exp->data.call);
176 break;
177 case PSI_T_NSNAME:
178 case PSI_T_NUMBER:
179 case PSI_T_DEFINE:
180 case PSI_T_QUOTED_CHAR:
181 free(exp->data.numb);
182 break;
183 case PSI_T_NAME:
184 psi_decl_var_free(&exp->data.dvar);
185 break;
186 case PSI_T_SIZEOF:
187 psi_decl_type_free(&exp->data.dtyp);
188 break;
189 default:
190 assert(0);
191 }
192 free(exp);
193 }
194 }
195
196 void psi_number_dump(int fd, struct psi_number *exp)
197 {
198 switch (exp->type) {
199 case PSI_T_INT8:
200 dprintf(fd, "%" PRId8, exp->data.ival.i8);
201 break;
202 case PSI_T_UINT8:
203 dprintf(fd, "%" PRIu8, exp->data.ival.u8);
204 break;
205 case PSI_T_INT16:
206 dprintf(fd, "%" PRId16, exp->data.ival.i16);
207 break;
208 case PSI_T_UINT16:
209 dprintf(fd, "%" PRIu16, exp->data.ival.u16);
210 break;
211 case PSI_T_INT32:
212 dprintf(fd, "%" PRId32, exp->data.ival.i32);
213 break;
214 case PSI_T_UINT32:
215 dprintf(fd, "%" PRIu32, exp->data.ival.u32);
216 break;
217 case PSI_T_INT64:
218 dprintf(fd, "%" PRId64, exp->data.ival.i64);
219 break;
220 case PSI_T_UINT64:
221 dprintf(fd, "%" PRIu64, exp->data.ival.u64);
222 break;
223 case PSI_T_FLOAT:
224 dprintf(fd, "%" PRIfval, exp->data.ival.dval);
225 break;
226 case PSI_T_DOUBLE:
227 dprintf(fd, "%" PRIdval, exp->data.ival.dval);
228 break;
229 #if HAVE_LONG_DOUBLE
230 case PSI_T_LONG_DOUBLE:
231 dprintf(fd, "%" PRIldval, exp->data.ival.ldval);
232 break;
233 #endif
234 case PSI_T_NULL:
235 dprintf(fd, "NULL");
236 break;
237 case PSI_T_NUMBER:
238 case PSI_T_NSNAME:
239 case PSI_T_DEFINE:
240 case PSI_T_QUOTED_CHAR:
241 dprintf(fd, "%s", exp->data.numb);
242 break;
243 case PSI_T_FUNCTION:
244 psi_cpp_macro_call_dump(fd, exp->data.call);
245 break;
246 case PSI_T_CONST:
247 dprintf(fd, "%s", exp->data.cnst->name);
248 break;
249 case PSI_T_ENUM:
250 dprintf(fd, "%s", exp->data.enm->name);
251 break;
252 case PSI_T_NAME:
253 psi_decl_var_dump(fd, exp->data.dvar);
254 break;
255 case PSI_T_SIZEOF:
256 psi_decl_type_dump(fd, exp->data.dtyp, 0);
257 break;
258 default:
259 assert(0);
260 }
261 }
262
263 static inline bool psi_number_validate_enum(struct psi_data *data, struct psi_number *exp,
264 struct psi_decl_enum *enm)
265 {
266 size_t i = 0;
267 struct psi_decl_enum_item *itm;
268
269 while (psi_plist_get(enm->items, i++, &itm)) {
270 if (!strcmp(itm->name, exp->data.dvar->name)) {
271 psi_decl_var_free(&exp->data.dvar);
272 exp->type = PSI_T_ENUM;
273 exp->data.enm = itm;
274 return psi_number_validate(data, exp, NULL, NULL, NULL, NULL, enm);
275 }
276 }
277
278 return false;
279 }
280
281 static inline token_t validate_char(char *numb, impl_val *res, unsigned *lvl)
282 {
283 char *endptr;
284 token_t typ = PSI_T_INT8;
285
286 res->i8 = numb[0];
287 endptr = &numb[1];
288
289 switch(res->i8) {
290 case '\\':
291 res->i8 = numb[1];
292 endptr = &numb[2];
293
294 switch(res->i8) {
295 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
296 res->i8 = strtol(&numb[1], &endptr, 8);
297 break;
298
299 case 'x':
300 res->i8 = strtol(&numb[2], &endptr, 16);
301 break;
302
303 case 'a':
304 res->i8 = '\a';
305 break;
306 case 'b':
307 res->i8 = '\b';
308 break;
309 case 'f':
310 res->i8 = '\f';
311 break;
312 case 'n':
313 res->i8 = '\n';
314 break;
315 case 'r':
316 res->i8 = '\r';
317 break;
318 case 't':
319 res->i8 = '\t';
320 break;
321 case 'v':
322 res->i8 = '\v';
323 break;
324 default:
325 break;
326 }
327 break;
328 default:
329 break;
330 }
331
332 /* more to grok? */
333 if (*endptr) {
334 impl_val tmp_val = {0};
335 token_t tmp_typ = validate_char(endptr, &tmp_val, lvl);
336
337 if (!tmp_typ) {
338 return 0;
339 }
340
341 res->i32 = res->i8 << (8 * *lvl);
342 typ = psi_calc_add(PSI_T_INT32, res, tmp_typ, &tmp_val, res);
343 }
344
345 ++(*lvl);
346
347 return typ;
348 }
349 static inline bool psi_number_validate_char(struct psi_data *data, struct psi_number *exp)
350 {
351 impl_val val = {0};
352 unsigned lvl = 1;
353 token_t typ = validate_char(exp->data.numb, &val, &lvl);
354
355 if (!typ) {
356 return false;
357 }
358
359 free(exp->data.numb);
360 exp->type = typ;
361 exp->data.ival = val;
362 return true;
363 }
364
365 static inline bool psi_number_validate_number(struct psi_data *data, struct psi_number *exp)
366 {
367 impl_val tmp = {0};
368
369 if (exp->flags) {
370 switch (exp->flags & 0x0f) {
371 case PSI_NUMBER_INT:
372 switch (exp->flags & 0x0f00) {
373 case PSI_NUMBER_L:
374 default:
375 tmp.i64 = strtol(exp->data.numb, NULL, 0);
376 free(exp->data.numb);
377 exp->type = PSI_T_INT64;
378 exp->data.ival.i64 = tmp.i64;
379 break;
380 case PSI_NUMBER_LL:
381 tmp.i64 = strtoll(exp->data.numb, NULL, 0);
382 free(exp->data.numb);
383 exp->type = PSI_T_INT64;
384 exp->data.ival.i64 = tmp.i64;
385 break;
386 case PSI_NUMBER_U:
387 case PSI_NUMBER_UL:
388 tmp.u64 = strtoul(exp->data.numb, NULL, 0);
389 free(exp->data.numb);
390 exp->type = PSI_T_UINT64;
391 exp->data.ival.u64 = tmp.u64;
392 break;
393 case PSI_NUMBER_ULL:
394 tmp.u64 = strtoull(exp->data.numb, NULL, 0);
395 free(exp->data.numb);
396 exp->type = PSI_T_UINT64;
397 exp->data.ival.u64 = tmp.u64;
398 break;
399 }
400 return true;
401
402 case PSI_NUMBER_FLT:
403 switch (exp->flags & 0x0ff00) {
404 case PSI_NUMBER_F:
405 case PSI_NUMBER_DF:
406 tmp.fval = strtof(exp->data.numb, NULL);
407 free(exp->data.numb);
408 exp->type = PSI_T_FLOAT;
409 exp->data.ival.fval = tmp.fval;
410 break;
411 case PSI_NUMBER_L:
412 case PSI_NUMBER_DL:
413 #if HAVE_LONG_DOUBLE
414 tmp.ldval = strtold(exp->data.numb, NULL);
415 free(exp->data.numb);
416 exp->type = PSI_T_LONG_DOUBLE;
417 exp->data.ival.ldval = tmp.ldval;
418 break;
419 #endif
420 case PSI_NUMBER_DD:
421 default:
422 tmp.dval = strtod(exp->data.numb, NULL);
423 free(exp->data.numb);
424 exp->type = PSI_T_DOUBLE;
425 exp->data.ival.dval = tmp.dval;
426 break;
427 }
428 return true;
429 default:
430 assert(0);
431 break;
432 }
433 } else {
434 switch (is_numeric_string(exp->data.numb, strlen(exp->data.numb), (zend_long *) &tmp, (double *) &tmp, 1)) {
435 case IS_LONG:
436 free(exp->data.numb);
437 exp->type = PSI_T_INT64;
438 exp->data.ival.i64 = tmp.zend.lval;
439 return true;
440
441 case IS_DOUBLE:
442 free(exp->data.numb);
443 exp->type = PSI_T_DOUBLE;
444 exp->data.ival.dval = tmp.dval;
445 return true;
446 }
447 }
448 data->error(data, exp->token, PSI_WARNING, "Expected numeric entity (parser error?)");
449 return false;
450
451 }
452 bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
453 struct psi_impl *impl, struct psi_decl *cb_decl, struct psi_let_exp *current_let,
454 struct psi_set_exp *current_set, struct psi_decl_enum *current_enum)
455 {
456 size_t i = 0;
457 struct psi_const *cnst;
458 struct psi_decl_enum *enm;
459
460 switch (exp->type) {
461 case PSI_T_NULL:
462 exp->type = PSI_T_UINT8;
463 /* no break */
464 case PSI_T_CONST:
465 case PSI_T_INT8:
466 case PSI_T_UINT8:
467 case PSI_T_INT16:
468 case PSI_T_UINT16:
469 case PSI_T_INT32:
470 case PSI_T_UINT32:
471 case PSI_T_INT64:
472 case PSI_T_UINT64:
473 case PSI_T_DOUBLE:
474 #if HAVE_LONG_DOUBLE
475 case PSI_T_LONG_DOUBLE:
476 #endif
477 case PSI_T_ENUM:
478 case PSI_T_DEFINE:
479 case PSI_T_FUNCTION:
480 return true;
481
482 case PSI_T_NAME:
483 if (current_enum && psi_number_validate_enum(data, exp, current_enum)) {
484 return true;
485 }
486 while (psi_plist_get(data->enums, i++, &enm)) {
487 if (psi_number_validate_enum(data, exp, enm)) {
488 return true;
489 }
490 }
491 if (exp->data.dvar->arg) {
492 return true;
493 }
494 if (psi_decl_var_validate(data, exp->data.dvar, impl,
495 impl ? impl->decl : NULL, current_let, current_set)) {
496 return true;
497 }
498 if (cb_decl && psi_decl_var_validate(data, exp->data.dvar,
499 NULL, cb_decl, NULL, NULL)) {
500 return true;
501 }
502 data->error(data, exp->token, PSI_WARNING,
503 "Unknown variable '%s' in numeric expression",
504 exp->data.dvar->name);
505 return false;
506
507 case PSI_T_SIZEOF:
508 if (psi_decl_type_validate(data, exp->data.dtyp, 0, NULL)) {
509 struct psi_decl_type *dtyp = exp->data.dtyp;
510
511 exp->type = PSI_T_UINT64;
512 exp->data.ival.u64 = psi_decl_type_get_size(dtyp, NULL);
513 psi_decl_type_free(&dtyp);
514 return true;
515 } else {
516 data->error(data, exp->token, PSI_WARNING,
517 "Cannot compute sizeof(%s) (%u)",
518 exp->data.dtyp->name, exp->data.dtyp->type);
519 }
520 break;
521
522 case PSI_T_NSNAME:
523 while (psi_plist_get(data->consts, i++, &cnst)) {
524 if (!strcmp(cnst->name, exp->data.numb)) {
525 free(exp->data.numb);
526 exp->type = PSI_T_CONST;
527 exp->data.cnst = cnst;
528 return true;
529 }
530 }
531 data->error(data, exp->token, PSI_WARNING,
532 "Unknown constant '%s' in numeric expression",
533 exp->data.numb);
534 return false;
535
536 case PSI_T_NUMBER:
537 return psi_number_validate_number(data, exp);
538
539 case PSI_T_QUOTED_CHAR:
540 return psi_number_validate_char(data, exp);
541
542 default:
543 assert(0);
544 }
545
546 return false;
547 }
548
549 #include "Zend/zend_constants.h"
550
551 static inline token_t psi_number_eval_constant(struct psi_number *exp,
552 impl_val *res, struct psi_call_frame *frame)
553 {
554 switch (exp->data.cnst->type->type) {
555 case PSI_T_INT:
556 res->i64 = zend_get_constant_str(exp->data.cnst->name,
557 strlen(exp->data.cnst->name))->value.lval;
558 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
559 return PSI_T_INT64;
560 case PSI_T_FLOAT:
561 res->dval = zend_get_constant_str(exp->data.cnst->name,
562 strlen(exp->data.cnst->name))->value.dval;
563 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
564 return PSI_T_DOUBLE;
565 default:
566 if (frame) PSI_DEBUG_PRINT(frame->context, " ?(t=%u)", exp->data.cnst->type->type);
567 return 0;
568 }
569 }
570
571
572 static inline token_t psi_number_eval_decl_var(struct psi_number *exp,
573 impl_val *res, struct psi_call_frame *frame)
574 {
575 impl_val *ref;
576 struct psi_call_frame_symbol *sym;
577 struct psi_decl_type *real;
578 struct psi_decl_var *var;
579 size_t size;
580
581 var = exp->data.dvar;
582 real = psi_decl_type_get_real(var->arg->type);
583 size = psi_decl_arg_get_size(var->arg);
584 sym = psi_call_frame_fetch_symbol(frame, var);
585 ref = deref_impl_val(sym->ptr, var);
586
587 memcpy(res, ref, size);
588
589 if (var->arg->var->pointer_level > var->pointer_level) {
590 switch (SIZEOF_VOID_P) {
591 case 4:
592 return PSI_T_INT32;
593 case 8:
594 return PSI_T_INT64;
595 default:
596 assert(0);
597 }
598 }
599 return real->type;
600 }
601
602 static inline token_t psi_number_eval_define(struct psi_number *exp,
603 impl_val *res, HashTable *defs)
604 {
605 struct psi_cpp_macro_decl *macro = zend_hash_str_find_ptr(defs, exp->data.numb, strlen(exp->data.numb));
606
607 assert(!macro);
608
609 res->u8 = 0;
610 return PSI_T_UINT8;
611 }
612
613 token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_frame *frame, HashTable *defs)
614 {
615 switch (exp->type) {
616 case PSI_T_INT8:
617 *res = exp->data.ival;
618 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8);
619 return PSI_T_INT8;
620 case PSI_T_UINT8:
621 *res = exp->data.ival;
622 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu8, res->u8);
623 return PSI_T_UINT8;
624 case PSI_T_INT16:
625 *res = exp->data.ival;
626 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi16, res->i16);
627 return PSI_T_INT16;
628 case PSI_T_UINT16:
629 *res = exp->data.ival;
630 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu16, res->u16);
631 return PSI_T_UINT16;
632 case PSI_T_INT32:
633 *res = exp->data.ival;
634 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi32, res->i32);
635 return PSI_T_INT32;
636 case PSI_T_UINT32:
637 *res = exp->data.ival;
638 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu32, res->u32);
639 return PSI_T_UINT32;
640 case PSI_T_INT64:
641 *res = exp->data.ival;
642 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
643 return PSI_T_INT64;
644 case PSI_T_UINT64:
645 *res = exp->data.ival;
646 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu64, res->u64);
647 return PSI_T_UINT64;
648
649 case PSI_T_DOUBLE:
650 *res = exp->data.ival;
651 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
652 return exp->type;
653
654 #if HAVE_LONG_DOUBLE
655 case PSI_T_LONG_DOUBLE:
656 *res = exp->data.ival;
657 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIldval, res->ldval);
658 return exp->type;
659 #endif
660
661 case PSI_T_ENUM:
662 res->i64 = exp->data.enm->val;
663 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
664 return PSI_T_INT64;
665
666 case PSI_T_NUMBER:
667 res->i64 = atol(exp->data.numb);
668 return PSI_T_INT64;
669
670 case PSI_T_CONST:
671 return psi_number_eval_constant(exp, res, frame);
672
673 case PSI_T_NAME:
674 return psi_number_eval_decl_var(exp, res, frame);
675
676 case PSI_T_DEFINE:
677 return psi_number_eval_define(exp, res, defs);
678
679 case PSI_T_FUNCTION:
680 res->u8 = 0;
681 return PSI_T_UINT8;
682
683 default:
684 assert(0);
685 }
686 return 0;
687 }