db/fixup_kernel.sh: fix clear_user() handling
[smatch.git] / smatch_function_ptrs.c
blob6380494c47c29c5448464613c77832b05bdf2614
1 /*
2 * Copyright (C) 2013 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 * Track how functions are saved as various struct members or passed as
20 * parameters.
24 #include "scope.h"
25 #include "smatch.h"
26 #include "smatch_slist.h"
28 static int my_id;
30 static char *get_from__symbol_get(struct expression *expr)
32 struct expression *arg;
35 * typeof(&dib0070_attach) __a =
36 * ((((typeof(&dib0070_attach)) (__symbol_get("dib0070_attach")))) ?:
37 * (__request_module(true, "symbol:" "dib0070_attach"), (((typeof(&dib0070_attach))(__symbol_get("dib0070_attach"))))));
40 expr = strip_expr(expr);
42 if (expr->type != EXPR_CALL)
43 return NULL;
44 if (!sym_name_is("__symbol_get", expr->fn))
45 return NULL;
46 arg = get_argument_from_call_expr(expr->args, 0);
47 if (!arg || arg->type != EXPR_STRING)
48 return NULL;
50 return alloc_string(arg->string->data);
53 static int xxx_is_array(struct expression *expr)
55 struct symbol *type;
57 expr = strip_expr(expr);
58 if (!expr)
59 return 0;
61 if (expr->type == EXPR_PREOP && expr->op == '*') {
62 expr = strip_expr(expr->unop);
63 if (!expr)
64 return 0;
65 if (expr->type == EXPR_BINOP && expr->op == '+')
66 return 1;
69 if (expr->type != EXPR_BINOP || expr->op != '+')
70 return 0;
72 type = get_type(expr->left);
73 if (!type)
74 return 0;
75 if (type->type != SYM_ARRAY && type->type != SYM_PTR)
76 return 0;
78 return 1;
81 static struct expression *xxx_get_array_base(struct expression *expr)
83 if (!xxx_is_array(expr))
84 return NULL;
85 expr = strip_expr(expr);
86 if (expr->type == EXPR_PREOP && expr->op == '*')
87 expr = strip_expr(expr->unop);
88 if (expr->type != EXPR_BINOP || expr->op != '+')
89 return NULL;
90 return strip_parens(expr->left);
93 static char *get_array_ptr(struct expression *expr)
95 struct expression *array;
96 struct symbol *type;
97 char *name;
98 char buf[256];
100 array = xxx_get_array_base(expr);
102 if (array) {
103 name = get_member_name(array);
104 if (name)
105 return alloc_string(name);
108 /* FIXME: is_array() should probably be is_array_element() */
109 type = get_type(expr);
110 if (!array && type && type->type == SYM_ARRAY)
111 array = expr;
112 if (array) {
113 name = expr_to_var(array);
114 if (!name)
115 return NULL;
116 snprintf(buf, sizeof(buf), "%s[]", name);
117 return alloc_string(buf);
120 expr = get_assigned_expr(expr);
121 array = xxx_get_array_base(expr);
122 if (!array)
123 return NULL;
124 name = expr_to_var(array);
125 if (!name)
126 return NULL;
127 snprintf(buf, sizeof(buf), "%s[]", name);
128 free_string(name);
129 return alloc_string(buf);
132 static int is_local_symbol(struct symbol *sym)
134 if (!sym ||
135 !(sym->ctype.modifiers & MOD_TOPLEVEL))
136 return 1;
137 return 0;
140 static char *ptr_prefix(struct symbol *sym)
142 static char buf[128];
144 if (is_local_symbol(sym))
145 snprintf(buf, sizeof(buf), "%s ptr", get_function());
146 else if (sym && toplevel(sym->scope))
147 snprintf(buf, sizeof(buf), "%s ptr", get_base_file());
148 else
149 snprintf(buf, sizeof(buf), "ptr");
151 return buf;
154 char *get_returned_ptr(struct expression *expr)
156 struct symbol *type;
157 char *name;
158 char buf[256];
160 if (expr->type != EXPR_CALL)
161 return NULL;
162 if (!expr->fn || expr->fn->type != EXPR_SYMBOL)
163 return NULL;
165 type = get_type(expr);
166 if (type && type->type == SYM_PTR)
167 type = get_real_base_type(type);
168 if (!type || type->type != SYM_FN)
169 return NULL;
171 name = expr_to_var(expr->fn);
172 if (!name)
173 return NULL;
174 snprintf(buf, sizeof(buf), "r %s()", name);
175 free_string(name);
176 return alloc_string(buf);
179 char *get_fnptr_name(struct expression *expr)
181 char *name;
183 if (expr_is_zero(expr))
184 return NULL;
186 expr = strip_expr(expr);
188 /* (*ptrs[0])(a, b, c) is the same as ptrs[0](a, b, c); */
189 if (expr->type == EXPR_PREOP && expr->op == '*')
190 expr = strip_expr(expr->unop);
192 name = get_from__symbol_get(expr);
193 if (name)
194 return name;
196 name = get_array_ptr(expr);
197 if (name)
198 return name;
200 name = get_returned_ptr(expr);
201 if (name)
202 return name;
204 name = get_member_name(expr);
205 if (name)
206 return alloc_string(name);
208 if (expr->type == EXPR_SYMBOL) {
209 int param;
210 char buf[256];
211 struct symbol *sym;
212 struct symbol *type;
214 param = get_param_num_from_sym(expr->symbol);
215 if (param >= 0) {
216 snprintf(buf, sizeof(buf), "%s param %d", get_function(), param);
217 return alloc_string(buf);
220 name = expr_to_var_sym(expr, &sym);
221 if (!name)
222 return NULL;
223 type = get_type(expr);
224 if (type && type->type == SYM_PTR) {
225 snprintf(buf, sizeof(buf), "%s %s", ptr_prefix(sym), name);
226 free_string(name);
227 return alloc_string(buf);
229 return name;
231 return expr_to_var(expr);
234 static int get_arg_count(struct expression *fn)
236 struct symbol *fn_type;
238 fn_type = get_type(fn);
239 if (!fn_type)
240 return INT_MAX;
241 if (fn_type->type == SYM_PTR)
242 fn_type = get_real_base_type(fn_type);
243 if (fn_type->type != SYM_FN)
244 return INT_MAX;
246 return ptr_list_size((struct ptr_list *)fn_type->arguments);
249 static void match_passes_function_pointer(struct expression *expr)
251 struct expression *arg, *tmp;
252 struct symbol *type;
253 char *called_name;
254 char *fn_name;
255 char ptr_name[256];
256 int cnt, i;
258 cnt = get_arg_count(expr->fn);
260 i = -1;
261 FOR_EACH_PTR(expr->args, arg) {
262 i++;
264 if (i >= cnt)
265 return;
267 tmp = strip_expr(arg);
268 if (tmp->type == EXPR_PREOP && tmp->op == '&')
269 tmp = strip_expr(tmp->unop);
271 type = get_type(tmp);
272 if (type && type->type == SYM_PTR)
273 type = get_real_base_type(type);
274 if (!type || type->type != SYM_FN)
275 continue;
277 called_name = expr_to_var(expr->fn);
278 if (!called_name)
279 return;
280 fn_name = get_fnptr_name(tmp);
281 if (!fn_name)
282 goto free;
284 snprintf(ptr_name, sizeof(ptr_name), "%s param %d", called_name, i);
285 sql_insert_function_ptr(fn_name, ptr_name);
286 free:
287 free_string(fn_name);
288 free_string(called_name);
289 } END_FOR_EACH_PTR(arg);
292 static int get_row_count(void *_row_count, int argc, char **argv, char **azColName)
294 int *row_count = _row_count;
296 *row_count = 0;
297 if (argc != 1)
298 return 0;
299 *row_count = atoi(argv[0]);
300 return 0;
303 static int can_hold_function_ptr(struct expression *expr)
305 struct symbol *type;
307 type = get_type(expr);
308 if (!type)
309 return 0;
310 if (type->type == SYM_PTR || type->type == SYM_ARRAY) {
311 type = get_real_base_type(type);
312 if (!type)
313 return 0;
315 /* pointer to a pointer */
316 if (type->type == SYM_PTR || type->type == SYM_ARRAY) {
317 type = get_real_base_type(type);
318 if (!type)
319 return 0;
321 if (type->type == SYM_FN)
322 return 1;
323 if (type == &ulong_ctype && expr->type == EXPR_DEREF)
324 return 1;
325 if (type == &void_ctype)
326 return 1;
327 return 0;
330 static void match_function_assign(struct expression *expr)
332 struct expression *right;
333 struct symbol *type;
334 char *fn_name;
335 char *ptr_name;
337 if (__in_fake_assign)
338 return;
339 if (is_fake_var_assign(expr))
340 return;
342 right = strip_expr(expr->right);
343 if (right->type == EXPR_PREOP && right->op == '&')
344 right = strip_expr(right->unop);
346 if (right->type != EXPR_SYMBOL &&
347 right->type != EXPR_DEREF &&
348 right->type != EXPR_CALL)
349 return;
351 if (!can_hold_function_ptr(right) ||
352 !can_hold_function_ptr(expr->left))
353 return;
355 fn_name = get_fnptr_name(right);
356 ptr_name = get_fnptr_name(expr->left);
357 if (!fn_name || !ptr_name)
358 goto free;
359 if (strcmp(fn_name, ptr_name) == 0)
360 goto free;
363 type = get_type(right);
364 if (!type)
365 return;
366 if (type->type == SYM_PTR || type->type == SYM_ARRAY) {
367 type = get_real_base_type(type);
368 if (!type)
369 return;
371 if (type->type != SYM_FN) {
372 int count = 0;
374 /* look it up in function_ptr */
375 run_sql(get_row_count, &count,
376 "select count(*) from function_ptr where ptr = '%s'",
377 fn_name);
378 if (count == 0)
379 goto free;
382 sql_insert_function_ptr(fn_name, ptr_name);
383 free:
384 free_string(fn_name);
385 free_string(ptr_name);
388 static void match_returns_function_pointer(struct expression *expr)
390 struct symbol *type;
391 char *fn_name;
392 char ptr_name[256];
394 if (__inline_fn)
395 return;
397 type = get_real_base_type(cur_func_sym);
398 if (!type || type->type != SYM_FN)
399 return;
400 type = get_real_base_type(type);
401 if (!type || type->type != SYM_PTR)
402 return;
403 type = get_real_base_type(type);
404 if (!type || type->type != SYM_FN)
405 return;
407 if (expr->type == EXPR_PREOP && expr->op == '&')
408 expr = strip_expr(expr->unop);
410 fn_name = get_fnptr_name(expr);
411 if (!fn_name)
412 return;
413 snprintf(ptr_name, sizeof(ptr_name), "r %s()", get_function());
414 sql_insert_function_ptr(fn_name, ptr_name);
417 static void print_initializer_list(struct expression_list *expr_list,
418 struct symbol *struct_type)
420 struct expression *expr;
421 struct symbol *base_type;
422 char struct_name[256];
424 FOR_EACH_PTR(expr_list, expr) {
425 if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) {
426 print_initializer_list(expr->idx_expression->expr_list, struct_type);
427 continue;
429 if (expr->type != EXPR_IDENTIFIER)
430 continue;
431 if (!expr->expr_ident)
432 continue;
433 if (!expr->ident_expression ||
434 expr->ident_expression->type != EXPR_SYMBOL ||
435 !expr->ident_expression->symbol_name)
436 continue;
437 base_type = get_type(expr->ident_expression);
438 if (!base_type || base_type->type != SYM_FN)
439 continue;
440 snprintf(struct_name, sizeof(struct_name), "(struct %s)->%s",
441 struct_type->ident->name, expr->expr_ident->name);
442 sql_insert_function_ptr(expr->ident_expression->symbol_name->name,
443 struct_name);
444 } END_FOR_EACH_PTR(expr);
447 static void global_variable(struct symbol *sym)
449 struct symbol *struct_type;
451 if (!sym->ident)
452 return;
453 if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
454 return;
455 struct_type = get_base_type(sym);
456 if (!struct_type)
457 return;
458 if (struct_type->type == SYM_ARRAY) {
459 struct_type = get_base_type(struct_type);
460 if (!struct_type)
461 return;
463 if (struct_type->type != SYM_STRUCT || !struct_type->ident)
464 return;
465 print_initializer_list(sym->initializer->expr_list, struct_type);
468 void register_function_ptrs(int id)
470 my_id = id;
472 if (!option_info)
473 return;
475 add_hook(&global_variable, BASE_HOOK);
476 add_hook(&global_variable, DECLARATION_HOOK);
477 add_hook(&match_passes_function_pointer, FUNCTION_CALL_HOOK);
478 add_hook(&match_returns_function_pointer, RETURN_HOOK);
479 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
480 add_hook(&match_function_assign, GLOBAL_ASSIGNMENT_HOOK);