math: overflows in hard max are undefined
[smatch.git] / smatch_db.c
blob63752a3abd2316607b7f3a311cc6490643c89ef8
1 /*
2 * smatch/smatch_db.c
4 * Copyright (C) 2010 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include <string.h>
11 #include <errno.h>
12 #include <sqlite3.h>
13 #include "smatch.h"
14 #include "smatch_slist.h"
15 #include "smatch_extra.h"
17 static sqlite3 *db;
19 struct def_callback {
20 int hook_type;
21 void (*callback)(const char *name, struct symbol *sym, char *key, char *value);
23 ALLOCATOR(def_callback, "definition db hook callbacks");
24 DECLARE_PTR_LIST(callback_list, struct def_callback);
25 static struct callback_list *callbacks;
27 struct member_info_callback {
28 int owner;
29 void (*callback)(char *fn, char *global_static, int param, char *printed_name, struct smatch_state *state);
31 ALLOCATOR(member_info_callback, "caller_info callbacks");
32 DECLARE_PTR_LIST(member_info_cb_list, struct member_info_callback);
33 static struct member_info_cb_list *member_callbacks;
35 struct call_implies_callback {
36 int type;
37 void (*callback)(struct expression *arg, char *value);
39 ALLOCATOR(call_implies_callback, "call_implies callbacks");
40 DECLARE_PTR_LIST(call_implies_cb_list, struct call_implies_callback);
41 static struct call_implies_cb_list *call_implies_cb_list;
43 static int return_id;
44 int get_return_id(void)
46 return return_id;
49 void sql_exec(int (*callback)(void*, int, char**, char**), const char *sql)
51 char *err = NULL;
52 int rc;
54 if (option_no_db || !db)
55 return;
57 rc = sqlite3_exec(db, sql, callback, 0, &err);
58 if (rc != SQLITE_OK) {
59 fprintf(stderr, "SQL error #2: %s\n", err);
60 fprintf(stderr, "SQL: '%s'\n", sql);
64 void add_definition_db_callback(void (*callback)(const char *name, struct symbol *sym, char *key, char *value), int type)
66 struct def_callback *def_callback = __alloc_def_callback(0);
68 def_callback->hook_type = type;
69 def_callback->callback = callback;
70 add_ptr_list(&callbacks, def_callback);
74 * These call backs are used when the --info option is turned on to print struct
75 * member information. For example foo->bar could have a state in
76 * smatch_extra.c and also check_user.c.
78 void add_member_info_callback(int owner, void (*callback)(char *fn, char *global_static, int param, char *printed_name, struct smatch_state *state))
80 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
82 member_callback->owner = owner;
83 member_callback->callback = callback;
84 add_ptr_list(&member_callbacks, member_callback);
87 void add_db_fn_call_callback(int type, void (*callback)(struct expression *arg, char *value))
89 struct call_implies_callback *cb = __alloc_call_implies_callback(0);
91 cb->type = type;
92 cb->callback = callback;
93 add_ptr_list(&call_implies_cb_list, cb);
96 static struct symbol *return_type;
97 static struct range_list *return_range_list;
98 static int db_return_callback(void *unused, int argc, char **argv, char **azColName)
100 if (argc != 1)
101 return 0;
102 if (option_debug)
103 sm_msg("return type %d", type_positive_bits(return_type));
104 parse_value_ranges_type(return_type, argv[0], &return_range_list);
105 return 0;
108 struct range_list *db_return_vals(struct expression *expr)
110 struct symbol *sym;
111 static char sql_filter[1024];
113 if (expr->type != EXPR_CALL)
114 return NULL;
115 if (expr->fn->type != EXPR_SYMBOL)
116 return NULL;
117 return_type = get_type(expr);
118 if (!return_type)
119 return NULL;
120 sym = expr->fn->symbol;
121 if (!sym)
122 return NULL;
124 if (sym->ctype.modifiers & MOD_STATIC) {
125 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
126 get_filename(), sym->ident->name);
127 } else {
128 snprintf(sql_filter, 1024, "function = '%s' and static = 0;",
129 sym->ident->name);
132 return_range_list = NULL;
133 run_sql(db_return_callback, "select return from return_values where %s",
134 sql_filter);
135 return return_range_list;
138 static void match_call_hack(struct expression *expr)
140 char *name;
143 * we just want to record something in the database so that if we have
144 * two calls like: frob(4); frob(some_unkown); then on the receiving
145 * side we know that sometimes frob is called with unknown parameters.
148 name = get_fnptr_name(expr->fn);
149 if (!name)
150 return;
151 sm_msg("info: call_marker '%s' %s", name, is_static(expr->fn) ? "static" : "global");
152 free_string(name);
155 static void print_struct_members(char *fn, char *global_static, struct expression *expr, int param, struct state_list *slist,
156 void (*callback)(char *fn, char *global_static, int param, char *printed_name, struct smatch_state *state))
158 struct sm_state *sm;
159 char *name;
160 struct symbol *sym;
161 int len;
162 char printed_name[256];
163 int is_address = 0;
165 expr = strip_expr(expr);
166 if (expr->type == EXPR_PREOP && expr->op == '&') {
167 expr = strip_expr(expr->unop);
168 is_address = 1;
171 name = get_variable_from_expr(expr, &sym);
172 if (!name || !sym)
173 goto free;
175 len = strlen(name);
176 FOR_EACH_PTR(slist, sm) {
177 if (sm->sym != sym)
178 continue;
179 if (strncmp(name, sm->name, len) || sm->name[len] == '\0')
180 continue;
181 if (is_address)
182 snprintf(printed_name, sizeof(printed_name), "$$->%s", sm->name + len + 1);
183 else
184 snprintf(printed_name, sizeof(printed_name), "$$%s", sm->name + len);
185 callback(fn, global_static, param, printed_name, sm->state);
186 } END_FOR_EACH_PTR(sm);
187 free:
188 free_string(name);
191 static void match_call_info(struct expression *expr)
193 struct member_info_callback *cb;
194 struct expression *arg;
195 struct state_list *slist;
196 char *name;
197 int i;
198 char *gs;
200 name = get_fnptr_name(expr->fn);
201 if (!name)
202 return;
204 if (is_static(expr->fn))
205 gs = (char *)"static";
206 else
207 gs = (char *)"global";
209 FOR_EACH_PTR(member_callbacks, cb) {
210 slist = get_all_states(cb->owner);
211 i = 0;
212 FOR_EACH_PTR(expr->args, arg) {
213 print_struct_members(name, gs, arg, i, slist, cb->callback);
214 i++;
215 } END_FOR_EACH_PTR(arg);
216 } END_FOR_EACH_PTR(cb);
218 free_string(name);
219 free_slist(&slist);
222 static int get_param(int param, char **name, struct symbol **sym)
224 struct symbol *arg;
225 int i;
227 i = 0;
228 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
230 * this is a temporary hack to work around a bug (I think in sparse?)
231 * 2.6.37-rc1:fs/reiserfs/journal.o
232 * If there is a function definition without parameter name found
233 * after a function implementation then it causes a crash.
234 * int foo() {}
235 * int bar(char *);
237 if (arg->ident->name < (char *)100)
238 continue;
239 if (i == param && arg->ident->name) {
240 *name = arg->ident->name;
241 *sym = arg;
242 return TRUE;
244 i++;
245 } END_FOR_EACH_PTR(arg);
247 return FALSE;
250 static struct state_list *final_states;
251 static int prev_func_id = -1;
252 static int db_callback(void *unused, int argc, char **argv, char **azColName)
254 int func_id;
255 long type;
256 long param;
257 char *name = NULL;
258 struct symbol *sym = NULL;
259 struct def_callback *def_callback;
261 if (argc != 5)
262 return 0;
264 func_id = atoi(argv[0]);
265 errno = 0;
266 type = strtol(argv[1], NULL, 10);
267 param = strtol(argv[2], NULL, 10);
268 if (errno)
269 return 0;
271 if (prev_func_id == -1)
272 prev_func_id = func_id;
273 if (func_id != prev_func_id) {
274 merge_slist(&final_states, __pop_fake_cur_slist());
275 __push_fake_cur_slist();
276 __unnullify_path();
277 prev_func_id = func_id;
280 if (type == INTERNAL)
281 return 0;
282 if (param >= 0 && !get_param(param, &name, &sym))
283 return 0;
285 FOR_EACH_PTR(callbacks, def_callback) {
286 if (def_callback->hook_type == type)
287 def_callback->callback(name, sym, argv[3], argv[4]);
288 } END_FOR_EACH_PTR(def_callback);
290 return 0;
293 static void get_direct_callers(struct symbol *sym)
295 char sql_filter[1024];
297 if (sym->ctype.modifiers & MOD_STATIC) {
298 snprintf(sql_filter, 1024,
299 "file = '%s' and function = '%s' order by function_id;",
300 get_filename(), sym->ident->name);
301 } else {
302 snprintf(sql_filter, 1024,
303 "function = '%s' and static = 0 order by function_id;",
304 sym->ident->name);
307 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
308 " where %s", sql_filter);
311 static char *ptr_name;
312 static int get_ptr_name(void *unused, int argc, char **argv, char **azColName)
314 if (!ptr_name)
315 ptr_name = alloc_string(argv[0]);
316 return 0;
319 static void get_function_pointer_callers(struct symbol *sym)
321 ptr_name = NULL;
322 run_sql(get_ptr_name, "select ptr from function_ptr where function = '%s'",
323 sym->ident->name);
324 if (!ptr_name)
325 return;
327 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
328 " where function = '%s' order by function_id", ptr_name);
331 static void match_data_from_db(struct symbol *sym)
333 struct sm_state *sm;
335 if (!sym || !sym->ident || !sym->ident->name)
336 return;
338 __push_fake_cur_slist();
339 __unnullify_path();
340 prev_func_id = -1;
342 get_direct_callers(sym);
343 get_function_pointer_callers(sym);
345 merge_slist(&final_states, __pop_fake_cur_slist());
347 FOR_EACH_PTR(final_states, sm) {
348 __set_sm(sm);
349 } END_FOR_EACH_PTR(sm);
351 free_slist(&final_states);
354 static void match_function_assign(struct expression *expr)
356 struct expression *right = expr->right;
357 struct symbol *sym;
358 char *fn_name;
359 char *ptr_name;
361 if (right->type == EXPR_PREOP && right->op == '&')
362 right = right->unop;
363 if (right->type != EXPR_SYMBOL)
364 return;
365 sym = get_type(right);
366 if (!sym || sym->type != SYM_FN)
367 return;
369 fn_name = get_variable_from_expr(right, NULL);
370 ptr_name = get_fnptr_name(expr->left);
371 if (!fn_name || !ptr_name)
372 goto free;
374 sm_msg("info: sets_fn_ptr '%s' '%s'", ptr_name, fn_name);
376 free:
377 free_string(fn_name);
378 free_string(ptr_name);
381 static struct expression *call_implies_call_expr;
382 static int call_implies_callbacks(void *unused, int argc, char **argv, char **azColName)
384 struct call_implies_callback *cb;
385 struct expression *arg = NULL;
386 int type;
387 int param;
389 if (argc != 4)
390 return 0;
392 type = atoi(argv[1]);
393 param = atoi(argv[2]);
395 FOR_EACH_PTR(call_implies_cb_list, cb) {
396 if (cb->type != type)
397 continue;
398 if (param != -1) {
399 arg = get_argument_from_call_expr(call_implies_call_expr->args, param);
400 if (!arg)
401 continue;
403 cb->callback(arg, argv[3]);
404 } END_FOR_EACH_PTR(cb);
406 return 0;
409 static void match_call_implies(struct expression *expr)
411 struct symbol *sym;
412 static char sql_filter[1024];
414 if (expr->fn->type != EXPR_SYMBOL)
415 return;
416 sym = expr->fn->symbol;
417 if (!sym)
418 return;
420 if (sym->ctype.modifiers & MOD_STATIC) {
421 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
422 get_filename(), sym->ident->name);
423 } else {
424 snprintf(sql_filter, 1024, "function = '%s' and static = 0;",
425 sym->ident->name);
428 call_implies_call_expr = expr;
429 run_sql(call_implies_callbacks,
430 "select function, type, parameter, value from call_implies where %s",
431 sql_filter);
432 return;
435 static void print_initializer_list(struct expression_list *expr_list,
436 struct symbol *struct_type)
438 struct expression *expr;
439 struct symbol *base_type;
441 FOR_EACH_PTR(expr_list, expr) {
442 if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) {
443 print_initializer_list(expr->idx_expression->expr_list, struct_type);
444 continue;
446 if (expr->type != EXPR_IDENTIFIER)
447 continue;
448 if (!expr->expr_ident)
449 continue;
450 if (!expr->ident_expression || !expr->ident_expression->symbol_name)
451 continue;
452 base_type = get_type(expr->ident_expression);
453 if (!base_type || base_type->type != SYM_FN)
454 continue;
455 sm_msg("info: sets_fn_ptr '(struct %s)->%s' '%s'", struct_type->ident->name,
456 expr->expr_ident->name,
457 expr->ident_expression->symbol_name->name);
458 } END_FOR_EACH_PTR(expr);
461 static void global_variable(struct symbol *sym)
463 struct symbol *struct_type;
465 if (!sym->ident)
466 return;
467 if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
468 return;
469 struct_type = get_base_type(sym);
470 if (!struct_type)
471 return;
472 if (struct_type->type == SYM_ARRAY) {
473 struct_type = get_base_type(struct_type);
474 if (!struct_type)
475 return;
477 if (struct_type->type != SYM_STRUCT || !struct_type->ident)
478 return;
479 print_initializer_list(sym->initializer->expr_list, struct_type);
482 static void match_return_info(struct expression *ret_value)
484 struct range_list *rl;
486 get_implied_range_list(ret_value, &rl);
487 rl = cast_rl(cur_func_return_type(), rl);
488 sm_msg("info: return_marker %d '%s' %s",
489 get_return_id(), show_ranges(rl), global_static());
492 static void match_end_func_info(struct symbol *sym)
494 if (__path_is_null())
495 return;
496 sm_msg("info: return_marker %d '' %s", get_return_id(), global_static());
499 static void match_function_def(struct symbol *sym)
501 return_id = 0;
504 static void match_return(struct expression *ret_value)
506 return_id++;
509 static void match_end_func(struct symbol *sym)
511 return_id++;
514 void open_smatch_db(void)
516 #ifdef SQLITE_OPEN_READONLY
517 int rc;
519 if (option_no_db)
520 return;
522 rc = sqlite3_open_v2("smatch_db.sqlite", &db, SQLITE_OPEN_READONLY, NULL);
523 if (rc != SQLITE_OK) {
524 option_no_db = 1;
525 return;
527 return;
528 #else
529 option_no_db = 1;
530 return;
531 #endif
534 void register_definition_db_callbacks(int id)
536 add_hook(&match_function_def, FUNC_DEF_HOOK);
537 add_hook(&match_return, RETURN_HOOK);
538 add_hook(&match_end_func, END_FUNC_HOOK);
540 if (option_info) {
541 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
542 add_hook(&match_call_hack, FUNCTION_CALL_HOOK);
543 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
544 add_hook(&global_variable, BASE_HOOK);
545 add_hook(&global_variable, DECLARATION_HOOK);
546 add_hook(&match_return_info, RETURN_HOOK);
547 add_hook(&match_end_func_info, END_FUNC_HOOK);
550 if (option_no_db)
551 return;
553 add_hook(&match_data_from_db, FUNC_DEF_HOOK);
554 add_hook(&match_call_implies, FUNCTION_CALL_HOOK);