sval: update check_snprintf.c
[smatch.git] / smatch_ranges.c
blob0582a9ec67a3a7ae7a5ba39a8041ac4b5bbcc19d
1 /*
2 * sparse/smatch_ranges.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "parse.h"
11 #include "smatch.h"
12 #include "smatch_extra.h"
13 #include "smatch_slist.h"
15 ALLOCATOR(data_info, "smatch extra data");
16 ALLOCATOR(data_range, "data range");
17 __DO_ALLOCATOR(struct data_range, sizeof(struct data_range), __alignof__(struct data_range),
18 "permanent ranges", perm_data_range);
20 struct data_range whole_range = {
21 .min = LLONG_MIN,
22 .max = LLONG_MAX,
25 static char *show_num(long long num)
27 static char buff[256];
29 if (num == whole_range.min)
30 snprintf(buff, 255, "min");
31 else if (num == whole_range.max)
32 snprintf(buff, 255, "max");
33 else if (num < 0)
34 snprintf(buff, 255, "(%lld)", num);
35 else
36 snprintf(buff, 255, "%lld", num);
38 buff[255] = '\0';
39 return buff;
42 char *show_ranges(struct range_list *list)
44 struct data_range *tmp;
45 char full[256];
46 int i = 0;
48 full[0] = '\0';
49 full[255] = '\0';
50 FOR_EACH_PTR(list, tmp) {
51 if (i++)
52 strncat(full, ",", 254 - strlen(full));
53 if (tmp->min == tmp->max) {
54 strncat(full, show_num(tmp->min), 254 - strlen(full));
55 continue;
57 strncat(full, show_num(tmp->min), 254 - strlen(full));
58 strncat(full, "-", 254 - strlen(full));
59 strncat(full, show_num(tmp->max), 254 - strlen(full));
60 } END_FOR_EACH_PTR(tmp);
61 return alloc_sname(full);
64 void get_value_ranges(char *value, struct range_list **rl)
66 long long val1, val2;
67 char *start;
68 char *c;
70 *rl = NULL;
72 c = value;
73 while (*c) {
74 if (*c == '(')
75 c++;
76 start = c;
78 if (!strncmp(start, "max", 3)) {
79 val1 = LLONG_MAX;
80 c += 3;
81 } else if (!strncmp(start, "u64max", 6)) {
82 val1 = LLONG_MAX; // FIXME
83 c += 6;
84 } else if (!strncmp(start, "s64max", 6)) {
85 val1 = LLONG_MAX;
86 c += 6;
87 } else if (!strncmp(start, "u32max", 6)) {
88 val1 = UINT_MAX;
89 c += 6;
90 } else if (!strncmp(start, "s32max", 6)) {
91 val1 = INT_MAX;
92 c += 6;
93 } else if (!strncmp(start, "u16max", 6)) {
94 val1 = USHRT_MAX;
95 c += 6;
96 } else if (!strncmp(start, "s16max", 6)) {
97 val1 = SHRT_MAX;
98 c += 6;
99 } else if (!strncmp(start, "min", 3)) {
100 val1 = LLONG_MIN;
101 c += 3;
102 } else if (!strncmp(start, "s64min", 6)) {
103 val1 = LLONG_MIN;
104 c += 6;
105 } else if (!strncmp(start, "s32min", 6)) {
106 val1 = INT_MIN;
107 c += 6;
108 } else if (!strncmp(start, "s16min", 6)) {
109 val1 = SHRT_MIN;
110 c += 6;
111 } else {
112 while (*c && *c != ',' && *c != '-')
113 c++;
114 val1 = strtoll(start, &c, 10);
116 if (*c == ')')
117 c++;
118 if (!*c) {
119 add_range(rl, val1, val1);
120 break;
122 if (*c == ',') {
123 add_range(rl, val1, val1);
124 c++;
125 start = c;
126 continue;
128 c++; /* skip the dash in eg. 4-5 */
129 if (*c == '(')
130 c++;
131 start = c;
132 if (!strncmp(start, "max", 3)) {
133 val2 = LLONG_MAX;
134 c += 3;
135 } else {
137 while (*c && *c != ',' && *c != '-')
138 c++;
139 val2 = strtoll(start, &c, 10);
141 add_range(rl, val1, val2);
142 if (!*c)
143 break;
144 if (*c == ')')
145 c++;
146 c++; /* skip the comma in eg: 4-5,7 */
150 static struct data_range range_zero = {
151 .min = 0,
152 .max = 0,
155 static struct data_range range_one = {
156 .min = 1,
157 .max = 1,
160 int is_whole_range_rl(struct range_list *rl)
162 struct data_range *drange;
164 if (ptr_list_empty(rl))
165 return 1;
166 drange = first_ptr_list((struct ptr_list *)rl);
167 if (drange->min == whole_range.min && drange->max == whole_range.max)
168 return 1;
169 return 0;
172 int rl_contiguous(struct range_list *rl)
174 if (first_ptr_list((struct ptr_list *)rl) == last_ptr_list((struct ptr_list *)rl))
175 return 1;
176 return 0;
179 long long rl_min(struct range_list *rl)
181 struct data_range *drange;
183 if (ptr_list_empty(rl))
184 return whole_range.min;
185 drange = first_ptr_list((struct ptr_list *)rl);
186 return drange->min;
189 long long rl_max(struct range_list *rl)
191 struct data_range *drange;
193 if (ptr_list_empty(rl))
194 return whole_range.max;
195 drange = last_ptr_list((struct ptr_list *)rl);
196 return drange->max;
199 static struct data_range *alloc_range_helper(long long min, long long max, int perm)
201 struct data_range *ret;
203 if (min > max) {
204 // sm_msg("debug invalid range %lld to %lld", min, max);
205 min = whole_range.min;
206 max = whole_range.max;
208 if (min == whole_range.min && max == whole_range.max)
209 return &whole_range;
210 if (min == 0 && max == 0)
211 return &range_zero;
212 if (min == 1 && max == 1)
213 return &range_one;
215 if (perm)
216 ret = __alloc_perm_data_range(0);
217 else
218 ret = __alloc_data_range(0);
219 ret->min = min;
220 ret->max = max;
221 return ret;
224 struct data_range *alloc_range(long long min, long long max)
226 return alloc_range_helper(min, max, 0);
229 struct data_range *alloc_range_perm(long long min, long long max)
231 return alloc_range_helper(min, max, 1);
234 struct range_list *alloc_range_list(long long min, long long max)
236 struct range_list *rl = NULL;
238 add_range(&rl, min, max);
239 return rl;
242 struct range_list *whole_range_list(void)
244 return alloc_range_list(whole_range.min, whole_range.max);
247 void add_range(struct range_list **list, long long min, long long max)
249 struct data_range *tmp = NULL;
250 struct data_range *new = NULL;
251 int check_next = 0;
254 * FIXME: This has a problem merging a range_list like: min-0,3-max
255 * with a range like 1-2. You end up with min-2,3-max instead of
256 * just min-max.
258 FOR_EACH_PTR(*list, tmp) {
259 if (check_next) {
260 /* Sometimes we overlap with more than one range
261 so we have to delete or modify the next range. */
262 if (max + 1 == tmp->min) {
263 /* join 2 ranges here */
264 new->max = tmp->max;
265 DELETE_CURRENT_PTR(tmp);
266 return;
269 /* Doesn't overlap with the next one. */
270 if (max < tmp->min)
271 return;
272 /* Partially overlaps with the next one. */
273 if (max < tmp->max) {
274 tmp->min = max + 1;
275 return;
277 /* Completely overlaps with the next one. */
278 if (max >= tmp->max) {
279 DELETE_CURRENT_PTR(tmp);
280 /* there could be more ranges to delete */
281 continue;
284 if (max != whole_range.max && max + 1 == tmp->min) {
285 /* join 2 ranges into a big range */
286 new = alloc_range(min, tmp->max);
287 REPLACE_CURRENT_PTR(tmp, new);
288 return;
290 if (max < tmp->min) { /* new range entirely below */
291 new = alloc_range(min, max);
292 INSERT_CURRENT(new, tmp);
293 return;
295 if (min < tmp->min) { /* new range partially below */
296 if (max < tmp->max)
297 max = tmp->max;
298 else
299 check_next = 1;
300 new = alloc_range(min, max);
301 REPLACE_CURRENT_PTR(tmp, new);
302 if (!check_next)
303 return;
304 continue;
306 if (max <= tmp->max) /* new range already included */
307 return;
308 if (min <= tmp->max) { /* new range partially above */
309 min = tmp->min;
310 new = alloc_range(min, max);
311 REPLACE_CURRENT_PTR(tmp, new);
312 check_next = 1;
313 continue;
315 if (min != whole_range.min && min - 1 == tmp->max) {
316 /* join 2 ranges into a big range */
317 new = alloc_range(tmp->min, max);
318 REPLACE_CURRENT_PTR(tmp, new);
319 check_next = 1;
320 continue;
322 /* the new range is entirely above the existing ranges */
323 } END_FOR_EACH_PTR(tmp);
324 if (check_next)
325 return;
326 new = alloc_range(min, max);
327 add_ptr_list(list, new);
330 struct range_list *clone_range_list(struct range_list *list)
332 struct data_range *tmp;
333 struct range_list *ret = NULL;
335 FOR_EACH_PTR(list, tmp) {
336 add_ptr_list(&ret, tmp);
337 } END_FOR_EACH_PTR(tmp);
338 return ret;
341 struct range_list *clone_permanent(struct range_list *list)
343 struct data_range *tmp;
344 struct data_range *new;
345 struct range_list *ret = NULL;
347 FOR_EACH_PTR(list, tmp) {
348 new = alloc_range_perm(tmp->min, tmp->max);
349 add_ptr_list(&ret, new);
350 } END_FOR_EACH_PTR(tmp);
351 return ret;
354 struct range_list *range_list_union(struct range_list *one, struct range_list *two)
356 struct data_range *tmp;
357 struct range_list *ret = NULL;
359 FOR_EACH_PTR(one, tmp) {
360 add_range(&ret, tmp->min, tmp->max);
361 } END_FOR_EACH_PTR(tmp);
362 FOR_EACH_PTR(two, tmp) {
363 add_range(&ret, tmp->min, tmp->max);
364 } END_FOR_EACH_PTR(tmp);
365 return ret;
368 struct range_list *remove_range(struct range_list *list, long long min, long long max)
370 struct data_range *tmp;
371 struct range_list *ret = NULL;
373 FOR_EACH_PTR(list, tmp) {
374 if (tmp->max < min) {
375 add_range(&ret, tmp->min, tmp->max);
376 continue;
378 if (tmp->min > max) {
379 add_range(&ret, tmp->min, tmp->max);
380 continue;
382 if (tmp->min >= min && tmp->max <= max)
383 continue;
384 if (tmp->min >= min) {
385 add_range(&ret, max + 1, tmp->max);
386 } else if (tmp->max <= max) {
387 add_range(&ret, tmp->min, min - 1);
388 } else {
389 add_range(&ret, tmp->min, min - 1);
390 add_range(&ret, max + 1, tmp->max);
392 } END_FOR_EACH_PTR(tmp);
393 return ret;
396 struct range_list *invert_range_list(struct range_list *orig)
398 struct range_list *ret = NULL;
399 struct data_range *tmp;
400 long long gap_min;
402 if (!orig)
403 return NULL;
405 gap_min = whole_range.min;
406 FOR_EACH_PTR(orig, tmp) {
407 if (tmp->min > gap_min)
408 add_range(&ret, gap_min, tmp->min - 1);
409 gap_min = tmp->max + 1;
410 if (tmp->max == whole_range.max)
411 gap_min = whole_range.max;
412 } END_FOR_EACH_PTR(tmp);
414 if (gap_min != whole_range.max)
415 add_range(&ret, gap_min, whole_range.max);
417 return ret;
421 * if it can be only one and only value return 1, else return 0
423 int estate_get_single_value(struct smatch_state *state, long long *val)
425 struct data_info *dinfo;
426 struct data_range *tmp;
427 int count = 0;
429 dinfo = get_dinfo(state);
430 if (!dinfo || dinfo->type != DATA_RANGE)
431 return 0;
433 FOR_EACH_PTR(dinfo->value_ranges, tmp) {
434 if (!count++) {
435 if (tmp->min != tmp->max)
436 return 0;
437 *val = tmp->min;
438 } else {
439 return 0;
441 } END_FOR_EACH_PTR(tmp);
442 return count;
445 int range_lists_equiv(struct range_list *one, struct range_list *two)
447 struct data_range *one_range;
448 struct data_range *two_range;
450 PREPARE_PTR_LIST(one, one_range);
451 PREPARE_PTR_LIST(two, two_range);
452 for (;;) {
453 if (!one_range && !two_range)
454 return 1;
455 if (!one_range || !two_range)
456 return 0;
457 if (one_range->min != two_range->min)
458 return 0;
459 if (one_range->max != two_range->max)
460 return 0;
461 NEXT_PTR_LIST(one_range);
462 NEXT_PTR_LIST(two_range);
464 FINISH_PTR_LIST(two_range);
465 FINISH_PTR_LIST(one_range);
467 return 1;
470 int true_comparison_range(struct data_range *left, int comparison, struct data_range *right)
472 switch (comparison) {
473 case '<':
474 case SPECIAL_UNSIGNED_LT:
475 if (left->min < right->max)
476 return 1;
477 return 0;
478 case SPECIAL_UNSIGNED_LTE:
479 case SPECIAL_LTE:
480 if (left->min <= right->max)
481 return 1;
482 return 0;
483 case SPECIAL_EQUAL:
484 if (left->max < right->min)
485 return 0;
486 if (left->min > right->max)
487 return 0;
488 return 1;
489 case SPECIAL_UNSIGNED_GTE:
490 case SPECIAL_GTE:
491 if (left->max >= right->min)
492 return 1;
493 return 0;
494 case '>':
495 case SPECIAL_UNSIGNED_GT:
496 if (left->max > right->min)
497 return 1;
498 return 0;
499 case SPECIAL_NOTEQUAL:
500 if (left->min != left->max)
501 return 1;
502 if (right->min != right->max)
503 return 1;
504 if (left->min != right->min)
505 return 1;
506 return 0;
507 default:
508 sm_msg("unhandled comparison %d\n", comparison);
509 return 0;
511 return 0;
514 int true_comparison_range_lr(int comparison, struct data_range *var, struct data_range *val, int left)
516 if (left)
517 return true_comparison_range(var, comparison, val);
518 else
519 return true_comparison_range(val, comparison, var);
522 static int false_comparison_range(struct data_range *left, int comparison, struct data_range *right)
524 switch (comparison) {
525 case '<':
526 case SPECIAL_UNSIGNED_LT:
527 if (left->max >= right->min)
528 return 1;
529 return 0;
530 case SPECIAL_UNSIGNED_LTE:
531 case SPECIAL_LTE:
532 if (left->max > right->min)
533 return 1;
534 return 0;
535 case SPECIAL_EQUAL:
536 if (left->min != left->max)
537 return 1;
538 if (right->min != right->max)
539 return 1;
540 if (left->min != right->min)
541 return 1;
542 return 0;
543 case SPECIAL_UNSIGNED_GTE:
544 case SPECIAL_GTE:
545 if (left->min < right->max)
546 return 1;
547 return 0;
548 case '>':
549 case SPECIAL_UNSIGNED_GT:
550 if (left->min <= right->max)
551 return 1;
552 return 0;
553 case SPECIAL_NOTEQUAL:
554 if (left->max < right->min)
555 return 0;
556 if (left->min > right->max)
557 return 0;
558 return 1;
559 default:
560 sm_msg("unhandled comparison %d\n", comparison);
561 return 0;
563 return 0;
566 int false_comparison_range_lr(int comparison, struct data_range *var, struct data_range *val, int left)
568 if (left)
569 return false_comparison_range(var, comparison, val);
570 else
571 return false_comparison_range(val, comparison, var);
574 int possibly_true(struct expression *left, int comparison, struct expression *right)
576 struct range_list *rl_left, *rl_right;
577 struct data_range *tmp_left, *tmp_right;
579 if (!get_implied_range_list(left, &rl_left))
580 return 1;
581 if (!get_implied_range_list(right, &rl_right))
582 return 1;
584 FOR_EACH_PTR(rl_left, tmp_left) {
585 FOR_EACH_PTR(rl_right, tmp_right) {
586 if (true_comparison_range(tmp_left, comparison, tmp_right))
587 return 1;
588 } END_FOR_EACH_PTR(tmp_right);
589 } END_FOR_EACH_PTR(tmp_left);
590 return 0;
593 int possibly_false(struct expression *left, int comparison, struct expression *right)
595 struct range_list *rl_left, *rl_right;
596 struct data_range *tmp_left, *tmp_right;
598 if (!get_implied_range_list(left, &rl_left))
599 return 1;
600 if (!get_implied_range_list(right, &rl_right))
601 return 1;
603 FOR_EACH_PTR(rl_left, tmp_left) {
604 FOR_EACH_PTR(rl_right, tmp_right) {
605 if (false_comparison_range(tmp_left, comparison, tmp_right))
606 return 1;
607 } END_FOR_EACH_PTR(tmp_right);
608 } END_FOR_EACH_PTR(tmp_left);
609 return 0;
612 int possibly_true_range_lists(struct range_list *left_ranges, int comparison, struct range_list *right_ranges)
614 struct data_range *left_tmp, *right_tmp;
616 if (!left_ranges || !right_ranges)
617 return 1;
619 FOR_EACH_PTR(left_ranges, left_tmp) {
620 FOR_EACH_PTR(right_ranges, right_tmp) {
621 if (true_comparison_range(left_tmp, comparison, right_tmp))
622 return 1;
623 } END_FOR_EACH_PTR(right_tmp);
624 } END_FOR_EACH_PTR(left_tmp);
625 return 0;
628 int possibly_false_range_lists(struct range_list *left_ranges, int comparison, struct range_list *right_ranges)
630 struct data_range *left_tmp, *right_tmp;
632 if (!left_ranges || !right_ranges)
633 return 1;
635 FOR_EACH_PTR(left_ranges, left_tmp) {
636 FOR_EACH_PTR(right_ranges, right_tmp) {
637 if (false_comparison_range(left_tmp, comparison, right_tmp))
638 return 1;
639 } END_FOR_EACH_PTR(right_tmp);
640 } END_FOR_EACH_PTR(left_tmp);
641 return 0;
644 int possibly_true_range_lists_rl(int comparison, struct range_list *a, struct range_list *b, int left)
646 if (left)
647 return possibly_true_range_lists(a, comparison, b);
648 else
649 return possibly_true_range_lists(b, comparison, a);
652 int possibly_false_range_lists_rl(int comparison, struct range_list *a, struct range_list *b, int left)
654 if (left)
655 return possibly_false_range_lists(a, comparison, b);
656 else
657 return possibly_false_range_lists(b, comparison, a);
660 void tack_on(struct range_list **list, struct data_range *drange)
662 add_ptr_list(list, drange);
665 int in_list_exact(struct range_list *list, struct data_range *drange)
667 struct data_range *tmp;
669 FOR_EACH_PTR(list, tmp) {
670 if (tmp->min == drange->min && tmp->max == drange->max)
671 return 1;
672 } END_FOR_EACH_PTR(tmp);
673 return 0;
676 void push_range_list(struct range_list_stack **rl_stack, struct range_list *rl)
678 add_ptr_list(rl_stack, rl);
681 struct range_list *pop_range_list(struct range_list_stack **rl_stack)
683 struct range_list *rl;
685 rl = last_ptr_list((struct ptr_list *)*rl_stack);
686 delete_ptr_list_last((struct ptr_list **)rl_stack);
687 return rl;
690 struct range_list *top_range_list(struct range_list_stack *rl_stack)
692 struct range_list *rl;
694 rl = last_ptr_list((struct ptr_list *)rl_stack);
695 return rl;
698 void filter_top_range_list(struct range_list_stack **rl_stack, long long num)
700 struct range_list *rl;
702 rl = pop_range_list(rl_stack);
703 rl = remove_range(rl, num, num);
704 push_range_list(rl_stack, rl);
707 void free_range_list(struct range_list **rlist)
709 __free_ptr_list((struct ptr_list **)rlist);
712 static void free_single_dinfo(struct data_info *dinfo)
714 if (dinfo->type == DATA_RANGE)
715 free_range_list(&dinfo->value_ranges);
718 static void free_dinfos(struct allocation_blob *blob)
720 unsigned int size = sizeof(struct data_info);
721 unsigned int offset = 0;
723 while (offset < blob->offset) {
724 free_single_dinfo((struct data_info *)(blob->data + offset));
725 offset += size;
729 void free_data_info_allocs(void)
731 struct allocator_struct *desc = &data_info_allocator;
732 struct allocation_blob *blob = desc->blobs;
734 desc->blobs = NULL;
735 desc->allocations = 0;
736 desc->total_bytes = 0;
737 desc->useful_bytes = 0;
738 desc->freelist = NULL;
739 while (blob) {
740 struct allocation_blob *next = blob->next;
741 free_dinfos(blob);
742 blob_free(blob, desc->chunking);
743 blob = next;
745 clear_data_range_alloc();