struct_assignment: move and improve handling smatch_data/*.clears_argument
[smatch.git] / smatch_db.c
bloba4683ded8be418e76a3fe5537add079004998a2f
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, const char *ranges)
219 sql_insert(function_type_size, "'%s', '%s', '%s', '%s'", get_base_file(), get_function(), member, ranges);
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 (is_fake_call(call))
285 return;
287 if (call->fn->type != EXPR_SYMBOL || !call->fn->symbol) {
288 sql_select_return_states_pointer(cols, call, callback);
289 return;
292 if (inlinable(call->fn)) {
293 mem_sql(callback,
294 "select %s from return_states where call_id = '%lu' order by return_id, type;",
295 cols, (unsigned long)call);
296 return;
299 row_count = 0;
300 run_sql(get_row_count, "select count(*) from return_states where %s;",
301 get_static_filter(call->fn->symbol));
302 if (row_count > 1000)
303 return;
305 run_sql(callback, "select %s from return_states where %s order by return_id, type;",
306 cols, get_static_filter(call->fn->symbol));
309 void sql_select_call_implies(const char *cols, struct expression *call,
310 int (*callback)(void*, int, char**, char**))
312 if (call->fn->type != EXPR_SYMBOL || !call->fn->symbol)
313 return;
315 if (inlinable(call->fn)) {
316 mem_sql(callback,
317 "select %s from call_implies where call_id = '%lu';",
318 cols, (unsigned long)call);
319 return;
322 run_sql(callback, "select %s from call_implies where %s;",
323 cols, get_static_filter(call->fn->symbol));
326 void sql_select_caller_info(const char *cols, struct symbol *sym,
327 int (*callback)(void*, int, char**, char**))
329 if (__inline_fn) {
330 mem_sql(callback, "select %s from caller_info where call_id = %lu;",
331 cols, (unsigned long)__inline_fn);
332 return;
335 run_sql(callback,
336 "select %s from caller_info where %s order by call_id;",
337 cols, get_static_filter(sym));
340 void select_caller_info_hook(void (*callback)(const char *name, struct symbol *sym, char *key, char *value), int type)
342 struct def_callback *def_callback = __alloc_def_callback(0);
344 def_callback->hook_type = type;
345 def_callback->callback = callback;
346 add_ptr_list(&callbacks, def_callback);
350 * These call backs are used when the --info option is turned on to print struct
351 * member information. For example foo->bar could have a state in
352 * smatch_extra.c and also check_user.c.
354 void add_member_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct smatch_state *state))
356 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
358 member_callback->owner = owner;
359 member_callback->callback = callback;
360 add_ptr_list(&member_callbacks, member_callback);
363 void add_split_return_callback(void (*fn)(int return_id, char *return_ranges, struct expression *returned_expr))
365 struct returned_state_callback *callback = __alloc_returned_state_callback(0);
367 callback->callback = fn;
368 add_ptr_list(&returned_state_callbacks, callback);
371 void add_returned_member_callback(int owner, void (*callback)(int return_id, char *return_ranges, char *printed_name, struct smatch_state *state))
373 struct returned_member_callback *member_callback = __alloc_returned_member_callback(0);
375 member_callback->owner = owner;
376 member_callback->callback = callback;
377 add_ptr_list(&returned_member_callbacks, member_callback);
380 void select_call_implies_hook(int type, void (*callback)(struct expression *arg, char *value))
382 struct call_implies_callback *cb = __alloc_call_implies_callback(0);
384 cb->type = type;
385 cb->callback = callback;
386 add_ptr_list(&call_implies_cb_list, cb);
389 static struct expression *static_call_expr;
390 static struct symbol *return_type;
391 static struct range_list *return_range_list;
392 static int db_return_callback(void *unused, int argc, char **argv, char **azColName)
394 struct range_list *rl;
396 if (argc != 1)
397 return 0;
398 call_results_to_rl(static_call_expr, return_type, argv[0], &rl);
399 return_range_list = rl_union(return_range_list, rl);
400 return 0;
403 struct range_list *db_return_vals(struct expression *expr)
405 static_call_expr = expr;
406 return_type = get_type(expr);
407 if (!return_type)
408 return NULL;
409 if (is_fake_call(expr))
410 return NULL;
411 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
412 return NULL;
414 return_range_list = NULL;
415 if (inlinable(expr->fn)) {
416 mem_sql(db_return_callback,
417 "select distinct return from return_states where call_id = '%lu';",
418 (unsigned long)expr);
419 } else {
420 run_sql(db_return_callback,
421 "select distinct return from return_states where %s;",
422 get_static_filter(expr->fn->symbol));
424 return return_range_list;
427 static void match_call_marker(struct expression *expr)
430 * we just want to record something in the database so that if we have
431 * two calls like: frob(4); frob(some_unkown); then on the receiving
432 * side we know that sometimes frob is called with unknown parameters.
435 sql_insert_caller_info(expr, INTERNAL, -1, "%call_marker%", "");
438 static void print_struct_members(struct expression *call, struct expression *expr, int param, struct state_list *slist,
439 void (*callback)(struct expression *call, int param, char *printed_name, struct smatch_state *state))
441 struct sm_state *sm;
442 char *name;
443 struct symbol *sym;
444 int len;
445 char printed_name[256];
446 int is_address = 0;
448 expr = strip_expr(expr);
449 if (expr->type == EXPR_PREOP && expr->op == '&') {
450 expr = strip_expr(expr->unop);
451 is_address = 1;
454 name = expr_to_var_sym(expr, &sym);
455 if (!name || !sym)
456 goto free;
458 len = strlen(name);
459 FOR_EACH_PTR(slist, sm) {
460 if (sm->sym != sym)
461 continue;
462 if (strcmp(name, sm->name) == 0) {
463 if (is_address)
464 snprintf(printed_name, sizeof(printed_name), "*$$");
465 else /* these are already handled. fixme: handle them here */
466 continue;
467 } else if (sm->name[0] == '*' && strcmp(name, sm->name + 1) == 0) {
468 snprintf(printed_name, sizeof(printed_name), "*$$");
469 } else if (strncmp(name, sm->name, len) == 0) {
470 if (is_address)
471 snprintf(printed_name, sizeof(printed_name), "$$->%s", sm->name + len + 1);
472 else
473 snprintf(printed_name, sizeof(printed_name), "$$%s", sm->name + len);
474 } else {
475 continue;
477 callback(call, param, printed_name, sm->state);
478 } END_FOR_EACH_PTR(sm);
479 free:
480 free_string(name);
483 static void match_call_info(struct expression *call)
485 struct member_info_callback *cb;
486 struct expression *arg;
487 struct state_list *slist;
488 char *name;
489 int i;
491 name = get_fnptr_name(call->fn);
492 if (!name)
493 return;
495 FOR_EACH_PTR(member_callbacks, cb) {
496 slist = get_all_states(cb->owner);
497 i = 0;
498 FOR_EACH_PTR(call->args, arg) {
499 print_struct_members(call, arg, i, slist, cb->callback);
500 i++;
501 } END_FOR_EACH_PTR(arg);
502 free_slist(&slist);
503 } END_FOR_EACH_PTR(cb);
505 free_string(name);
508 static int get_param(int param, char **name, struct symbol **sym)
510 struct symbol *arg;
511 int i;
513 i = 0;
514 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
516 * this is a temporary hack to work around a bug (I think in sparse?)
517 * 2.6.37-rc1:fs/reiserfs/journal.o
518 * If there is a function definition without parameter name found
519 * after a function implementation then it causes a crash.
520 * int foo() {}
521 * int bar(char *);
523 if (arg->ident->name < (char *)100)
524 continue;
525 if (i == param && arg->ident->name) {
526 *name = arg->ident->name;
527 *sym = arg;
528 return TRUE;
530 i++;
531 } END_FOR_EACH_PTR(arg);
533 return FALSE;
536 static struct state_list *final_states;
537 static int prev_func_id = -1;
538 static int db_callback(void *unused, int argc, char **argv, char **azColName)
540 int func_id;
541 long type;
542 long param;
543 char *name = NULL;
544 struct symbol *sym = NULL;
545 struct def_callback *def_callback;
546 struct state_list *slist;
548 if (argc != 5)
549 return 0;
551 func_id = atoi(argv[0]);
552 errno = 0;
553 type = strtol(argv[1], NULL, 10);
554 param = strtol(argv[2], NULL, 10);
555 if (errno)
556 return 0;
558 if (prev_func_id == -1)
559 prev_func_id = func_id;
560 if (func_id != prev_func_id) {
561 slist = __pop_fake_cur_slist();
562 merge_slist(&final_states, slist);
563 free_slist(&slist);
564 __push_fake_cur_slist();
565 __unnullify_path();
566 prev_func_id = func_id;
569 if (type == INTERNAL)
570 return 0;
571 if (param >= 0 && !get_param(param, &name, &sym))
572 return 0;
574 FOR_EACH_PTR(callbacks, def_callback) {
575 if (def_callback->hook_type == type)
576 def_callback->callback(name, sym, argv[3], argv[4]);
577 } END_FOR_EACH_PTR(def_callback);
579 return 0;
582 static void get_direct_callers(struct symbol *sym)
584 sql_select_caller_info("call_id, type, parameter, key, value", sym,
585 db_callback);
588 static struct string_list *ptr_names_done;
589 static struct string_list *ptr_names;
591 static int get_ptr_name(void *unused, int argc, char **argv, char **azColName)
593 insert_string(&ptr_names, alloc_string(argv[0]));
594 return 0;
597 static char *get_next_ptr_name(void)
599 char *ptr;
601 FOR_EACH_PTR(ptr_names, ptr) {
602 if (list_has_string(ptr_names_done, ptr))
603 continue;
604 insert_string(&ptr_names_done, ptr);
605 return ptr;
606 } END_FOR_EACH_PTR(ptr);
607 return NULL;
610 static void get_ptr_names(const char *file, const char *name)
612 char sql_filter[1024];
613 int before, after;
615 if (file) {
616 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
617 file, name);
618 } else {
619 snprintf(sql_filter, 1024, "function = '%s';", name);
622 before = ptr_list_size((struct ptr_list *)ptr_names);
624 run_sql(get_ptr_name,
625 "select distinct ptr from function_ptr where %s",
626 sql_filter);
628 after = ptr_list_size((struct ptr_list *)ptr_names);
629 if (before == after)
630 return;
632 while ((name = get_next_ptr_name()))
633 get_ptr_names(NULL, name);
636 static void get_function_pointer_callers(struct symbol *sym)
638 char *ptr;
640 if (sym->ctype.modifiers & MOD_STATIC)
641 get_ptr_names(get_base_file(), sym->ident->name);
642 else
643 get_ptr_names(NULL, sym->ident->name);
645 FOR_EACH_PTR(ptr_names, ptr) {
646 run_sql(db_callback, "select call_id, type, parameter, key, value"
647 " from caller_info where function = '%s' order by call_id",
648 ptr);
649 free_string(ptr);
650 } END_FOR_EACH_PTR(ptr);
652 __free_ptr_list((struct ptr_list **)&ptr_names);
653 __free_ptr_list((struct ptr_list **)&ptr_names_done);
656 static void match_data_from_db(struct symbol *sym)
658 struct sm_state *sm;
659 struct state_list *slist;
661 if (!sym || !sym->ident || !sym->ident->name)
662 return;
664 __push_fake_cur_slist();
665 __unnullify_path();
666 prev_func_id = -1;
668 get_direct_callers(sym);
669 if (!__inline_fn)
670 get_function_pointer_callers(sym);
672 slist = __pop_fake_cur_slist();
673 merge_slist(&final_states, slist);
674 free_slist(&slist);
676 FOR_EACH_PTR(final_states, sm) {
677 __set_sm(sm);
678 } END_FOR_EACH_PTR(sm);
680 free_slist(&final_states);
683 static int call_implies_callbacks(void *unused, int argc, char **argv, char **azColName)
685 struct call_implies_callback *cb;
686 struct expression *arg = NULL;
687 int type;
688 int param;
690 if (argc != 4)
691 return 0;
693 type = atoi(argv[1]);
694 param = atoi(argv[2]);
696 FOR_EACH_PTR(call_implies_cb_list, cb) {
697 if (cb->type != type)
698 continue;
699 if (param != -1) {
700 arg = get_argument_from_call_expr(static_call_expr->args, param);
701 if (!arg)
702 continue;
704 cb->callback(arg, argv[3]);
705 } END_FOR_EACH_PTR(cb);
707 return 0;
710 static void match_call_implies(struct expression *expr)
712 static_call_expr = expr;
713 sql_select_call_implies("function, type, parameter, value", expr,
714 call_implies_callbacks);
715 return;
718 static void print_initializer_list(struct expression_list *expr_list,
719 struct symbol *struct_type)
721 struct expression *expr;
722 struct symbol *base_type;
723 char struct_name[256];
725 FOR_EACH_PTR(expr_list, expr) {
726 if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) {
727 print_initializer_list(expr->idx_expression->expr_list, struct_type);
728 continue;
730 if (expr->type != EXPR_IDENTIFIER)
731 continue;
732 if (!expr->expr_ident)
733 continue;
734 if (!expr->ident_expression || !expr->ident_expression->symbol_name)
735 continue;
736 base_type = get_type(expr->ident_expression);
737 if (!base_type || base_type->type != SYM_FN)
738 continue;
739 snprintf(struct_name, sizeof(struct_name), "(struct %s)->%s",
740 struct_type->ident->name, expr->expr_ident->name);
741 sql_insert_function_ptr(expr->ident_expression->symbol_name->name,
742 struct_name);
743 } END_FOR_EACH_PTR(expr);
746 static void global_variable(struct symbol *sym)
748 struct symbol *struct_type;
750 if (!sym->ident)
751 return;
752 if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
753 return;
754 struct_type = get_base_type(sym);
755 if (!struct_type)
756 return;
757 if (struct_type->type == SYM_ARRAY) {
758 struct_type = get_base_type(struct_type);
759 if (!struct_type)
760 return;
762 if (struct_type->type != SYM_STRUCT || !struct_type->ident)
763 return;
764 print_initializer_list(sym->initializer->expr_list, struct_type);
767 static void match_return_info(int return_id, char *return_ranges, struct expression *expr)
769 sql_insert_return_states(return_id, return_ranges, INTERNAL, -1, "", "");
772 static void call_return_state_hooks_conditional(struct expression *expr)
774 struct returned_state_callback *cb;
775 struct range_list *rl;
776 char *return_ranges;
777 int final_pass_orig = final_pass;
779 __push_fake_cur_slist();
781 final_pass = 0;
782 __split_whole_condition(expr->conditional);
783 final_pass = final_pass_orig;
785 if (get_implied_rl(expr->cond_true, &rl))
786 rl = cast_rl(cur_func_return_type(), rl);
787 else
788 rl = cast_rl(cur_func_return_type(), alloc_whole_rl(get_type(expr->cond_true)));
789 return_ranges = show_rl(rl);
791 return_id++;
792 FOR_EACH_PTR(returned_state_callbacks, cb) {
793 cb->callback(return_id, return_ranges, expr);
794 } END_FOR_EACH_PTR(cb);
796 __push_true_states();
797 __use_false_states();
799 if (get_implied_rl(expr->cond_false, &rl))
800 rl = cast_rl(cur_func_return_type(), rl);
801 else
802 rl = cast_rl(cur_func_return_type(), alloc_whole_rl(get_type(expr->cond_false)));
803 return_ranges = show_rl(rl);
805 return_id++;
806 FOR_EACH_PTR(returned_state_callbacks, cb) {
807 cb->callback(return_id, return_ranges, expr);
808 } END_FOR_EACH_PTR(cb);
810 __merge_true_states();
811 __free_fake_cur_slist();
814 static void call_return_state_hooks_compare(struct expression *expr)
816 struct returned_state_callback *cb;
817 char *return_ranges;
818 int final_pass_orig = final_pass;
820 __push_fake_cur_slist();
822 final_pass = 0;
823 __split_whole_condition(expr);
824 final_pass = final_pass_orig;
826 return_ranges = alloc_sname("1");
828 return_id++;
829 FOR_EACH_PTR(returned_state_callbacks, cb) {
830 cb->callback(return_id, return_ranges, expr);
831 } END_FOR_EACH_PTR(cb);
833 __push_true_states();
834 __use_false_states();
836 return_ranges = alloc_sname("0");;
837 return_id++;
838 FOR_EACH_PTR(returned_state_callbacks, cb) {
839 cb->callback(return_id, return_ranges, expr);
840 } END_FOR_EACH_PTR(cb);
842 __merge_true_states();
843 __free_fake_cur_slist();
846 static int call_return_state_hooks_split_possible(struct expression *expr)
848 struct returned_state_callback *cb;
849 struct range_list *rl;
850 char *return_ranges;
851 struct sm_state *sm;
852 struct sm_state *tmp;
853 int ret = 0;
854 int nr_possible, nr_states;
855 char *compare_str;
856 char buf[128];
858 if (!expr || expr_equal_to_param(expr))
859 return 0;
861 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
862 if (!sm || !sm->merged)
863 return 0;
865 if (too_many_possible(sm))
866 return 0;
868 /* bail if it gets too complicated */
869 nr_possible = ptr_list_size((struct ptr_list *)sm->possible);
870 nr_states = ptr_list_size((struct ptr_list *)__get_cur_slist());
872 * the main thing option_info because we don't want to print a
873 * million lines of output. If someone else, like check_locking.c
874 * wants this data, then it doesn't cause a slow down to provide it.
876 if (option_info && nr_states * nr_possible >= 2000)
877 return 0;
879 compare_str = expr_lte_to_param(expr);
881 FOR_EACH_PTR(sm->possible, tmp) {
882 if (tmp->merged)
883 continue;
885 ret = 1;
886 __push_fake_cur_slist();
888 overwrite_states_using_pool(tmp);
890 rl = cast_rl(cur_func_return_type(), estate_rl(tmp->state));
891 return_ranges = show_rl(rl);
892 if (compare_str) {
893 snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
894 return_ranges = alloc_sname(buf);
897 return_id++;
898 FOR_EACH_PTR(returned_state_callbacks, cb) {
899 cb->callback(return_id, return_ranges, expr);
900 } END_FOR_EACH_PTR(cb);
902 __free_fake_cur_slist();
903 } END_FOR_EACH_PTR(tmp);
905 return ret;
908 static char *get_return_ranges_str(struct expression *expr)
910 struct range_list *rl;
911 char *return_ranges;
912 char *compare_str;
913 char buf[128];
915 if (!expr)
916 return alloc_sname("");
917 compare_str = expr_equal_to_param(expr);
918 if (compare_str)
919 return compare_str;
921 if (get_implied_rl(expr, &rl)) {
922 rl = cast_rl(cur_func_return_type(), rl);
923 return_ranges = show_rl(rl);
924 } else {
925 rl = cast_rl(cur_func_return_type(), alloc_whole_rl(get_type(expr)));
926 return_ranges = show_rl(rl);
928 compare_str = expr_lte_to_param(expr);
929 if (compare_str) {
930 snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
931 return alloc_sname(buf);
933 return return_ranges;
936 static int is_conditional(struct expression *expr)
938 if (!expr)
939 return 0;
940 if (expr->type == EXPR_CONDITIONAL || expr->type == EXPR_SELECT)
941 return 1;
942 return 0;
945 static void call_return_state_hooks(struct expression *expr)
947 struct returned_state_callback *cb;
948 char *return_ranges;
949 int nr_states;
951 expr = strip_expr(expr);
953 if (is_condition(expr)) {
954 call_return_state_hooks_compare(expr);
955 return;
956 } else if (is_conditional(expr)) {
957 call_return_state_hooks_conditional(expr);
958 return;
959 } else if (call_return_state_hooks_split_possible(expr)) {
960 return;
963 return_ranges = get_return_ranges_str(expr);
965 return_id++;
966 nr_states = ptr_list_size((struct ptr_list *)__get_cur_slist());
967 if (nr_states >= 10000) {
968 match_return_info(return_id, return_ranges, expr);
969 return;
971 FOR_EACH_PTR(returned_state_callbacks, cb) {
972 cb->callback(return_id, return_ranges, expr);
973 } END_FOR_EACH_PTR(cb);
976 static void print_returned_struct_members(int return_id, char *return_ranges, struct expression *expr)
978 struct returned_member_callback *cb;
979 struct state_list *my_slist;
980 struct sm_state *sm;
981 struct symbol *type;
982 char *name;
983 char member_name[256];
984 int len;
986 type = get_type(expr);
987 if (!type || type->type != SYM_PTR)
988 return;
989 name = expr_to_var(expr);
990 if (!name)
991 return;
993 member_name[sizeof(member_name) - 1] = '\0';
994 strcpy(member_name, "$$");
996 len = strlen(name);
997 FOR_EACH_PTR(returned_member_callbacks, cb) {
998 my_slist = get_all_states(cb->owner);
999 FOR_EACH_PTR(my_slist, sm) {
1000 if (sm->name[0] == '*' && strcmp(sm->name + 1, name) == 0) {
1001 strcpy(member_name, "*$$");
1002 cb->callback(return_id, return_ranges, member_name, sm->state);
1003 continue;
1005 if (strncmp(sm->name, name, len) != 0)
1006 continue;
1007 if (strncmp(sm->name + len, "->", 2) != 0)
1008 continue;
1009 strcpy(member_name, "$$");
1010 strncpy(member_name + 2, sm->name + len, sizeof(member_name) - 2);
1011 cb->callback(return_id, return_ranges, member_name, sm->state);
1012 } END_FOR_EACH_PTR(sm);
1013 free_slist(&my_slist);
1014 } END_FOR_EACH_PTR(cb);
1016 free_string(name);
1019 static void reset_memdb(void)
1021 mem_sql(NULL, "delete from caller_info;");
1022 mem_sql(NULL, "delete from return_states;");
1023 mem_sql(NULL, "delete from call_implies;");
1026 static void match_end_func_info(struct symbol *sym)
1028 if (__path_is_null())
1029 return;
1030 call_return_state_hooks(NULL);
1031 if (!__inline_fn)
1032 reset_memdb();
1035 static void init_memdb(void)
1037 char *err = NULL;
1038 int rc;
1039 const char *schema_files[] = {
1040 "db/db.schema",
1041 "db/caller_info.schema",
1042 "db/return_states.schema",
1043 "db/function_type_size.schema",
1044 "db/type_size.schema",
1045 "db/call_implies.schema",
1046 "db/function_ptr.schema",
1047 "db/local_values.schema",
1048 "db/function_type_value.schema",
1049 "db/type_value.schema",
1051 static char buf[4096];
1052 int fd;
1053 int ret;
1054 int i;
1056 rc = sqlite3_open(":memory:", &mem_db);
1057 if (rc != SQLITE_OK) {
1058 printf("Error starting In-Memory database.");
1059 return;
1062 for (i = 0; i < ARRAY_SIZE(schema_files); i++) {
1063 fd = open_data_file(schema_files[i]);
1064 if (fd < 0) {
1065 mem_db = NULL;
1066 return;
1068 ret = read(fd, buf, sizeof(buf));
1069 if (ret == sizeof(buf)) {
1070 printf("Schema file too large: %s (limit %zd bytes)",
1071 schema_files[i], sizeof(buf));
1073 buf[ret] = '\0';
1074 rc = sqlite3_exec(mem_db, buf, NULL, 0, &err);
1075 if (rc != SQLITE_OK) {
1076 fprintf(stderr, "SQL error #2: %s\n", err);
1077 fprintf(stderr, "%s\n", buf);
1082 void open_smatch_db(void)
1084 int rc;
1086 if (option_no_db)
1087 return;
1089 init_memdb();
1091 rc = sqlite3_open_v2("smatch_db.sqlite", &db, SQLITE_OPEN_READONLY, NULL);
1092 if (rc != SQLITE_OK) {
1093 option_no_db = 1;
1094 return;
1096 return;
1099 static void register_common_funcs(void)
1101 struct token *token;
1102 char *func;
1103 char filename[256];
1105 if (option_project == PROJ_NONE)
1106 strcpy(filename, "common_functions");
1107 else
1108 snprintf(filename, 256, "%s.common_functions", option_project_str);
1110 token = get_tokens_file(filename);
1111 if (!token)
1112 return;
1113 if (token_type(token) != TOKEN_STREAMBEGIN)
1114 return;
1115 token = token->next;
1116 while (token_type(token) != TOKEN_STREAMEND) {
1117 if (token_type(token) != TOKEN_IDENT)
1118 return;
1119 func = alloc_string(show_ident(token->ident));
1120 add_ptr_list(&common_funcs, func);
1121 token = token->next;
1123 clear_token_alloc();
1127 void register_definition_db_callbacks(int id)
1129 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
1130 add_hook(&global_variable, BASE_HOOK);
1131 add_hook(&global_variable, DECLARATION_HOOK);
1132 add_split_return_callback(match_return_info);
1133 add_split_return_callback(print_returned_struct_members);
1134 add_hook(&call_return_state_hooks, RETURN_HOOK);
1135 add_hook(&match_end_func_info, END_FUNC_HOOK);
1137 add_hook(&match_data_from_db, FUNC_DEF_HOOK);
1138 add_hook(&match_call_implies, CALL_HOOK_AFTER_INLINE);
1140 register_common_funcs();
1143 void register_db_call_marker(int id)
1145 add_hook(&match_call_marker, FUNCTION_CALL_HOOK);
1148 char *return_state_to_var_sym(struct expression *expr, int param, char *key, struct symbol **sym)
1150 struct expression *arg;
1151 char *name = NULL;
1152 char member_name[256];
1154 *sym = NULL;
1156 if (param == -1) {
1157 const char *star = "";
1159 if (expr->type != EXPR_ASSIGNMENT)
1160 return NULL;
1161 name = expr_to_var_sym(expr->left, sym);
1162 if (!name)
1163 return NULL;
1164 if (key[0] == '*') {
1165 star = "*";
1166 key++;
1168 if (strncmp(key, "$$", 2) != 0)
1169 return name;
1170 snprintf(member_name, sizeof(member_name), "%s%s%s", star, name, key + 2);
1171 free_string(name);
1172 return alloc_string(member_name);
1175 while (expr->type == EXPR_ASSIGNMENT)
1176 expr = strip_expr(expr->right);
1177 if (expr->type != EXPR_CALL)
1178 return NULL;
1180 arg = get_argument_from_call_expr(expr->args, param);
1181 if (!arg)
1182 return NULL;
1184 return get_variable_from_key(arg, key, sym);
1187 char *get_variable_from_key(struct expression *arg, char *key, struct symbol **sym)
1189 char buf[256];
1190 char *tmp;
1192 if (strcmp(key, "$$") == 0)
1193 return expr_to_var_sym(arg, sym);
1195 if (strcmp(key, "*$$") == 0) {
1196 if (arg->type == EXPR_PREOP && arg->op == '&') {
1197 arg = strip_expr(arg->unop);
1198 return expr_to_var_sym(arg, sym);
1199 } else {
1200 tmp = expr_to_var_sym(arg, sym);
1201 if (!tmp)
1202 return NULL;
1203 snprintf(buf, sizeof(buf), "*%s", tmp);
1204 free_string(tmp);
1205 return alloc_string(buf);
1209 if (arg->type == EXPR_PREOP && arg->op == '&') {
1210 arg = strip_expr(arg->unop);
1211 tmp = expr_to_var_sym(arg, sym);
1212 if (!tmp)
1213 return NULL;
1214 snprintf(buf, sizeof(buf), "%s.%s", tmp, key + 4);
1215 return alloc_string(buf);
1218 tmp = expr_to_var_sym(arg, sym);
1219 if (!tmp)
1220 return NULL;
1221 snprintf(buf, sizeof(buf), "%s%s", tmp, key + 2);
1222 free_string(tmp);
1223 return alloc_string(buf);
1226 const char *get_param_name(struct sm_state *sm)
1228 char *param_name;
1229 int name_len;
1230 static char buf[256];
1232 if (!sm->sym->ident)
1233 return NULL;
1235 param_name = sm->sym->ident->name;
1236 name_len = strlen(param_name);
1238 if (strcmp(sm->name, param_name) == 0) {
1239 return "$$";
1240 } else if (sm->name[name_len] == '-' && /* check for '-' from "->" */
1241 strncmp(sm->name, param_name, name_len) == 0) {
1242 snprintf(buf, sizeof(buf), "$$%s", sm->name + name_len);
1243 return buf;
1244 } else if (sm->name[0] == '*' && strcmp(sm->name + 1, param_name) == 0) {
1245 return "*$$";
1247 return NULL;