Print this page
11506 smatch resync
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/check_off_by_one_relative.c
+++ new/usr/src/tools/smatch/src/check_off_by_one_relative.c
1 1 /*
2 2 * Copyright (C) 2015 Oracle.
3 3 *
4 4 * This program is free software; you can redistribute it and/or
5 5 * modify it under the terms of the GNU General Public License
6 6 * as published by the Free Software Foundation; either version 2
7 7 * of the License, or (at your option) any later version.
8 8 *
9 9 * This program is distributed in the hope that it will be useful,
10 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 * GNU General Public License for more details.
13 13 *
14 14 * You should have received a copy of the GNU General Public License
15 15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
16 16 */
17 17
18 18 /*
19 19 * The point here is to store that a buffer has x bytes even if we don't know
20 20 * the value of x.
21 21 *
22 22 */
23 23
24 24 #include "smatch.h"
25 25 #include "smatch_slist.h"
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
26 26 #include "smatch_extra.h"
27 27
28 28 static int my_id;
29 29
30 30 static void array_check(struct expression *expr)
31 31 {
32 32 struct expression *array;
33 33 struct expression *size;
34 34 struct expression *offset;
35 35 char *array_str, *offset_str;
36 + int limit_type;
36 37
37 38 expr = strip_expr(expr);
38 39 if (!is_array(expr))
39 40 return;
40 41
41 42 array = get_array_base(expr);
42 - size = get_size_variable(array);
43 - if (!size)
43 + size = get_size_variable(array, &limit_type);
44 + if (!size || limit_type != ELEM_COUNT)
44 45 return;
45 46 offset = get_array_offset(expr);
46 47 if (!possible_comparison(size, SPECIAL_EQUAL, offset))
47 48 return;
48 49
50 + if (buf_comparison_index_ok(expr))
51 + return;
52 +
49 53 array_str = expr_to_str(array);
50 54 offset_str = expr_to_str(offset);
51 55 sm_warning("potentially one past the end of array '%s[%s]'", array_str, offset_str);
52 56 free_string(array_str);
53 57 free_string(offset_str);
54 58 }
55 59
56 -static int known_access_ok_comparison(struct expression *expr)
57 -{
58 - struct expression *array;
59 - struct expression *size;
60 - struct expression *offset;
61 - int comparison;
62 -
63 - array = get_array_base(expr);
64 - size = get_size_variable(array);
65 - if (!size)
66 - return 0;
67 - offset = get_array_offset(expr);
68 - comparison = get_comparison(size, offset);
69 - if (comparison == '>' || comparison == SPECIAL_UNSIGNED_GT)
70 - return 1;
71 -
72 - return 0;
73 -}
74 -
75 60 static int known_access_ok_numbers(struct expression *expr)
76 61 {
77 62 struct expression *array;
78 63 struct expression *offset;
79 64 sval_t max;
80 65 int size;
81 66
82 67 array = get_array_base(expr);
83 68 offset = get_array_offset(expr);
84 69
85 70 size = get_array_size(array);
86 71 if (size <= 0)
87 72 return 0;
88 73
89 74 get_absolute_max(offset, &max);
90 75 if (max.uvalue < size)
91 76 return 1;
92 77 return 0;
93 78 }
94 79
95 80 static void array_check_data_info(struct expression *expr)
96 81 {
97 82 struct expression *array;
98 83 struct expression *offset;
99 84 struct state_list *slist;
100 85 struct sm_state *sm;
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
101 86 struct compare_data *comp;
102 87 char *offset_name;
103 88 const char *equal_name = NULL;
104 89
105 90 expr = strip_expr(expr);
106 91 if (!is_array(expr))
107 92 return;
108 93
109 94 if (known_access_ok_numbers(expr))
110 95 return;
111 - if (known_access_ok_comparison(expr))
96 + if (buf_comparison_index_ok(expr))
112 97 return;
113 98
114 99 array = get_array_base(expr);
115 100 offset = get_array_offset(expr);
116 101 offset_name = expr_to_var(offset);
117 102 if (!offset_name)
118 103 return;
119 104 slist = get_all_possible_equal_comparisons(offset);
120 105 if (!slist)
121 106 goto free;
122 107
123 108 FOR_EACH_PTR(slist, sm) {
124 109 comp = sm->state->data;
125 110 if (strcmp(comp->left_var, offset_name) == 0) {
126 111 if (db_var_is_array_limit(array, comp->right_var, comp->right_vsl)) {
127 112 equal_name = comp->right_var;
128 113 break;
129 114 }
130 115 } else if (strcmp(comp->right_var, offset_name) == 0) {
131 116 if (db_var_is_array_limit(array, comp->left_var, comp->left_vsl)) {
132 117 equal_name = comp->left_var;
133 118 break;
134 119 }
135 120 }
136 121 } END_FOR_EACH_PTR(sm);
137 122
138 123 if (equal_name) {
139 124 char *array_name = expr_to_str(array);
140 125
141 126 sm_warning("potential off by one '%s[]' limit '%s'", array_name, equal_name);
142 127 free_string(array_name);
143 128 }
144 129
145 130 free:
146 131 free_slist(&slist);
147 132 free_string(offset_name);
148 133 }
149 134
150 135 void check_off_by_one_relative(int id)
151 136 {
152 137 my_id = id;
153 138
154 139 add_hook(&array_check, OP_HOOK);
155 140 add_hook(&array_check_data_info, OP_HOOK);
156 141 }
157 142
↓ open down ↓ |
36 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX