Print this page
11506 smatch resync
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_param_set.c
+++ new/usr/src/tools/smatch/src/smatch_param_set.c
1 1 /*
2 2 * Copyright (C) 2012 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 * This is for functions like:
20 20 *
21 21 * int foo(int *x)
22 22 * {
23 23 * if (*x == 42) {
24 24 * *x = 0;
25 25 * return 1;
26 26 * }
27 27 * return 0;
28 28 * }
29 29 *
30 30 * If we return 1 that means the value of *x has been set to 0. If we return
31 31 * 0 then we have left *x alone.
32 32 *
33 33 */
34 34
35 35 #include "scope.h"
36 36 #include "smatch.h"
37 37 #include "smatch_slist.h"
38 38 #include "smatch_extra.h"
39 39
40 40 static int my_id;
41 41
42 42 static struct smatch_state *unmatched_state(struct sm_state *sm)
43 43 {
44 44 return alloc_estate_empty();
45 45 }
46 46
47 47 static int parent_is_set(const char *name, struct symbol *sym, struct smatch_state *state)
48 48 {
49 49 struct expression *faked;
50 50 char *left_name;
51 51 int ret = 0;
52 52 int len;
53 53
54 54 if (!__in_fake_assign)
55 55 return 0;
56 56 if (!is_whole_rl(estate_rl(state)))
57 57 return 0;
58 58 if (get_state(my_id, name, sym))
59 59 return 0;
60 60
61 61 faked = get_faked_expression();
62 62 if (!faked)
63 63 return 0;
64 64 if ((faked->type == EXPR_PREOP || faked->type == EXPR_POSTOP) &&
65 65 (faked->op == SPECIAL_INCREMENT || faked->op == SPECIAL_DECREMENT)) {
66 66 faked = strip_expr(faked->unop);
67 67 if (faked->type == EXPR_SYMBOL)
68 68 return 1;
69 69 return 0;
70 70 }
71 71 if (faked->type != EXPR_ASSIGNMENT)
72 72 return 0;
73 73
74 74 left_name = expr_to_var(faked->left);
75 75 if (!left_name)
76 76 return 0;
77 77
78 78 len = strlen(left_name);
79 79 if (strncmp(name, left_name, len) == 0 && name[len] == '-')
80 80 ret = 1;
81 81 free_string(left_name);
82 82
83 83 return ret;
84 84 }
85 85
86 86 static void extra_mod_hook(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
87 87 {
88 88 if (parent_is_set(name, sym, state))
89 89 return;
90 90 if (get_param_num_from_sym(sym) < 0)
91 91 return;
92 92 set_state(my_id, name, sym, state);
93 93 }
94 94
95 95 /*
96 96 * This function is is a dirty hack because extra_mod_hook is giving us a NULL
97 97 * sym instead of a vsl.
98 98 */
99 99 static void match_array_assignment(struct expression *expr)
100 100 {
101 101 struct expression *array, *offset;
102 102 char *name;
103 103 struct symbol *sym;
104 104 struct range_list *rl;
105 105 sval_t sval;
106 106 char buf[256];
107 107
108 108 if (__in_fake_assign)
109 109 return;
110 110
111 111 if (!is_array(expr->left))
112 112 return;
113 113 array = get_array_base(expr->left);
114 114 offset = get_array_offset(expr->left);
115 115
116 116 /* These are handled by extra_mod_hook() */
117 117 if (get_value(offset, &sval))
118 118 return;
119 119 name = expr_to_var_sym(array, &sym);
120 120 if (!name || !sym)
121 121 goto free;
122 122 if (get_param_num_from_sym(sym) < 0)
123 123 goto free;
124 124 get_absolute_rl(expr->right, &rl);
125 125 rl = cast_rl(get_type(expr->left), rl);
126 126
127 127 snprintf(buf, sizeof(buf), "*%s", name);
128 128 set_state(my_id, buf, sym, alloc_estate_rl(rl));
129 129 free:
130 130 free_string(name);
131 131 }
132 132
133 133 /*
134 134 * This relies on the fact that these states are stored so that
135 135 * foo->bar is before foo->bar->baz.
136 136 */
137 137 static int parent_set(struct string_list *list, const char *name)
138 138 {
139 139 char *tmp;
140 140 int len;
141 141 int ret;
142 142
143 143 FOR_EACH_PTR(list, tmp) {
144 144 len = strlen(tmp);
145 145 ret = strncmp(tmp, name, len);
146 146 if (ret < 0)
147 147 continue;
148 148 if (ret > 0)
149 149 return 0;
150 150 if (name[len] == '-')
151 151 return 1;
152 152 } END_FOR_EACH_PTR(tmp);
153 153
154 154 return 0;
155 155 }
156 156
↓ open down ↓ |
156 lines elided |
↑ open up ↑ |
157 157 static void print_return_value_param(int return_id, char *return_ranges, struct expression *expr)
158 158 {
159 159 struct sm_state *sm;
160 160 struct smatch_state *extra;
161 161 int param;
162 162 struct range_list *rl;
163 163 const char *param_name;
164 164 struct string_list *set_list = NULL;
165 165 char *math_str;
166 166 char buf[256];
167 - sval_t sval;
168 167
169 168 FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
170 169 if (!estate_rl(sm->state))
171 170 continue;
172 171 extra = get_state(SMATCH_EXTRA, sm->name, sm->sym);
173 172 if (extra) {
174 173 rl = rl_intersection(estate_rl(sm->state), estate_rl(extra));
175 174 if (!rl)
176 175 continue;
177 176 } else {
178 177 rl = estate_rl(sm->state);
179 178 }
180 179
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
181 180 param = get_param_num_from_sym(sm->sym);
182 181 if (param < 0)
183 182 continue;
184 183 param_name = get_param_name(sm);
185 184 if (!param_name)
186 185 continue;
187 186 if (strcmp(param_name, "$") == 0) {
188 187 insert_string(&set_list, (char *)sm->name);
189 188 continue;
190 189 }
190 + if (is_recursive_member(param_name)) {
191 + insert_string(&set_list, (char *)sm->name);
192 + continue;
193 + }
191 194
192 - if (rl_to_sval(rl, &sval)) {
195 + if (is_ignored_kernel_data(param_name)) {
193 196 insert_string(&set_list, (char *)sm->name);
194 - sql_insert_return_states(return_id, return_ranges,
195 - param_has_filter_data(sm) ? PARAM_ADD : PARAM_SET,
196 - param, param_name, show_rl(rl));
197 197 continue;
198 198 }
199 199
200 200 math_str = get_value_in_terms_of_parameter_math_var_sym(sm->name, sm->sym);
201 201 if (math_str) {
202 202 snprintf(buf, sizeof(buf), "%s[%s]", show_rl(rl), math_str);
203 203 insert_string(&set_list, (char *)sm->name);
204 204 sql_insert_return_states(return_id, return_ranges,
205 205 param_has_filter_data(sm) ? PARAM_ADD : PARAM_SET,
206 206 param, param_name, buf);
207 207 continue;
208 208 }
209 209
210 210 /* no useful information here. */
211 211 if (is_whole_rl(rl) && parent_set(set_list, sm->name))
212 212 continue;
213 213 insert_string(&set_list, (char *)sm->name);
214 214
215 215 sql_insert_return_states(return_id, return_ranges,
216 216 param_has_filter_data(sm) ? PARAM_ADD : PARAM_SET,
217 217 param, param_name, show_rl(rl));
218 218
219 219 } END_FOR_EACH_SM(sm);
220 220
221 221 free_ptr_list((struct ptr_list **)&set_list);
222 222 }
223 223
224 224 int param_was_set_var_sym(const char *name, struct symbol *sym)
225 225 {
226 226 struct sm_state *sm;
227 227 int len;
228 228
229 229 FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
230 230 if (sm->sym != sym)
231 231 continue;
232 232 len = strlen(sm->name);
233 233 if (strncmp(sm->name, name, len) != 0)
234 234 continue;
235 235 if (name[len] == '\0' ||
236 236 name[len] == '-')
237 237 return 1;
238 238 } END_FOR_EACH_SM(sm);
239 239
240 240 return 0;
241 241 }
242 242
243 243 int param_was_set(struct expression *expr)
244 244 {
245 245 char *name;
246 246 struct symbol *sym;
247 247 int ret = 0;
248 248
249 249 name = expr_to_var_sym(expr, &sym);
250 250 if (!name || !sym)
251 251 goto free;
252 252
↓ open down ↓ |
46 lines elided |
↑ open up ↑ |
253 253 ret = param_was_set_var_sym(name, sym);
254 254 free:
255 255 free_string(name);
256 256 return ret;
257 257 }
258 258
259 259 void register_param_set(int id)
260 260 {
261 261 my_id = id;
262 262
263 + set_dynamic_states(my_id);
263 264 add_extra_mod_hook(&extra_mod_hook);
264 265 add_hook(match_array_assignment, ASSIGNMENT_HOOK);
265 266 add_unmatched_state_hook(my_id, &unmatched_state);
266 267 add_merge_hook(my_id, &merge_estates);
267 268 add_split_return_callback(&print_return_value_param);
268 269 }
269 270
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX