check_precedence: fix a segfault
[smatch.git] / smatch_db.c
blob1cef38173ef7e5a759e751daae0a826b92f2fbc0
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 range_list *return_range_list;
97 static int db_return_callback(void *unused, int argc, char **argv, char **azColName)
99 if (argc != 1)
100 return 0;
101 get_value_ranges(argv[0], &return_range_list);
102 return 0;
105 struct range_list *db_return_vals(struct expression *expr)
107 struct symbol *sym;
108 static char sql_filter[1024];
110 if (expr->type != EXPR_CALL)
111 return NULL;
112 if (expr->fn->type != EXPR_SYMBOL)
113 return NULL;
114 sym = expr->fn->symbol;
115 if (!sym)
116 return NULL;
118 if (sym->ctype.modifiers & MOD_STATIC) {
119 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
120 get_filename(), sym->ident->name);
121 } else {
122 snprintf(sql_filter, 1024, "function = '%s' and static = 0;",
123 sym->ident->name);
126 return_range_list = NULL;
127 run_sql(db_return_callback, "select return from return_values where %s",
128 sql_filter);
129 return return_range_list;
132 static void match_call_hack(struct expression *expr)
134 char *name;
137 * we just want to record something in the database so that if we have
138 * two calls like: frob(4); frob(some_unkown); then on the receiving
139 * side we know that sometimes frob is called with unknown parameters.
142 name = get_fnptr_name(expr->fn);
143 if (!name)
144 return;
145 sm_msg("info: call_marker '%s' %s", name, is_static(expr->fn) ? "static" : "global");
146 free_string(name);
149 static void print_struct_members(char *fn, char *global_static, struct expression *expr, int param, struct state_list *slist,
150 void (*callback)(char *fn, char *global_static, int param, char *printed_name, struct smatch_state *state))
152 struct sm_state *sm;
153 char *name;
154 struct symbol *sym;
155 int len;
156 char printed_name[256];
157 int is_address = 0;
159 expr = strip_expr(expr);
160 if (expr->type == EXPR_PREOP && expr->op == '&') {
161 expr = strip_expr(expr->unop);
162 is_address = 1;
165 name = get_variable_from_expr(expr, &sym);
166 if (!name || !sym)
167 goto free;
169 len = strlen(name);
170 FOR_EACH_PTR(slist, sm) {
171 if (sm->sym != sym)
172 continue;
173 if (strncmp(name, sm->name, len) || sm->name[len] == '\0')
174 continue;
175 if (is_address)
176 snprintf(printed_name, sizeof(printed_name), "$$->%s", sm->name + len + 1);
177 else
178 snprintf(printed_name, sizeof(printed_name), "$$%s", sm->name + len);
179 callback(fn, global_static, param, printed_name, sm->state);
180 } END_FOR_EACH_PTR(sm);
181 free:
182 free_string(name);
185 static void match_call_info(struct expression *expr)
187 struct member_info_callback *cb;
188 struct expression *arg;
189 struct state_list *slist;
190 char *name;
191 int i;
192 char *gs;
194 name = get_fnptr_name(expr->fn);
195 if (!name)
196 return;
198 if (is_static(expr->fn))
199 gs = (char *)"static";
200 else
201 gs = (char *)"global";
203 FOR_EACH_PTR(member_callbacks, cb) {
204 slist = get_all_states(cb->owner);
205 i = 0;
206 FOR_EACH_PTR(expr->args, arg) {
207 print_struct_members(name, gs, arg, i, slist, cb->callback);
208 i++;
209 } END_FOR_EACH_PTR(arg);
210 } END_FOR_EACH_PTR(cb);
212 free_string(name);
213 free_slist(&slist);
216 static int get_param(int param, char **name, struct symbol **sym)
218 struct symbol *arg;
219 int i;
221 i = 0;
222 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
224 * this is a temporary hack to work around a bug (I think in sparse?)
225 * 2.6.37-rc1:fs/reiserfs/journal.o
226 * If there is a function definition without parameter name found
227 * after a function implementation then it causes a crash.
228 * int foo() {}
229 * int bar(char *);
231 if (arg->ident->name < (char *)100)
232 continue;
233 if (i == param && arg->ident->name) {
234 *name = arg->ident->name;
235 *sym = arg;
236 return TRUE;
238 i++;
239 } END_FOR_EACH_PTR(arg);
241 return FALSE;
244 static struct state_list *final_states;
245 static int prev_func_id = -1;
246 static int db_callback(void *unused, int argc, char **argv, char **azColName)
248 int func_id;
249 long type;
250 long param;
251 char *name = NULL;
252 struct symbol *sym = NULL;
253 struct def_callback *def_callback;
255 if (argc != 5)
256 return 0;
258 func_id = atoi(argv[0]);
259 errno = 0;
260 type = strtol(argv[1], NULL, 10);
261 param = strtol(argv[2], NULL, 10);
262 if (errno)
263 return 0;
265 if (prev_func_id == -1)
266 prev_func_id = func_id;
267 if (func_id != prev_func_id) {
268 merge_slist(&final_states, __pop_fake_cur_slist());
269 __push_fake_cur_slist();
270 __unnullify_path();
271 prev_func_id = func_id;
274 if (type == INTERNAL)
275 return 0;
276 if (param >= 0 && !get_param(param, &name, &sym))
277 return 0;
279 FOR_EACH_PTR(callbacks, def_callback) {
280 if (def_callback->hook_type == type)
281 def_callback->callback(name, sym, argv[3], argv[4]);
282 } END_FOR_EACH_PTR(def_callback);
284 return 0;
287 static void get_direct_callers(struct symbol *sym)
289 char sql_filter[1024];
291 if (sym->ctype.modifiers & MOD_STATIC) {
292 snprintf(sql_filter, 1024,
293 "file = '%s' and function = '%s' order by function_id;",
294 get_filename(), sym->ident->name);
295 } else {
296 snprintf(sql_filter, 1024,
297 "function = '%s' and static = 0 order by function_id;",
298 sym->ident->name);
301 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
302 " where %s", sql_filter);
305 static char *ptr_name;
306 static int get_ptr_name(void *unused, int argc, char **argv, char **azColName)
308 if (!ptr_name)
309 ptr_name = alloc_string(argv[0]);
310 return 0;
313 static void get_function_pointer_callers(struct symbol *sym)
315 ptr_name = NULL;
316 run_sql(get_ptr_name, "select ptr from function_ptr where function = '%s'",
317 sym->ident->name);
318 if (!ptr_name)
319 return;
321 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
322 " where function = '%s' order by function_id", ptr_name);
325 static void match_data_from_db(struct symbol *sym)
327 struct sm_state *sm;
329 if (!sym || !sym->ident || !sym->ident->name)
330 return;
332 __push_fake_cur_slist();
333 __unnullify_path();
334 prev_func_id = -1;
336 get_direct_callers(sym);
337 get_function_pointer_callers(sym);
339 merge_slist(&final_states, __pop_fake_cur_slist());
341 FOR_EACH_PTR(final_states, sm) {
342 __set_sm(sm);
343 } END_FOR_EACH_PTR(sm);
345 free_slist(&final_states);
348 static void match_function_assign(struct expression *expr)
350 struct expression *right = expr->right;
351 struct symbol *sym;
352 char *fn_name;
353 char *ptr_name;
355 if (right->type == EXPR_PREOP && right->op == '&')
356 right = right->unop;
357 if (right->type != EXPR_SYMBOL)
358 return;
359 sym = get_type(right);
360 if (!sym || sym->type != SYM_FN)
361 return;
363 fn_name = get_variable_from_expr(right, NULL);
364 ptr_name = get_fnptr_name(expr->left);
365 if (!fn_name || !ptr_name)
366 goto free;
368 sm_msg("info: sets_fn_ptr '%s' '%s'", ptr_name, fn_name);
370 free:
371 free_string(fn_name);
372 free_string(ptr_name);
375 static struct expression *call_implies_call_expr;
376 static int call_implies_callbacks(void *unused, int argc, char **argv, char **azColName)
378 struct call_implies_callback *cb;
379 struct expression *arg = NULL;
380 int type;
381 int param;
383 if (argc != 4)
384 return 0;
386 type = atoi(argv[1]);
387 param = atoi(argv[2]);
389 FOR_EACH_PTR(call_implies_cb_list, cb) {
390 if (cb->type != type)
391 continue;
392 if (param != -1) {
393 arg = get_argument_from_call_expr(call_implies_call_expr->args, param);
394 if (!arg)
395 continue;
397 cb->callback(arg, argv[3]);
398 } END_FOR_EACH_PTR(cb);
400 return 0;
403 static void match_call_implies(struct expression *expr)
405 struct symbol *sym;
406 static char sql_filter[1024];
408 if (expr->fn->type != EXPR_SYMBOL)
409 return;
410 sym = expr->fn->symbol;
411 if (!sym)
412 return;
414 if (sym->ctype.modifiers & MOD_STATIC) {
415 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
416 get_filename(), sym->ident->name);
417 } else {
418 snprintf(sql_filter, 1024, "function = '%s' and static = 0;",
419 sym->ident->name);
422 call_implies_call_expr = expr;
423 run_sql(call_implies_callbacks,
424 "select function, type, parameter, value from call_implies where %s",
425 sql_filter);
426 return;
429 static void print_initializer_list(struct expression_list *expr_list,
430 struct symbol *struct_type)
432 struct expression *expr;
433 struct symbol *base_type;
435 FOR_EACH_PTR(expr_list, expr) {
436 if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) {
437 print_initializer_list(expr->idx_expression->expr_list, struct_type);
438 continue;
440 if (expr->type != EXPR_IDENTIFIER)
441 continue;
442 if (!expr->expr_ident)
443 continue;
444 if (!expr->ident_expression || !expr->ident_expression->symbol_name)
445 continue;
446 base_type = get_type(expr->ident_expression);
447 if (!base_type || base_type->type != SYM_FN)
448 continue;
449 sm_msg("info: sets_fn_ptr '(struct %s)->%s' '%s'", struct_type->ident->name,
450 expr->expr_ident->name,
451 expr->ident_expression->symbol_name->name);
452 } END_FOR_EACH_PTR(expr);
455 static void global_variable(struct symbol *sym)
457 struct symbol *struct_type;
459 if (!sym->ident)
460 return;
461 if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
462 return;
463 struct_type = get_base_type(sym);
464 if (!struct_type)
465 return;
466 if (struct_type->type == SYM_ARRAY) {
467 struct_type = get_base_type(struct_type);
468 if (!struct_type)
469 return;
471 if (struct_type->type != SYM_STRUCT || !struct_type->ident)
472 return;
473 print_initializer_list(sym->initializer->expr_list, struct_type);
476 static void match_return_info(struct expression *ret_value)
478 struct range_list *rl;
480 get_implied_range_list(ret_value, &rl);
481 sm_msg("info: return_marker %d '%s' %s",
482 get_return_id(), show_ranges(rl), global_static());
485 static void match_end_func_info(struct symbol *sym)
487 if (__path_is_null())
488 return;
489 sm_msg("info: return_marker %d '' %s", get_return_id(), global_static());
492 static void match_function_def(struct symbol *sym)
494 return_id = 0;
497 static void match_return(struct expression *ret_value)
499 return_id++;
502 static void match_end_func(struct symbol *sym)
504 return_id++;
507 void open_smatch_db(void)
509 #ifdef SQLITE_OPEN_READONLY
510 int rc;
512 if (option_no_db)
513 return;
515 rc = sqlite3_open_v2("smatch_db.sqlite", &db, SQLITE_OPEN_READONLY, NULL);
516 if (rc != SQLITE_OK) {
517 option_no_db = 1;
518 return;
520 return;
521 #else
522 option_no_db = 1;
523 return;
524 #endif
527 void register_definition_db_callbacks(int id)
529 add_hook(&match_function_def, FUNC_DEF_HOOK);
530 add_hook(&match_return, RETURN_HOOK);
531 add_hook(&match_end_func, END_FUNC_HOOK);
533 if (option_info) {
534 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
535 add_hook(&match_call_hack, FUNCTION_CALL_HOOK);
536 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
537 add_hook(&global_variable, BASE_HOOK);
538 add_hook(&global_variable, DECLARATION_HOOK);
539 add_hook(&match_return_info, RETURN_HOOK);
540 add_hook(&match_end_func_info, END_FUNC_HOOK);
543 if (option_no_db)
544 return;
546 add_hook(&match_data_from_db, FUNC_DEF_HOOK);
547 add_hook(&match_call_implies, FUNCTION_CALL_HOOK);