*new* add smatch_data/kernel.silenced_functions to silence common noise
[smatch.git] / smatch_db.c
blob025ab15981b2ff3ef414c22089b459a6a073b91d
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 <unistd.h>
14 #include "smatch.h"
15 #include "smatch_slist.h"
16 #include "smatch_extra.h"
18 static sqlite3 *db;
19 static sqlite3 *mem_db;
21 static int return_id;
23 #define sql_insert(table, values...) \
24 do { \
25 if (!mem_db) \
26 break; \
27 if (__inline_fn) { \
28 char buf[1024]; \
29 char *err, *p = buf; \
30 int rc; \
32 p += snprintf(p, buf + sizeof(buf) - p, \
33 "insert into %s values (", #table); \
34 p += snprintf(p, buf + sizeof(buf) - p, values); \
35 p += snprintf(p, buf + sizeof(buf) - p, ");"); \
36 sm_debug("in-mem: %s\n", buf); \
37 rc = sqlite3_exec(mem_db, buf, NULL, 0, &err); \
38 if (rc != SQLITE_OK) { \
39 fprintf(stderr, "SQL error #2: %s\n", err); \
40 fprintf(stderr, "SQL: '%s'\n", buf); \
41 } \
42 break; \
43 } \
44 if (option_info) { \
45 sm_prefix(); \
46 sm_printf("SQL: insert into " #table " values (" values); \
47 sm_printf(");\n"); \
48 } \
49 } while (0)
51 struct def_callback {
52 int hook_type;
53 void (*callback)(const char *name, struct symbol *sym, char *key, char *value);
55 ALLOCATOR(def_callback, "definition db hook callbacks");
56 DECLARE_PTR_LIST(callback_list, struct def_callback);
57 static struct callback_list *callbacks;
59 struct member_info_callback {
60 int owner;
61 void (*callback)(struct expression *call, int param, char *printed_name, struct smatch_state *state);
63 ALLOCATOR(member_info_callback, "caller_info callbacks");
64 DECLARE_PTR_LIST(member_info_cb_list, struct member_info_callback);
65 static struct member_info_cb_list *member_callbacks;
67 struct returned_state_callback {
68 void (*callback)(int return_id, char *return_ranges, struct expression *return_expr);
70 ALLOCATOR(returned_state_callback, "returned state callbacks");
71 DECLARE_PTR_LIST(returned_state_cb_list, struct returned_state_callback);
72 static struct returned_state_cb_list *returned_state_callbacks;
74 struct returned_member_callback {
75 int owner;
76 void (*callback)(int return_id, char *return_ranges, char *printed_name, struct smatch_state *state);
78 ALLOCATOR(returned_member_callback, "returned member callbacks");
79 DECLARE_PTR_LIST(returned_member_cb_list, struct returned_member_callback);
80 static struct returned_member_cb_list *returned_member_callbacks;
82 struct call_implies_callback {
83 int type;
84 void (*callback)(struct expression *arg, char *value);
86 ALLOCATOR(call_implies_callback, "call_implies callbacks");
87 DECLARE_PTR_LIST(call_implies_cb_list, struct call_implies_callback);
88 static struct call_implies_cb_list *call_implies_cb_list;
90 static int print_sql_output(void *unused, int argc, char **argv, char **azColName)
92 int i;
94 for (i = 0; i < argc; i++) {
95 if (i != 0)
96 printf(", ");
97 sm_printf("%s", argv[i]);
99 sm_printf("\n");
100 return 0;
103 void debug_sql(const char *sql)
105 if (!option_debug)
106 return;
107 sm_msg("%s", sql);
108 sql_exec(print_sql_output, sql);
112 void sql_exec(int (*callback)(void*, int, char**, char**), const char *sql)
114 char *err = NULL;
115 int rc;
117 if (option_no_db || !db)
118 return;
120 rc = sqlite3_exec(db, sql, callback, 0, &err);
121 if (rc != SQLITE_OK) {
122 fprintf(stderr, "SQL error #2: %s\n", err);
123 fprintf(stderr, "SQL: '%s'\n", sql);
127 void sql_mem_exec(int (*callback)(void*, int, char**, char**), const char *sql)
129 char *err = NULL;
130 int rc;
132 if (!mem_db)
133 return;
135 rc = sqlite3_exec(mem_db, sql, callback, 0, &err);
136 if (rc != SQLITE_OK) {
137 fprintf(stderr, "SQL error #2: %s\n", err);
138 fprintf(stderr, "SQL: '%s'\n", sql);
142 void sql_insert_return_states(int return_id, const char *return_ranges,
143 int type, int param, const char *key, const char *value)
145 if (key && strlen(key) >= 80)
146 return;
147 sql_insert(return_states, "'%s', '%s', %lu, %d, '%s', %d, %d, %d, '%s', '%s'",
148 get_base_file(), get_function(), (unsigned long)__inline_fn,
149 return_id, return_ranges, fn_static(), type, param, key, value);
152 static struct string_list *common_funcs;
153 static int is_common_function(const char *fn)
155 char *tmp;
157 if (strncmp(fn, "__builtin_", 10) == 0)
158 return 1;
160 FOR_EACH_PTR(common_funcs, tmp) {
161 if (strcmp(tmp, fn) == 0)
162 return 1;
163 } END_FOR_EACH_PTR(tmp);
165 return 0;
168 void sql_insert_caller_info(struct expression *call, int type,
169 int param, const char *key, const char *value)
171 char *fn;
173 if (!option_info && !__inline_call)
174 return;
176 if (key && strlen(key) >= 80)
177 return;
179 fn = get_fnptr_name(call->fn);
180 if (!fn)
181 return;
183 if (__inline_call) {
184 mem_sql(NULL,
185 "insert into caller_info values ('%s', '%s', '%s', %lu, %d, %d, %d, '%s', '%s');",
186 get_base_file(), get_function(), fn, (unsigned long)call,
187 is_static(call->fn), type, param, key, value);
190 if (!option_info)
191 return;
193 if (is_common_function(fn))
194 return;
196 sm_msg("SQL_caller_info: insert into caller_info values ("
197 "'%s', '%s', '%s', %%CALL_ID%%, %d, %d, %d, '%s', '%s');",
198 get_base_file(), get_function(), fn, is_static(call->fn),
199 type, param, key, value);
201 free_string(fn);
204 void sql_insert_function_ptr(const char *fn, const char *struct_name)
206 sql_insert(function_ptr, "'%s', '%s', '%s'", get_base_file(), fn,
207 struct_name);
210 void sql_insert_call_implies(int type, int param, int value)
212 sql_insert(call_implies, "'%s', '%s', %lu, %d, %d, %d, %d", get_base_file(),
213 get_function(), (unsigned long)__inline_fn, fn_static(),
214 type, param, value);
217 void sql_insert_function_type_size(const char *member, int size)
219 sql_insert(function_type_size, "'%s', '%s', '%s', %d", get_base_file(), get_function(), member, size);
222 void sql_insert_local_values(const char *name, const char *value)
224 sql_insert(local_values, "'%s', '%s', '%s'", get_base_file(), name, value);
227 void sql_insert_function_type_value(const char *type, const char *value)
229 sql_insert(function_type_value, "'%s', '%s', '%s', '%s'", get_base_file(), get_function(), type, value);
232 static char *get_static_filter(struct symbol *sym)
234 static char sql_filter[1024];
236 if (sym->ctype.modifiers & MOD_STATIC) {
237 snprintf(sql_filter, sizeof(sql_filter),
238 "file = '%s' and function = '%s' and static = '1'",
239 get_base_file(), sym->ident->name);
240 } else {
241 snprintf(sql_filter, sizeof(sql_filter),
242 "function = '%s' and static = '0'", sym->ident->name);
245 return sql_filter;
248 static int row_count;
249 static int get_row_count(void *unused, int argc, char **argv, char **azColName)
251 if (argc != 1)
252 return 0;
253 row_count = atoi(argv[0]);
254 return 0;
257 static void sql_select_return_states_pointer(const char *cols,
258 struct expression *call, int (*callback)(void*, int, char**, char**))
260 char *ptr;
262 ptr = get_fnptr_name(call);
263 if (!ptr)
264 return;
266 row_count = 0;
267 run_sql(get_row_count,
268 "select count(*) from return_states join function_ptr where "
269 "return_states.function == function_ptr.function and ptr = '%s';",
270 ptr);
271 if (row_count > 1000)
272 return;
274 run_sql(callback,
275 "select %s from return_states join function_ptr where "
276 "return_states.function == function_ptr.function and ptr = '%s' "
277 "order by return_id, type;",
278 cols, ptr);
281 void sql_select_return_states(const char *cols, struct expression *call,
282 int (*callback)(void*, int, char**, char**))
284 if (call->fn->type != EXPR_SYMBOL || !call->fn->symbol) {
285 sql_select_return_states_pointer(cols, call, callback);
286 return;
289 if (inlinable(call->fn)) {
290 mem_sql(callback,
291 "select %s from return_states where call_id = '%lu' order by return_id, type;",
292 cols, (unsigned long)call);
293 return;
296 row_count = 0;
297 run_sql(get_row_count, "select count(*) from return_states where %s;",
298 get_static_filter(call->fn->symbol));
299 if (row_count > 1000)
300 return;
302 run_sql(callback, "select %s from return_states where %s order by return_id, type;",
303 cols, get_static_filter(call->fn->symbol));
306 void sql_select_call_implies(const char *cols, struct expression *call,
307 int (*callback)(void*, int, char**, char**))
309 if (call->fn->type != EXPR_SYMBOL || !call->fn->symbol)
310 return;
312 if (inlinable(call->fn)) {
313 mem_sql(callback,
314 "select %s from call_implies where call_id = '%lu';",
315 cols, (unsigned long)call);
316 return;
319 run_sql(callback, "select %s from call_implies where %s;",
320 cols, get_static_filter(call->fn->symbol));
323 void sql_select_caller_info(const char *cols, struct symbol *sym,
324 int (*callback)(void*, int, char**, char**))
326 if (__inline_fn) {
327 mem_sql(callback, "select %s from caller_info where call_id = %lu;",
328 cols, (unsigned long)__inline_fn);
329 return;
332 run_sql(callback,
333 "select %s from caller_info where %s order by call_id;",
334 cols, get_static_filter(sym));
337 void select_caller_info_hook(void (*callback)(const char *name, struct symbol *sym, char *key, char *value), int type)
339 struct def_callback *def_callback = __alloc_def_callback(0);
341 def_callback->hook_type = type;
342 def_callback->callback = callback;
343 add_ptr_list(&callbacks, def_callback);
347 * These call backs are used when the --info option is turned on to print struct
348 * member information. For example foo->bar could have a state in
349 * smatch_extra.c and also check_user.c.
351 void add_member_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct smatch_state *state))
353 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
355 member_callback->owner = owner;
356 member_callback->callback = callback;
357 add_ptr_list(&member_callbacks, member_callback);
360 void add_split_return_callback(void (*fn)(int return_id, char *return_ranges, struct expression *returned_expr))
362 struct returned_state_callback *callback = __alloc_returned_state_callback(0);
364 callback->callback = fn;
365 add_ptr_list(&returned_state_callbacks, callback);
368 void add_returned_member_callback(int owner, void (*callback)(int return_id, char *return_ranges, char *printed_name, struct smatch_state *state))
370 struct returned_member_callback *member_callback = __alloc_returned_member_callback(0);
372 member_callback->owner = owner;
373 member_callback->callback = callback;
374 add_ptr_list(&returned_member_callbacks, member_callback);
377 void select_call_implies_hook(int type, void (*callback)(struct expression *arg, char *value))
379 struct call_implies_callback *cb = __alloc_call_implies_callback(0);
381 cb->type = type;
382 cb->callback = callback;
383 add_ptr_list(&call_implies_cb_list, cb);
386 static struct expression *static_call_expr;
387 static struct symbol *return_type;
388 static struct range_list *return_range_list;
389 static int db_return_callback(void *unused, int argc, char **argv, char **azColName)
391 struct range_list *rl;
393 if (argc != 1)
394 return 0;
395 call_results_to_rl(static_call_expr, return_type, argv[0], &rl);
396 return_range_list = rl_union(return_range_list, rl);
397 return 0;
400 struct range_list *db_return_vals(struct expression *expr)
402 static_call_expr = expr;
403 return_type = get_type(expr);
404 if (!return_type)
405 return NULL;
406 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
407 return NULL;
409 return_range_list = NULL;
410 if (inlinable(expr->fn)) {
411 mem_sql(db_return_callback,
412 "select distinct return from return_states where call_id = '%lu';",
413 (unsigned long)expr);
414 } else {
415 run_sql(db_return_callback,
416 "select distinct return from return_states where %s;",
417 get_static_filter(expr->fn->symbol));
419 return return_range_list;
422 static void match_call_marker(struct expression *expr)
425 * we just want to record something in the database so that if we have
426 * two calls like: frob(4); frob(some_unkown); then on the receiving
427 * side we know that sometimes frob is called with unknown parameters.
430 sql_insert_caller_info(expr, INTERNAL, -1, "%call_marker%", "");
433 static void print_struct_members(struct expression *call, struct expression *expr, int param, struct state_list *slist,
434 void (*callback)(struct expression *call, int param, char *printed_name, struct smatch_state *state))
436 struct sm_state *sm;
437 char *name;
438 struct symbol *sym;
439 int len;
440 char printed_name[256];
441 int is_address = 0;
443 expr = strip_expr(expr);
444 if (expr->type == EXPR_PREOP && expr->op == '&') {
445 expr = strip_expr(expr->unop);
446 is_address = 1;
449 name = expr_to_var_sym(expr, &sym);
450 if (!name || !sym)
451 goto free;
453 len = strlen(name);
454 FOR_EACH_PTR(slist, sm) {
455 if (sm->sym != sym)
456 continue;
457 if (strcmp(name, sm->name) == 0) {
458 if (is_address)
459 snprintf(printed_name, sizeof(printed_name), "*$$");
460 else /* these are already handled. fixme: handle them here */
461 continue;
462 } else if (sm->name[0] == '*' && strcmp(name, sm->name + 1) == 0) {
463 snprintf(printed_name, sizeof(printed_name), "*$$");
464 } else if (strncmp(name, sm->name, len) == 0) {
465 if (is_address)
466 snprintf(printed_name, sizeof(printed_name), "$$->%s", sm->name + len + 1);
467 else
468 snprintf(printed_name, sizeof(printed_name), "$$%s", sm->name + len);
469 } else {
470 continue;
472 callback(call, param, printed_name, sm->state);
473 } END_FOR_EACH_PTR(sm);
474 free:
475 free_string(name);
478 static void match_call_info(struct expression *call)
480 struct member_info_callback *cb;
481 struct expression *arg;
482 struct state_list *slist;
483 char *name;
484 int i;
486 name = get_fnptr_name(call->fn);
487 if (!name)
488 return;
490 FOR_EACH_PTR(member_callbacks, cb) {
491 slist = get_all_states(cb->owner);
492 i = 0;
493 FOR_EACH_PTR(call->args, arg) {
494 print_struct_members(call, arg, i, slist, cb->callback);
495 i++;
496 } END_FOR_EACH_PTR(arg);
497 free_slist(&slist);
498 } END_FOR_EACH_PTR(cb);
500 free_string(name);
503 static int get_param(int param, char **name, struct symbol **sym)
505 struct symbol *arg;
506 int i;
508 i = 0;
509 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
511 * this is a temporary hack to work around a bug (I think in sparse?)
512 * 2.6.37-rc1:fs/reiserfs/journal.o
513 * If there is a function definition without parameter name found
514 * after a function implementation then it causes a crash.
515 * int foo() {}
516 * int bar(char *);
518 if (arg->ident->name < (char *)100)
519 continue;
520 if (i == param && arg->ident->name) {
521 *name = arg->ident->name;
522 *sym = arg;
523 return TRUE;
525 i++;
526 } END_FOR_EACH_PTR(arg);
528 return FALSE;
531 static struct state_list *final_states;
532 static int prev_func_id = -1;
533 static int db_callback(void *unused, int argc, char **argv, char **azColName)
535 int func_id;
536 long type;
537 long param;
538 char *name = NULL;
539 struct symbol *sym = NULL;
540 struct def_callback *def_callback;
541 struct state_list *slist;
543 if (argc != 5)
544 return 0;
546 func_id = atoi(argv[0]);
547 errno = 0;
548 type = strtol(argv[1], NULL, 10);
549 param = strtol(argv[2], NULL, 10);
550 if (errno)
551 return 0;
553 if (prev_func_id == -1)
554 prev_func_id = func_id;
555 if (func_id != prev_func_id) {
556 slist = __pop_fake_cur_slist();
557 merge_slist(&final_states, slist);
558 free_slist(&slist);
559 __push_fake_cur_slist();
560 __unnullify_path();
561 prev_func_id = func_id;
564 if (type == INTERNAL)
565 return 0;
566 if (param >= 0 && !get_param(param, &name, &sym))
567 return 0;
569 FOR_EACH_PTR(callbacks, def_callback) {
570 if (def_callback->hook_type == type)
571 def_callback->callback(name, sym, argv[3], argv[4]);
572 } END_FOR_EACH_PTR(def_callback);
574 return 0;
577 static void get_direct_callers(struct symbol *sym)
579 sql_select_caller_info("call_id, type, parameter, key, value", sym,
580 db_callback);
583 static struct string_list *ptr_names_done;
584 static struct string_list *ptr_names;
586 static int get_ptr_name(void *unused, int argc, char **argv, char **azColName)
588 insert_string(&ptr_names, alloc_string(argv[0]));
589 return 0;
592 static char *get_next_ptr_name(void)
594 char *ptr;
596 FOR_EACH_PTR(ptr_names, ptr) {
597 if (list_has_string(ptr_names_done, ptr))
598 continue;
599 insert_string(&ptr_names_done, ptr);
600 return ptr;
601 } END_FOR_EACH_PTR(ptr);
602 return NULL;
605 static void get_ptr_names(const char *file, const char *name)
607 char sql_filter[1024];
608 int before, after;
610 if (file) {
611 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
612 file, name);
613 } else {
614 snprintf(sql_filter, 1024, "function = '%s';", name);
617 before = ptr_list_size((struct ptr_list *)ptr_names);
619 run_sql(get_ptr_name,
620 "select distinct ptr from function_ptr where %s",
621 sql_filter);
623 after = ptr_list_size((struct ptr_list *)ptr_names);
624 if (before == after)
625 return;
627 while ((name = get_next_ptr_name()))
628 get_ptr_names(NULL, name);
631 static void get_function_pointer_callers(struct symbol *sym)
633 char *ptr;
635 if (sym->ctype.modifiers & MOD_STATIC)
636 get_ptr_names(get_base_file(), sym->ident->name);
637 else
638 get_ptr_names(NULL, sym->ident->name);
640 FOR_EACH_PTR(ptr_names, ptr) {
641 run_sql(db_callback, "select call_id, type, parameter, key, value"
642 " from caller_info where function = '%s' order by call_id",
643 ptr);
644 free_string(ptr);
645 } END_FOR_EACH_PTR(ptr);
647 __free_ptr_list((struct ptr_list **)&ptr_names);
648 __free_ptr_list((struct ptr_list **)&ptr_names_done);
651 static void match_data_from_db(struct symbol *sym)
653 struct sm_state *sm;
654 struct state_list *slist;
656 if (!sym || !sym->ident || !sym->ident->name)
657 return;
659 __push_fake_cur_slist();
660 __unnullify_path();
661 prev_func_id = -1;
663 get_direct_callers(sym);
664 if (!__inline_fn)
665 get_function_pointer_callers(sym);
667 slist = __pop_fake_cur_slist();
668 merge_slist(&final_states, slist);
669 free_slist(&slist);
671 FOR_EACH_PTR(final_states, sm) {
672 __set_sm(sm);
673 } END_FOR_EACH_PTR(sm);
675 free_slist(&final_states);
678 static int call_implies_callbacks(void *unused, int argc, char **argv, char **azColName)
680 struct call_implies_callback *cb;
681 struct expression *arg = NULL;
682 int type;
683 int param;
685 if (argc != 4)
686 return 0;
688 type = atoi(argv[1]);
689 param = atoi(argv[2]);
691 FOR_EACH_PTR(call_implies_cb_list, cb) {
692 if (cb->type != type)
693 continue;
694 if (param != -1) {
695 arg = get_argument_from_call_expr(static_call_expr->args, param);
696 if (!arg)
697 continue;
699 cb->callback(arg, argv[3]);
700 } END_FOR_EACH_PTR(cb);
702 return 0;
705 static void match_call_implies(struct expression *expr)
707 static_call_expr = expr;
708 sql_select_call_implies("function, type, parameter, value", expr,
709 call_implies_callbacks);
710 return;
713 static void print_initializer_list(struct expression_list *expr_list,
714 struct symbol *struct_type)
716 struct expression *expr;
717 struct symbol *base_type;
718 char struct_name[256];
720 FOR_EACH_PTR(expr_list, expr) {
721 if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) {
722 print_initializer_list(expr->idx_expression->expr_list, struct_type);
723 continue;
725 if (expr->type != EXPR_IDENTIFIER)
726 continue;
727 if (!expr->expr_ident)
728 continue;
729 if (!expr->ident_expression || !expr->ident_expression->symbol_name)
730 continue;
731 base_type = get_type(expr->ident_expression);
732 if (!base_type || base_type->type != SYM_FN)
733 continue;
734 snprintf(struct_name, sizeof(struct_name), "(struct %s)->%s",
735 struct_type->ident->name, expr->expr_ident->name);
736 sql_insert_function_ptr(expr->ident_expression->symbol_name->name,
737 struct_name);
738 } END_FOR_EACH_PTR(expr);
741 static void global_variable(struct symbol *sym)
743 struct symbol *struct_type;
745 if (!sym->ident)
746 return;
747 if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
748 return;
749 struct_type = get_base_type(sym);
750 if (!struct_type)
751 return;
752 if (struct_type->type == SYM_ARRAY) {
753 struct_type = get_base_type(struct_type);
754 if (!struct_type)
755 return;
757 if (struct_type->type != SYM_STRUCT || !struct_type->ident)
758 return;
759 print_initializer_list(sym->initializer->expr_list, struct_type);
762 static void match_return_info(int return_id, char *return_ranges, struct expression *expr)
764 sql_insert_return_states(return_id, return_ranges, INTERNAL, -1, "", "");
767 static void call_return_state_hooks_conditional(struct expression *expr)
769 struct returned_state_callback *cb;
770 struct range_list *rl;
771 char *return_ranges;
772 int final_pass_orig = final_pass;
774 __push_fake_cur_slist();
776 final_pass = 0;
777 __split_whole_condition(expr->conditional);
778 final_pass = final_pass_orig;
780 if (get_implied_rl(expr->cond_true, &rl))
781 rl = cast_rl(cur_func_return_type(), rl);
782 else
783 rl = cast_rl(cur_func_return_type(), alloc_whole_rl(get_type(expr->cond_true)));
784 return_ranges = show_rl(rl);
786 return_id++;
787 FOR_EACH_PTR(returned_state_callbacks, cb) {
788 cb->callback(return_id, return_ranges, expr);
789 } END_FOR_EACH_PTR(cb);
791 __push_true_states();
792 __use_false_states();
794 if (get_implied_rl(expr->cond_false, &rl))
795 rl = cast_rl(cur_func_return_type(), rl);
796 else
797 rl = cast_rl(cur_func_return_type(), alloc_whole_rl(get_type(expr->cond_false)));
798 return_ranges = show_rl(rl);
800 return_id++;
801 FOR_EACH_PTR(returned_state_callbacks, cb) {
802 cb->callback(return_id, return_ranges, expr);
803 } END_FOR_EACH_PTR(cb);
805 __merge_true_states();
806 __free_fake_cur_slist();
809 static void call_return_state_hooks_compare(struct expression *expr)
811 struct returned_state_callback *cb;
812 char *return_ranges;
813 int final_pass_orig = final_pass;
815 __push_fake_cur_slist();
817 final_pass = 0;
818 __split_whole_condition(expr);
819 final_pass = final_pass_orig;
821 return_ranges = alloc_sname("1");
823 return_id++;
824 FOR_EACH_PTR(returned_state_callbacks, cb) {
825 cb->callback(return_id, return_ranges, expr);
826 } END_FOR_EACH_PTR(cb);
828 __push_true_states();
829 __use_false_states();
831 return_ranges = alloc_sname("0");;
832 return_id++;
833 FOR_EACH_PTR(returned_state_callbacks, cb) {
834 cb->callback(return_id, return_ranges, expr);
835 } END_FOR_EACH_PTR(cb);
837 __merge_true_states();
838 __free_fake_cur_slist();
841 static int call_return_state_hooks_split_possible(struct expression *expr)
843 struct returned_state_callback *cb;
844 struct range_list *rl;
845 char *return_ranges;
846 struct sm_state *sm;
847 struct sm_state *tmp;
848 int ret = 0;
849 int nr_possible, nr_states;
850 char *compare_str;
851 char buf[128];
853 if (!expr || expr_equal_to_param(expr))
854 return 0;
856 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
857 if (!sm || !sm->merged)
858 return 0;
860 if (too_many_possible(sm))
861 return 0;
863 /* bail if it gets too complicated */
864 nr_possible = ptr_list_size((struct ptr_list *)sm->possible);
865 nr_states = ptr_list_size((struct ptr_list *)__get_cur_slist());
867 * the main thing option_info because we don't want to print a
868 * million lines of output. If someone else, like check_locking.c
869 * wants this data, then it doesn't cause a slow down to provide it.
871 if (option_info && nr_states * nr_possible >= 2000)
872 return 0;
874 compare_str = expr_lte_to_param(expr);
876 FOR_EACH_PTR(sm->possible, tmp) {
877 if (tmp->merged)
878 continue;
880 ret = 1;
881 __push_fake_cur_slist();
883 overwrite_states_using_pool(tmp);
885 rl = cast_rl(cur_func_return_type(), estate_rl(tmp->state));
886 return_ranges = show_rl(rl);
887 if (compare_str) {
888 snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
889 return_ranges = alloc_sname(buf);
892 return_id++;
893 FOR_EACH_PTR(returned_state_callbacks, cb) {
894 cb->callback(return_id, return_ranges, expr);
895 } END_FOR_EACH_PTR(cb);
897 __free_fake_cur_slist();
898 } END_FOR_EACH_PTR(tmp);
900 return ret;
903 static char *get_return_ranges_str(struct expression *expr)
905 struct range_list *rl;
906 char *return_ranges;
907 char *compare_str;
908 char buf[128];
910 if (!expr)
911 return alloc_sname("");
912 compare_str = expr_equal_to_param(expr);
913 if (compare_str)
914 return compare_str;
916 if (get_implied_rl(expr, &rl)) {
917 rl = cast_rl(cur_func_return_type(), rl);
918 return_ranges = show_rl(rl);
919 } else {
920 rl = cast_rl(cur_func_return_type(), alloc_whole_rl(get_type(expr)));
921 return_ranges = show_rl(rl);
923 compare_str = expr_lte_to_param(expr);
924 if (compare_str) {
925 snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
926 return alloc_sname(buf);
928 return return_ranges;
931 static int is_conditional(struct expression *expr)
933 if (!expr)
934 return 0;
935 if (expr->type == EXPR_CONDITIONAL || expr->type == EXPR_SELECT)
936 return 1;
937 return 0;
940 static void call_return_state_hooks(struct expression *expr)
942 struct returned_state_callback *cb;
943 char *return_ranges;
944 int nr_states;
946 expr = strip_expr(expr);
948 if (is_condition(expr)) {
949 call_return_state_hooks_compare(expr);
950 return;
951 } else if (is_conditional(expr)) {
952 call_return_state_hooks_conditional(expr);
953 return;
954 } else if (call_return_state_hooks_split_possible(expr)) {
955 return;
958 return_ranges = get_return_ranges_str(expr);
960 return_id++;
961 nr_states = ptr_list_size((struct ptr_list *)__get_cur_slist());
962 if (nr_states >= 10000) {
963 match_return_info(return_id, return_ranges, expr);
964 return;
966 FOR_EACH_PTR(returned_state_callbacks, cb) {
967 cb->callback(return_id, return_ranges, expr);
968 } END_FOR_EACH_PTR(cb);
971 static void print_returned_struct_members(int return_id, char *return_ranges, struct expression *expr)
973 struct returned_member_callback *cb;
974 struct state_list *my_slist;
975 struct sm_state *sm;
976 struct symbol *type;
977 char *name;
978 char member_name[256];
979 int len;
981 type = get_type(expr);
982 if (!type || type->type != SYM_PTR)
983 return;
984 name = expr_to_var(expr);
985 if (!name)
986 return;
988 member_name[sizeof(member_name) - 1] = '\0';
989 strcpy(member_name, "$$");
991 len = strlen(name);
992 FOR_EACH_PTR(returned_member_callbacks, cb) {
993 my_slist = get_all_states(cb->owner);
994 FOR_EACH_PTR(my_slist, sm) {
995 if (sm->name[0] == '*' && strcmp(sm->name + 1, name) == 0) {
996 strcpy(member_name, "*$$");
997 cb->callback(return_id, return_ranges, member_name, sm->state);
998 continue;
1000 if (strncmp(sm->name, name, len) != 0)
1001 continue;
1002 if (strncmp(sm->name + len, "->", 2) != 0)
1003 continue;
1004 strcpy(member_name, "$$");
1005 strncpy(member_name + 2, sm->name + len, sizeof(member_name) - 2);
1006 cb->callback(return_id, return_ranges, member_name, sm->state);
1007 } END_FOR_EACH_PTR(sm);
1008 free_slist(&my_slist);
1009 } END_FOR_EACH_PTR(cb);
1011 free_string(name);
1014 static void reset_memdb(void)
1016 mem_sql(NULL, "delete from caller_info;");
1017 mem_sql(NULL, "delete from return_states;");
1018 mem_sql(NULL, "delete from call_implies;");
1021 static void match_end_func_info(struct symbol *sym)
1023 if (__path_is_null())
1024 return;
1025 call_return_state_hooks(NULL);
1026 if (!__inline_fn)
1027 reset_memdb();
1030 static void init_memdb(void)
1032 char *err = NULL;
1033 int rc;
1034 const char *schema_files[] = {
1035 "db/db.schema",
1036 "db/caller_info.schema",
1037 "db/return_states.schema",
1038 "db/function_type_size.schema",
1039 "db/type_size.schema",
1040 "db/call_implies.schema",
1041 "db/function_ptr.schema",
1042 "db/local_values.schema",
1043 "db/function_type_value.schema",
1044 "db/type_value.schema",
1046 static char buf[4096];
1047 int fd;
1048 int ret;
1049 int i;
1051 rc = sqlite3_open(":memory:", &mem_db);
1052 if (rc != SQLITE_OK) {
1053 printf("Error starting In-Memory database.");
1054 return;
1057 for (i = 0; i < ARRAY_SIZE(schema_files); i++) {
1058 fd = open_data_file(schema_files[i]);
1059 if (fd < 0) {
1060 mem_db = NULL;
1061 return;
1063 ret = read(fd, buf, sizeof(buf));
1064 if (ret == sizeof(buf)) {
1065 printf("Schema file too large: %s (limit %zd bytes)",
1066 schema_files[i], sizeof(buf));
1068 buf[ret] = '\0';
1069 rc = sqlite3_exec(mem_db, buf, NULL, 0, &err);
1070 if (rc != SQLITE_OK) {
1071 fprintf(stderr, "SQL error #2: %s\n", err);
1072 fprintf(stderr, "%s\n", buf);
1077 void open_smatch_db(void)
1079 int rc;
1081 if (option_no_db)
1082 return;
1084 init_memdb();
1086 rc = sqlite3_open_v2("smatch_db.sqlite", &db, SQLITE_OPEN_READONLY, NULL);
1087 if (rc != SQLITE_OK) {
1088 option_no_db = 1;
1089 return;
1091 return;
1094 static void register_common_funcs(void)
1096 struct token *token;
1097 char *func;
1098 char filename[256];
1100 if (option_project == PROJ_NONE)
1101 strcpy(filename, "common_functions");
1102 else
1103 snprintf(filename, 256, "%s.common_functions", option_project_str);
1105 token = get_tokens_file(filename);
1106 if (!token)
1107 return;
1108 if (token_type(token) != TOKEN_STREAMBEGIN)
1109 return;
1110 token = token->next;
1111 while (token_type(token) != TOKEN_STREAMEND) {
1112 if (token_type(token) != TOKEN_IDENT)
1113 return;
1114 func = alloc_string(show_ident(token->ident));
1115 add_ptr_list(&common_funcs, func);
1116 token = token->next;
1118 clear_token_alloc();
1122 void register_definition_db_callbacks(int id)
1124 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
1125 add_hook(&global_variable, BASE_HOOK);
1126 add_hook(&global_variable, DECLARATION_HOOK);
1127 add_split_return_callback(match_return_info);
1128 add_split_return_callback(print_returned_struct_members);
1129 add_hook(&call_return_state_hooks, RETURN_HOOK);
1130 add_hook(&match_end_func_info, END_FUNC_HOOK);
1132 add_hook(&match_data_from_db, FUNC_DEF_HOOK);
1133 add_hook(&match_call_implies, CALL_HOOK_AFTER_INLINE);
1135 register_common_funcs();
1138 void register_db_call_marker(int id)
1140 add_hook(&match_call_marker, FUNCTION_CALL_HOOK);
1143 char *return_state_to_var_sym(struct expression *expr, int param, char *key, struct symbol **sym)
1145 struct expression *arg;
1146 char *name = NULL;
1147 char member_name[256];
1149 *sym = NULL;
1151 if (param == -1) {
1152 const char *star = "";
1154 if (expr->type != EXPR_ASSIGNMENT)
1155 return NULL;
1156 name = expr_to_var_sym(expr->left, sym);
1157 if (!name)
1158 return NULL;
1159 if (key[0] == '*') {
1160 star = "*";
1161 key++;
1163 if (strncmp(key, "$$", 2) != 0)
1164 return name;
1165 snprintf(member_name, sizeof(member_name), "%s%s%s", star, name, key + 2);
1166 free_string(name);
1167 return alloc_string(member_name);
1170 while (expr->type == EXPR_ASSIGNMENT)
1171 expr = strip_expr(expr->right);
1172 if (expr->type != EXPR_CALL)
1173 return NULL;
1175 arg = get_argument_from_call_expr(expr->args, param);
1176 if (!arg)
1177 return NULL;
1179 return get_variable_from_key(arg, key, sym);
1182 char *get_variable_from_key(struct expression *arg, char *key, struct symbol **sym)
1184 char buf[256];
1185 char *tmp;
1187 if (strcmp(key, "$$") == 0)
1188 return expr_to_var_sym(arg, sym);
1190 if (strcmp(key, "*$$") == 0) {
1191 if (arg->type == EXPR_PREOP && arg->op == '&') {
1192 arg = strip_expr(arg->unop);
1193 return expr_to_var_sym(arg, sym);
1194 } else {
1195 tmp = expr_to_var_sym(arg, sym);
1196 if (!tmp)
1197 return NULL;
1198 snprintf(buf, sizeof(buf), "*%s", tmp);
1199 free_string(tmp);
1200 return alloc_string(buf);
1204 if (arg->type == EXPR_PREOP && arg->op == '&') {
1205 arg = strip_expr(arg->unop);
1206 tmp = expr_to_var_sym(arg, sym);
1207 if (!tmp)
1208 return NULL;
1209 snprintf(buf, sizeof(buf), "%s.%s", tmp, key + 4);
1210 return alloc_string(buf);
1213 tmp = expr_to_var_sym(arg, sym);
1214 if (!tmp)
1215 return NULL;
1216 snprintf(buf, sizeof(buf), "%s%s", tmp, key + 2);
1217 free_string(tmp);
1218 return alloc_string(buf);
1221 const char *get_param_name(struct sm_state *sm)
1223 char *param_name;
1224 int name_len;
1225 static char buf[256];
1227 if (!sm->sym->ident)
1228 return NULL;
1230 param_name = sm->sym->ident->name;
1231 name_len = strlen(param_name);
1233 if (strcmp(sm->name, param_name) == 0) {
1234 return "$$";
1235 } else if (sm->name[name_len] == '-' && /* check for '-' from "->" */
1236 strncmp(sm->name, param_name, name_len) == 0) {
1237 snprintf(buf, sizeof(buf), "$$%s", sm->name + name_len);
1238 return buf;
1239 } else if (sm->name[0] == '*' && strcmp(sm->name + 1, param_name) == 0) {
1240 return "*$$";
1242 return NULL;