113 array = get_array_base(expr->left);
114 offset = get_array_offset(expr->left);
115
116 /* These are handled by extra_mod_hook() */
117 if (get_value(offset, &sval))
118 return;
119 name = expr_to_var_sym(array, &sym);
120 if (!name || !sym)
121 goto free;
122 if (get_param_num_from_sym(sym) < 0)
123 goto free;
124 get_absolute_rl(expr->right, &rl);
125 rl = cast_rl(get_type(expr->left), rl);
126
127 snprintf(buf, sizeof(buf), "*%s", name);
128 set_state(my_id, buf, sym, alloc_estate_rl(rl));
129 free:
130 free_string(name);
131 }
132
133 /*
134 * This relies on the fact that these states are stored so that
135 * foo->bar is before foo->bar->baz.
136 */
137 static int parent_set(struct string_list *list, const char *name)
138 {
139 char *tmp;
140 int len;
141 int ret;
142
143 FOR_EACH_PTR(list, tmp) {
144 len = strlen(tmp);
145 ret = strncmp(tmp, name, len);
146 if (ret < 0)
147 continue;
148 if (ret > 0)
149 return 0;
150 if (name[len] == '-')
151 return 1;
152 } END_FOR_EACH_PTR(tmp);
153
154 return 0;
155 }
156
157 static void print_return_value_param(int return_id, char *return_ranges, struct expression *expr)
158 {
159 struct sm_state *sm;
160 struct smatch_state *extra;
161 int param;
162 struct range_list *rl;
163 const char *param_name;
164 struct string_list *set_list = NULL;
165 char *math_str;
166 char buf[256];
167
168 FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
169 if (!estate_rl(sm->state))
170 continue;
171 extra = get_state(SMATCH_EXTRA, sm->name, sm->sym);
172 if (extra) {
173 rl = rl_intersection(estate_rl(sm->state), estate_rl(extra));
174 if (!rl)
175 continue;
176 } else {
177 rl = estate_rl(sm->state);
178 }
179
180 param = get_param_num_from_sym(sm->sym);
181 if (param < 0)
182 continue;
183 param_name = get_param_name(sm);
184 if (!param_name)
185 continue;
186 if (strcmp(param_name, "$") == 0) {
187 insert_string(&set_list, (char *)sm->name);
188 continue;
189 }
190 if (is_recursive_member(param_name)) {
191 insert_string(&set_list, (char *)sm->name);
192 continue;
193 }
194
195 if (is_ignored_kernel_data(param_name)) {
196 insert_string(&set_list, (char *)sm->name);
197 continue;
198 }
199
200 math_str = get_value_in_terms_of_parameter_math_var_sym(sm->name, sm->sym);
201 if (math_str) {
202 snprintf(buf, sizeof(buf), "%s[%s]", show_rl(rl), math_str);
203 insert_string(&set_list, (char *)sm->name);
204 sql_insert_return_states(return_id, return_ranges,
205 param_has_filter_data(sm) ? PARAM_ADD : PARAM_SET,
206 param, param_name, buf);
207 continue;
208 }
209
210 /* no useful information here. */
211 if (is_whole_rl(rl) && parent_set(set_list, sm->name))
212 continue;
213 insert_string(&set_list, (char *)sm->name);
214
215 sql_insert_return_states(return_id, return_ranges,
216 param_has_filter_data(sm) ? PARAM_ADD : PARAM_SET,
217 param, param_name, show_rl(rl));
218
219 } END_FOR_EACH_SM(sm);
220
221 free_ptr_list((struct ptr_list **)&set_list);
222 }
223
224 int param_was_set_var_sym(const char *name, struct symbol *sym)
225 {
226 struct sm_state *sm;
227 int len;
228
229 FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
230 if (sm->sym != sym)
231 continue;
232 len = strlen(sm->name);
233 if (strncmp(sm->name, name, len) != 0)
234 continue;
235 if (name[len] == '\0' ||
236 name[len] == '-')
237 return 1;
238 } END_FOR_EACH_SM(sm);
239
240 return 0;
241 }
242
243 int param_was_set(struct expression *expr)
244 {
245 char *name;
246 struct symbol *sym;
247 int ret = 0;
248
249 name = expr_to_var_sym(expr, &sym);
250 if (!name || !sym)
251 goto free;
252
253 ret = param_was_set_var_sym(name, sym);
254 free:
255 free_string(name);
256 return ret;
257 }
258
259 void register_param_set(int id)
|
113 array = get_array_base(expr->left);
114 offset = get_array_offset(expr->left);
115
116 /* These are handled by extra_mod_hook() */
117 if (get_value(offset, &sval))
118 return;
119 name = expr_to_var_sym(array, &sym);
120 if (!name || !sym)
121 goto free;
122 if (get_param_num_from_sym(sym) < 0)
123 goto free;
124 get_absolute_rl(expr->right, &rl);
125 rl = cast_rl(get_type(expr->left), rl);
126
127 snprintf(buf, sizeof(buf), "*%s", name);
128 set_state(my_id, buf, sym, alloc_estate_rl(rl));
129 free:
130 free_string(name);
131 }
132
133 static char *get_two_dots(const char *name)
134 {
135 static char buf[80];
136 int i, cnt = 0;
137
138 for (i = 0; i < sizeof(buf); i++) {
139 if (name[i] == '.') {
140 cnt++;
141 if (cnt >= 2) {
142 buf[i] = '\0';
143 return buf;
144 }
145 }
146 buf[i] = name[i];
147 }
148 return NULL;
149 }
150
151 /*
152 * This relies on the fact that these states are stored so that
153 * foo->bar is before foo->bar->baz.
154 */
155 static int parent_set(struct string_list *list, const char *name)
156 {
157 char *tmp;
158 int len;
159 int ret;
160
161 FOR_EACH_PTR(list, tmp) {
162 len = strlen(tmp);
163 ret = strncmp(tmp, name, len);
164 if (ret < 0)
165 continue;
166 if (ret > 0)
167 return 0;
168 if (name[len] == '-')
169 return 1;
170 } END_FOR_EACH_PTR(tmp);
171
172 return 0;
173 }
174
175 static void print_return_value_param_helper(int return_id, char *return_ranges, struct expression *expr, int limit)
176 {
177 struct sm_state *sm;
178 struct smatch_state *extra;
179 int param;
180 struct range_list *rl;
181 const char *param_name;
182 struct string_list *set_list = NULL;
183 char *math_str;
184 char buf[256];
185 char two_dot[80] = "";
186 int count = 0;
187
188 FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
189 if (!estate_rl(sm->state))
190 continue;
191 extra = __get_state(SMATCH_EXTRA, sm->name, sm->sym);
192 if (extra) {
193 rl = rl_intersection(estate_rl(sm->state), estate_rl(extra));
194 if (!rl)
195 continue;
196 } else {
197 rl = estate_rl(sm->state);
198 }
199
200 param = get_param_num_from_sym(sm->sym);
201 if (param < 0)
202 continue;
203 param_name = get_param_name(sm);
204 if (!param_name)
205 continue;
206 if (strcmp(param_name, "$") == 0) {
207 insert_string(&set_list, (char *)sm->name);
208 continue;
209 }
210 if (is_recursive_member(param_name)) {
211 insert_string(&set_list, (char *)sm->name);
212 continue;
213 }
214
215 if (is_ignored_kernel_data(param_name)) {
216 insert_string(&set_list, (char *)sm->name);
217 continue;
218 }
219 if (limit) {
220 char *new = get_two_dots(param_name);
221
222 if (new) {
223 if (strcmp(new, two_dot) == 0)
224 continue;
225 strncpy(two_dot, new, sizeof(two_dot));
226 sql_insert_return_states(return_id, return_ranges,
227 PARAM_SET, param, new, "s64min-s64max");
228 continue;
229 }
230 }
231
232 math_str = get_value_in_terms_of_parameter_math_var_sym(sm->name, sm->sym);
233 if (math_str) {
234 snprintf(buf, sizeof(buf), "%s[%s]", show_rl(rl), math_str);
235 insert_string(&set_list, (char *)sm->name);
236 sql_insert_return_states(return_id, return_ranges,
237 param_has_filter_data(sm) ? PARAM_ADD : PARAM_SET,
238 param, param_name, buf);
239 continue;
240 }
241
242 /* no useful information here. */
243 if (is_whole_rl(rl) && parent_set(set_list, sm->name))
244 continue;
245 insert_string(&set_list, (char *)sm->name);
246
247 sql_insert_return_states(return_id, return_ranges,
248 param_has_filter_data(sm) ? PARAM_ADD : PARAM_SET,
249 param, param_name, show_rl(rl));
250 if (limit && ++count > limit)
251 break;
252
253 } END_FOR_EACH_SM(sm);
254
255 free_ptr_list((struct ptr_list **)&set_list);
256 }
257
258 static void print_return_value_param(int return_id, char *return_ranges, struct expression *expr)
259 {
260 print_return_value_param_helper(return_id, return_ranges, expr, 0);
261 }
262
263 void print_limited_param_set(int return_id, char *return_ranges, struct expression *expr)
264 {
265 print_return_value_param_helper(return_id, return_ranges, expr, 1000);
266 }
267
268 static int possibly_empty(struct sm_state *sm)
269 {
270 struct sm_state *tmp;
271
272 FOR_EACH_PTR(sm->possible, tmp) {
273 if (strcmp(tmp->name, "") == 0)
274 return 1;
275 } END_FOR_EACH_PTR(tmp);
276 return 0;
277 }
278
279 int param_was_set_var_sym(const char *name, struct symbol *sym)
280 {
281 struct sm_state *sm;
282 char buf[80];
283 int len, i;
284
285 if (!name)
286 return 0;
287
288 len = strlen(name);
289 if (len >= sizeof(buf))
290 len = sizeof(buf) - 1;
291
292 for (i = 0; i <= len; i++) {
293 if (name[i] != '-' && name[i] != '\0')
294 continue;
295
296 memcpy(buf, name, i);
297 buf[i] = '\0';
298
299 sm = get_sm_state(my_id, buf, sym);
300 if (!sm)
301 continue;
302 if (possibly_empty(sm))
303 continue;
304 return 1;
305 }
306
307 if (name[0] == '*')
308 return param_was_set_var_sym(name + 1, sym);
309
310 return 0;
311 }
312
313 int param_was_set(struct expression *expr)
314 {
315 char *name;
316 struct symbol *sym;
317 int ret = 0;
318
319 name = expr_to_var_sym(expr, &sym);
320 if (!name || !sym)
321 goto free;
322
323 ret = param_was_set_var_sym(name, sym);
324 free:
325 free_string(name);
326 return ret;
327 }
328
329 void register_param_set(int id)
|