param_key: use get_name_sym_from_key() instead of return_state_to_var_sym()
[smatch.git] / smatch_db.c
blobbb81a80b37609d9ade4662cd07e4fe04ba8bad33
1 /*
2 * Copyright (C) 2010 Dan Carpenter.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
18 #include <string.h>
19 #include <errno.h>
20 #include <unistd.h>
21 #include <ctype.h>
22 #include "smatch.h"
23 #include "smatch_slist.h"
24 #include "smatch_extra.h"
26 struct sqlite3 *smatch_db;
27 struct sqlite3 *mem_db;
28 struct sqlite3 *cache_db;
30 int debug_db;
32 STATE(incomplete);
33 static int my_id;
35 static int return_id;
37 static void call_return_state_hooks(struct expression *expr);
39 #define SQLITE_CACHE_PAGES 1000
41 struct def_callback {
42 int hook_type;
43 void (*callback)(const char *name, struct symbol *sym, char *key, char *value);
45 ALLOCATOR(def_callback, "definition db hook callbacks");
46 DECLARE_PTR_LIST(callback_list, struct def_callback);
47 static struct callback_list *select_caller_info_callbacks;
49 struct member_info_callback {
50 int owner;
51 void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm);
53 ALLOCATOR(member_info_callback, "caller_info callbacks");
54 DECLARE_PTR_LIST(member_info_cb_list, struct member_info_callback);
55 static struct member_info_cb_list *member_callbacks;
56 static struct member_info_cb_list *member_callbacks_new;
58 struct return_info_callback {
59 int owner;
60 void (*callback)(int return_id, char *return_ranges,
61 struct expression *returned_expr,
62 int param,
63 const char *printed_name,
64 struct sm_state *sm);
66 ALLOCATOR(return_info_callback, "return_info callbacks");
67 DECLARE_PTR_LIST(return_info_cb_list, struct return_info_callback);
68 static struct return_info_cb_list *return_callbacks;
70 struct returned_state_callback {
71 void (*callback)(int return_id, char *return_ranges, struct expression *return_expr);
73 ALLOCATOR(returned_state_callback, "returned state callbacks");
74 DECLARE_PTR_LIST(returned_state_cb_list, struct returned_state_callback);
75 static struct returned_state_cb_list *returned_state_callbacks;
77 struct returned_member_callback {
78 int owner;
79 void (*callback)(int return_id, char *return_ranges, struct expression *expr, char *printed_name, struct smatch_state *state);
81 ALLOCATOR(returned_member_callback, "returned member callbacks");
82 DECLARE_PTR_LIST(returned_member_cb_list, struct returned_member_callback);
83 static struct returned_member_cb_list *returned_member_callbacks;
85 struct db_implies_callback {
86 int type;
87 void (*callback)(struct expression *call, struct expression *arg, char *key, char *value);
89 ALLOCATOR(db_implies_callback, "return_implies callbacks");
90 DECLARE_PTR_LIST(db_implies_cb_list, struct db_implies_callback);
91 static struct db_implies_cb_list *return_implies_cb_list;
92 static struct db_implies_cb_list *call_implies_cb_list;
94 /* silently truncates if needed. */
95 char *escape_newlines(const char *str)
97 char buf[1024] = "";
98 bool found = false;
99 int i, j;
101 for (i = 0, j = 0; str[i] != '\0' && j != sizeof(buf); i++, j++) {
102 if (str[i] != '\r' && str[i] != '\n') {
103 buf[j] = str[i];
104 continue;
107 found = true;
108 buf[j++] = '\\';
109 if (j == sizeof(buf))
110 break;
111 buf[j] = 'n';
114 if (!found)
115 return alloc_sname(str);
117 if (j == sizeof(buf))
118 buf[j - 1] = '\0';
119 return alloc_sname(buf);
122 static int print_sql_output(void *unused, int argc, char **argv, char **azColName)
124 int i;
126 for (i = 0; i < argc; i++) {
127 if (i != 0)
128 sm_printf(", ");
129 sm_printf("%s", argv[i]);
131 sm_printf("\n");
132 return 0;
135 void sql_exec(struct sqlite3 *db, int (*callback)(void*, int, char**, char**), void *data, const char *sql)
137 char *err = NULL;
138 int rc;
140 if (!db)
141 return;
143 if (option_debug || debug_db) {
144 sm_msg("%s", sql);
145 if (strncasecmp(sql, "select", strlen("select")) == 0)
146 sqlite3_exec(db, sql, print_sql_output, NULL, NULL);
149 rc = sqlite3_exec(db, sql, callback, data, &err);
150 if (rc != SQLITE_OK && !parse_error) {
151 sm_ierror("%s:%d SQL error #2: %s\n", get_filename(), get_lineno(), err);
152 sm_ierror("%s:%d SQL: '%s'\n", get_filename(), get_lineno(), sql);
153 parse_error = 1;
157 static int replace_count;
158 static char **replace_table;
159 static const char *replace_return_ranges(const char *return_ranges)
161 int i;
163 if (!get_function()) {
164 /* I have no idea why EXPORT_SYMBOL() is here */
165 return return_ranges;
167 for (i = 0; i < replace_count; i += 3) {
168 if (strcmp(replace_table[i + 0], get_function()) == 0) {
169 if (strcmp(replace_table[i + 1], return_ranges) == 0)
170 return replace_table[i + 2];
173 return return_ranges;
177 static char *use_states;
178 static int get_db_state_count(void)
180 struct sm_state *sm;
181 int count = 0;
183 FOR_EACH_SM(__get_cur_stree(), sm) {
184 if (sm->owner == USHRT_MAX)
185 continue;
186 if (use_states[sm->owner])
187 count++;
188 } END_FOR_EACH_SM(sm);
189 return count;
192 void db_ignore_states(int id)
194 use_states[id] = 0;
197 unsigned long long __fn_mtag;
198 static void set_fn_mtag(struct symbol *sym)
200 char buf[128];
202 if (cur_func_sym->ctype.modifiers & MOD_STATIC)
203 snprintf(buf, sizeof(buf), "%s %s", get_base_file(), get_function());
204 else
205 snprintf(buf, sizeof(buf), "extern %s", get_function());
207 __fn_mtag = str_to_mtag(buf);
210 void sql_insert_return_states(int return_id, const char *return_ranges,
211 int type, int param, const char *key, const char *value)
213 unsigned long long id;
216 if (key && strlen(key) >= 80)
217 return;
218 if (__inline_fn)
219 id = (unsigned long)__inline_fn;
220 else
221 id = __fn_mtag;
223 return_ranges = replace_return_ranges(return_ranges);
224 sql_insert(return_states, "'%s', '%s', %llu, %d, '%s', %d, %d, %d, '%s', '%s'",
225 get_base_file(), get_function(), id, return_id,
226 return_ranges, fn_static(), type, param, key, value);
229 static struct string_list *common_funcs;
230 static int is_common_function(const char *fn)
232 char *tmp;
234 if (!fn)
235 return 0;
237 if (strncmp(fn, "__builtin_", 10) == 0)
238 return 1;
240 FOR_EACH_PTR(common_funcs, tmp) {
241 if (strcmp(tmp, fn) == 0)
242 return 1;
243 } END_FOR_EACH_PTR(tmp);
245 return 0;
248 static char *function_signature(void)
250 return type_to_str(get_real_base_type(cur_func_sym));
253 void sql_insert_caller_info(struct expression *call, int type,
254 int param, const char *key, const char *value)
256 FILE *tmp_fd = sm_outfd;
257 char *fn;
259 if (!option_info && !__inline_call)
260 return;
261 if (unreachable())
262 return;
264 if (key && strlen(key) >= 80)
265 return;
267 fn = get_fnptr_name(call->fn);
268 if (!fn)
269 return;
271 if (__inline_call) {
272 mem_sql(NULL, NULL,
273 "insert into caller_info values ('%s', '%s', '%s', %lu, %d, %d, %d, '%s', '%s');",
274 get_base_file(), get_function(), fn, (unsigned long)call,
275 is_static(call->fn), type, param, key, value);
278 if (!option_info)
279 return;
281 if (strncmp(fn, "__builtin_", 10) == 0)
282 return;
283 if (type != INTERNAL && is_common_function(fn))
284 return;
286 sm_outfd = caller_info_fd;
287 sm_msg("SQL_caller_info: insert into caller_info values ("
288 "'%s', '%s', '%s', %%CALL_ID%%, %d, %d, %d, '%s', '%s');",
289 get_base_file(), get_function(), fn, is_static(call->fn),
290 type, param, key, value);
291 sm_outfd = tmp_fd;
293 free_string(fn);
296 void sql_insert_function_ptr(const char *fn, const char *struct_name)
298 sql_insert_or_ignore(function_ptr, "'%s', '%s', '%s', 0",
299 get_base_file(), fn, struct_name);
302 void sql_insert_return_implies(int type, int param, const char *key, const char *value)
304 sql_insert_or_ignore(return_implies, "'%s', '%s', %lu, %d, %d, %d, '%s', '%s'",
305 get_base_file(), get_function(), (unsigned long)__inline_fn,
306 fn_static(), type, param, key, value);
309 void sql_insert_call_implies(int type, int param, const char *key, const char *value)
311 sql_insert_or_ignore(call_implies, "'%s', '%s', %lu, %d, %d, %d, '%s', '%s'",
312 get_base_file(), get_function(), (unsigned long)__inline_fn,
313 fn_static(), type, param, key, value);
316 void sql_insert_function_type_size(const char *member, const char *ranges)
318 sql_insert(function_type_size, "'%s', '%s', '%s', '%s'", get_base_file(), get_function(), member, ranges);
321 void sql_insert_function_type_info(int type, const char *struct_type, const char *member, const char *value)
323 sql_insert(function_type_info, "'%s', '%s', %d, '%s', '%s', '%s'", get_base_file(), get_function(), type, struct_type, member, value);
326 void sql_insert_type_info(int type, const char *member, const char *value)
328 sql_insert_cache(type_info, "'%s', %d, '%s', '%s'", get_base_file(), type, member, value);
331 void sql_insert_local_values(const char *name, const char *value)
333 sql_insert(local_values, "'%s', '%s', '%s'", get_base_file(), name, value);
336 void sql_insert_function_type_value(const char *type, const char *value)
338 sql_insert(function_type_value, "'%s', '%s', '%s', '%s'", get_base_file(), get_function(), type, value);
341 void sql_insert_function_type(int param, const char *value)
343 sql_insert(function_type, "'%s', '%s', %d, %d, '%s'",
344 get_base_file(), get_function(), fn_static(), param, value);
347 void sql_insert_parameter_name(int param, const char *value)
349 sql_insert(parameter_name, "'%s', '%s', %d, %d, '%s'",
350 get_base_file(), get_function(), fn_static(), param, value);
353 void sql_insert_data_info(struct expression *data, int type, const char *value)
355 char *data_name;
357 data_name = get_data_info_name(data);
358 if (!data_name)
359 return;
360 sql_insert(data_info, "'%s', '%s', %d, '%s'",
361 is_static(data) ? get_base_file() : "extern",
362 data_name, type, value);
365 void sql_insert_data_info_var_sym(const char *var, struct symbol *sym, int type, const char *value)
367 sql_insert(data_info, "'%s', '%s', %d, '%s'",
368 (sym->ctype.modifiers & MOD_STATIC) ? get_base_file() : "extern",
369 var, type, value);
372 void sql_save_constraint(const char *con)
374 if (!option_info)
375 return;
377 sm_msg("SQL: insert or ignore into constraints (str) values('%s');", escape_newlines(con));
380 void sql_save_constraint_required(const char *data, int op, const char *limit)
382 sql_insert_or_ignore(constraints_required, "'%s', '%s', '%s'", data, show_special(op), limit);
385 void sql_copy_constraint_required(const char *new_limit, const char *old_limit)
387 if (!option_info)
388 return;
390 sm_msg("SQL_late: insert or ignore into constraints_required (data, op, bound) "
391 "select constraints_required.data, constraints_required.op, '%s' from "
392 "constraints_required where bound = '%s';", new_limit, old_limit);
395 void sql_insert_fn_ptr_data_link(const char *ptr, const char *data)
397 sql_insert_or_ignore(fn_ptr_data_link, "'%s', '%s'", ptr, data);
400 void sql_insert_fn_data_link(struct expression *fn, int type, int param, const char *key, const char *value)
402 if (fn->type != EXPR_SYMBOL || !fn->symbol->ident)
403 return;
405 sql_insert(fn_data_link, "'%s', '%s', %d, %d, %d, '%s', '%s'",
406 (fn->symbol->ctype.modifiers & MOD_STATIC) ? get_base_file() : "extern",
407 fn->symbol->ident->name,
408 !!(fn->symbol->ctype.modifiers & MOD_STATIC),
409 type, param, key, value);
412 void sql_insert_mtag_about(mtag_t tag, const char *left_name, const char *right_name)
414 sql_insert_cache(mtag_about, "%lld, '%s', '%s', %d, '%s', '%s'",
415 tag, get_filename(), get_function(), get_lineno(),
416 left_name, right_name);
419 void sql_insert_mtag_info(mtag_t tag, int type, const char *value)
421 sql_insert_cache(mtag_info, "'%s', %lld, %d, '%s'", get_filename(), tag, type, value);
424 void sql_insert_mtag_map(mtag_t container, int container_offset, mtag_t tag, int tag_offset)
426 sql_insert(mtag_map, "%lld, %d, %lld, %d", container, container_offset, tag, tag_offset);
429 void sql_insert_mtag_alias(mtag_t orig, mtag_t alias)
431 sql_insert(mtag_alias, "%lld, %lld", orig, alias);
434 static int save_mtag(void *_tag, int argc, char **argv, char **azColName)
436 mtag_t *saved_tag = _tag;
437 mtag_t new_tag;
439 new_tag = strtoll(argv[0], NULL, 10);
441 if (!*saved_tag)
442 *saved_tag = new_tag;
443 else if (*saved_tag != new_tag)
444 *saved_tag = -1ULL;
446 return 0;
449 int mtag_map_select_container(mtag_t tag, int container_offset, mtag_t *container)
451 mtag_t tmp = 0;
453 run_sql(save_mtag, &tmp,
454 "select container from mtag_map where tag = %lld and container_offset = %d and tag_offset = 0;",
455 tag, container_offset);
457 if (tmp == 0 || tmp == -1ULL)
458 return 0;
459 *container = tmp;
460 return 1;
463 int mtag_map_select_tag(mtag_t container, int offset, mtag_t *tag)
465 mtag_t tmp = 0;
467 run_sql(save_mtag, &tmp,
468 "select tag from mtag_map where container = %lld and container_offset = %d;",
469 container, offset);
471 if (tmp == 0 || tmp == -1ULL)
472 return 0;
473 *tag = tmp;
474 return 1;
477 char *get_static_filter(struct symbol *sym)
479 static char sql_filter[1024];
481 /* This can only happen on buggy code. Return invalid SQL. */
482 if (!sym) {
483 sql_filter[0] = '\0';
484 return sql_filter;
487 if (sym->ctype.modifiers & MOD_STATIC) {
488 snprintf(sql_filter, sizeof(sql_filter),
489 "file = '%s' and function = '%s' and static = '1'",
490 get_base_file(), sym->ident->name);
491 } else {
492 snprintf(sql_filter, sizeof(sql_filter),
493 "function = '%s' and static = '0'", sym->ident->name);
496 return sql_filter;
499 static int get_row_count(void *_row_count, int argc, char **argv, char **azColName)
501 int *row_count = _row_count;
503 *row_count = 0;
504 if (argc != 1)
505 return 0;
506 *row_count = atoi(argv[0]);
507 return 0;
510 static void mark_call_params_untracked(struct expression *call)
512 struct expression *arg;
513 int i = 0;
515 FOR_EACH_PTR(call->args, arg) {
516 mark_untracked(call, i++, "$", NULL);
517 } END_FOR_EACH_PTR(arg);
520 static void sql_select_return_states_pointer(const char *cols,
521 struct expression *call, int (*callback)(void*, int, char**, char**), void *info)
523 char *ptr;
524 int return_count = 0;
526 ptr = get_fnptr_name(call->fn);
527 if (!ptr)
528 return;
530 run_sql(get_row_count, &return_count,
531 "select count(*) from return_states join function_ptr "
532 "where return_states.function == function_ptr.function and "
533 "ptr = '%s' and searchable = 1 and type = %d;", ptr, INTERNAL);
534 /* The magic number 100 is just from testing on the kernel. */
535 if (return_count > 100) {
536 mark_call_params_untracked(call);
537 return;
540 run_sql(callback, info,
541 "select %s from return_states join function_ptr where "
542 "return_states.function == function_ptr.function and ptr = '%s' "
543 "and searchable = 1 "
544 "order by function_ptr.file, return_states.file, return_id, type;",
545 cols, ptr);
548 static int is_local_symbol(struct expression *expr)
550 if (expr->type != EXPR_SYMBOL)
551 return 0;
552 if (expr->symbol->ctype.modifiers & (MOD_NONLOCAL | MOD_STATIC | MOD_ADDRESSABLE))
553 return 0;
554 return 1;
557 void sql_select_return_states(const char *cols, struct expression *call,
558 int (*callback)(void*, int, char**, char**), void *info)
560 struct expression *fn;
561 int row_count = 0;
563 if (is_fake_call(call))
564 return;
566 fn = strip_expr(call->fn);
567 if (fn->type != EXPR_SYMBOL || !fn->symbol || is_local_symbol(fn)) {
568 sql_select_return_states_pointer(cols, call, callback, info);
569 return;
572 if (inlinable(fn)) {
573 mem_sql(callback, info,
574 "select %s from return_states where call_id = '%lu' order by return_id, type;",
575 cols, (unsigned long)call);
576 return;
579 run_sql(get_row_count, &row_count, "select count(*) from return_states where %s;",
580 get_static_filter(fn->symbol));
581 if (row_count == 0 && fn->symbol && fn->symbol->definition)
582 set_state(my_id, "db_incomplete", NULL, &incomplete);
583 if (row_count > 3000)
584 return;
586 run_sql(callback, info, "select %s from return_states where %s order by file, return_id, type;",
587 cols, get_static_filter(fn->symbol));
590 bool db_incomplete(void)
592 return !!get_state(my_id, "db_incomplete", NULL);
595 #define CALL_IMPLIES 0
596 #define RETURN_IMPLIES 1
598 struct implies_info {
599 int type;
600 struct db_implies_cb_list *cb_list;
601 struct expression *expr;
602 struct symbol *sym;
605 void sql_select_implies(const char *cols, struct implies_info *info,
606 int (*callback)(void*, int, char**, char**))
608 if (info->type == RETURN_IMPLIES && inlinable(info->expr->fn)) {
609 mem_sql(callback, info,
610 "select %s from return_implies where call_id = '%lu';",
611 cols, (unsigned long)info->expr);
612 return;
615 run_sql(callback, info, "select %s from %s_implies where %s;",
616 cols,
617 info->type == CALL_IMPLIES ? "call" : "return",
618 get_static_filter(info->sym));
621 struct select_caller_info_data {
622 struct stree *final_states;
623 struct timeval start_time;
624 int prev_func_id;
625 int ignore;
626 int results;
629 static int caller_info_callback(void *_data, int argc, char **argv, char **azColName);
631 static void sql_select_caller_info(struct select_caller_info_data *data,
632 const char *cols, struct symbol *sym)
634 if (__inline_fn) {
635 mem_sql(caller_info_callback, data,
636 "select %s from caller_info where call_id = %lu;",
637 cols, (unsigned long)__inline_fn);
638 return;
641 if (sym->ident->name && is_common_function(sym->ident->name))
642 return;
643 run_sql(caller_info_callback, data,
644 "select %s from common_caller_info where %s order by call_id;",
645 cols, get_static_filter(sym));
646 if (data->results)
647 return;
649 run_sql(caller_info_callback, data,
650 "select %s from caller_info where %s order by call_id;",
651 cols, get_static_filter(sym));
654 void select_caller_info_hook(void (*callback)(const char *name, struct symbol *sym, char *key, char *value), int type)
656 struct def_callback *def_callback = __alloc_def_callback(0);
658 def_callback->hook_type = type;
659 def_callback->callback = callback;
660 add_ptr_list(&select_caller_info_callbacks, def_callback);
664 * These call backs are used when the --info option is turned on to print struct
665 * member information. For example foo->bar could have a state in
666 * smatch_extra.c and also check_user.c.
668 void add_member_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
670 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
672 member_callback->owner = owner;
673 member_callback->callback = callback;
674 add_ptr_list(&member_callbacks, member_callback);
677 void add_caller_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
679 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
681 member_callback->owner = owner;
682 member_callback->callback = callback;
683 add_ptr_list(&member_callbacks_new, member_callback);
686 void add_return_info_callback(int owner,
687 void (*callback)(int return_id, char *return_ranges,
688 struct expression *returned_expr,
689 int param,
690 const char *printed_name,
691 struct sm_state *sm))
693 struct return_info_callback *return_callback = __alloc_return_info_callback(0);
695 return_callback->owner = owner;
696 return_callback->callback = callback;
697 add_ptr_list(&return_callbacks, return_callback);
700 void add_split_return_callback(void (*fn)(int return_id, char *return_ranges, struct expression *returned_expr))
702 struct returned_state_callback *callback = __alloc_returned_state_callback(0);
704 callback->callback = fn;
705 add_ptr_list(&returned_state_callbacks, callback);
708 void add_returned_member_callback(int owner, void (*callback)(int return_id, char *return_ranges, struct expression *expr, char *printed_name, struct smatch_state *state))
710 struct returned_member_callback *member_callback = __alloc_returned_member_callback(0);
712 member_callback->owner = owner;
713 member_callback->callback = callback;
714 add_ptr_list(&returned_member_callbacks, member_callback);
717 void select_call_implies_hook(int type, void (*callback)(struct expression *call, struct expression *arg, char *key, char *value))
719 struct db_implies_callback *cb = __alloc_db_implies_callback(0);
721 cb->type = type;
722 cb->callback = callback;
723 add_ptr_list(&call_implies_cb_list, cb);
726 void select_return_implies_hook(int type, void (*callback)(struct expression *call, struct expression *arg, char *key, char *value))
728 struct db_implies_callback *cb = __alloc_db_implies_callback(0);
730 cb->type = type;
731 cb->callback = callback;
732 add_ptr_list(&return_implies_cb_list, cb);
735 struct return_info {
736 struct expression *static_returns_call;
737 struct symbol *return_type;
738 struct range_list *return_range_list;
741 static int db_return_callback(void *_ret_info, int argc, char **argv, char **azColName)
743 struct return_info *ret_info = _ret_info;
744 struct range_list *rl;
745 struct expression *call_expr = ret_info->static_returns_call;
747 if (argc != 1)
748 return 0;
749 call_results_to_rl(call_expr, ret_info->return_type, argv[0], &rl);
750 ret_info->return_range_list = rl_union(ret_info->return_range_list, rl);
751 return 0;
754 struct range_list *db_return_vals(struct expression *expr)
756 struct return_info ret_info = {};
757 struct sm_state *sm;
759 if (is_fake_call(expr))
760 return NULL;
762 sm = get_extra_sm_state(expr);
763 if (sm)
764 return clone_rl(estate_rl(sm->state));
765 ret_info.static_returns_call = expr;
766 ret_info.return_type = get_type(expr);
767 if (!ret_info.return_type)
768 return NULL;
770 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
771 return NULL;
773 ret_info.return_range_list = NULL;
774 if (inlinable(expr->fn)) {
775 mem_sql(db_return_callback, &ret_info,
776 "select distinct return from return_states where call_id = '%lu';",
777 (unsigned long)expr);
778 } else {
779 run_sql(db_return_callback, &ret_info,
780 "select distinct return from return_states where %s;",
781 get_static_filter(expr->fn->symbol));
783 return ret_info.return_range_list;
786 struct range_list *db_return_vals_from_str(const char *fn_name)
788 struct return_info ret_info;
790 ret_info.static_returns_call = NULL;
791 ret_info.return_type = &llong_ctype;
792 ret_info.return_range_list = NULL;
794 run_sql(db_return_callback, &ret_info,
795 "select distinct return from return_states where function = '%s';",
796 fn_name);
797 return ret_info.return_range_list;
801 * This is used when we have a function that takes a function pointer as a
802 * parameter. "frob(blah, blah, my_function);" We know that the return values
803 * from frob() come from my_funcion() so we want to find the possible returns
804 * of my_function(), but we don't know which arguments are passed to it.
807 struct range_list *db_return_vals_no_args(struct expression *expr)
809 struct return_info ret_info = {};
811 if (!expr || expr->type != EXPR_SYMBOL)
812 return NULL;
814 ret_info.static_returns_call = expr;
815 ret_info.return_type = get_type(expr);
816 ret_info.return_type = get_real_base_type(ret_info.return_type);
817 if (!ret_info.return_type)
818 return NULL;
820 run_sql(db_return_callback, &ret_info,
821 "select distinct return from return_states where %s;",
822 get_static_filter(expr->symbol));
824 return ret_info.return_range_list;
827 static void match_call_marker(struct expression *expr)
829 struct symbol *type;
831 type = get_type(expr->fn);
832 if (type && type->type == SYM_PTR)
833 type = get_real_base_type(type);
836 * we just want to record something in the database so that if we have
837 * two calls like: frob(4); frob(some_unkown); then on the receiving
838 * side we know that sometimes frob is called with unknown parameters.
841 sql_insert_caller_info(expr, INTERNAL, -1, "%call_marker%", type_to_str(type));
844 int is_recursive_member(const char *name)
846 char buf[256];
847 const char *p, *next;
848 int size;
850 p = strchr(name, '>');
851 if (!p)
852 return 0;
853 p++;
854 while (true) {
855 next = strchr(p, '>');
856 if (!next)
857 return 0;
858 next++;
860 size = next - p;
861 if (size >= sizeof(buf))
862 return 0;
863 memcpy(buf, p, size);
864 buf[size] = '\0';
865 if (strstr(next, buf))
866 return 1;
867 p = next;
871 char *sm_to_arg_name(struct expression *expr, struct sm_state *sm)
873 struct symbol *sym;
874 const char *sm_name;
875 char *name;
876 bool is_address = false;
877 bool add_star = false;
878 char buf[256];
879 char *ret = NULL;
880 int len;
882 expr = strip_expr(expr);
883 if (!expr)
884 return NULL;
886 if (expr->type == EXPR_PREOP && expr->op == '&') {
887 expr = strip_expr(expr->unop);
888 is_address = true;
891 name = expr_to_var_sym(expr, &sym);
892 if (!name || !sym)
893 goto free;
894 if (sym != sm->sym)
895 goto free;
897 sm_name = sm->name;
898 add_star = false;
899 if (sm_name[0] == '*') {
900 add_star = true;
901 sm_name++;
904 len = strlen(name);
905 if (strncmp(name, sm_name, len) != 0)
906 goto free;
907 if (sm_name[len] == '\0') {
908 snprintf(buf, sizeof(buf), "%s%s$",
909 add_star ? "*" : "", is_address ? "*" : "");
910 } else {
911 if (sm_name[len] != '.' && sm_name[len] != '-')
912 goto free;
913 if (sm_name[len] == '-')
914 len++;
915 // FIXME does is_address really imply that sm_name[len] == '-'
916 snprintf(buf, sizeof(buf), "%s$->%s", add_star ? "*" : "",
917 sm_name + len);
920 ret = alloc_sname(buf);
921 free:
922 free_string(name);
923 return ret;
926 static void print_struct_members(struct expression *call, struct expression *expr, int param,
927 int owner,
928 void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm),
929 bool new)
931 struct sm_state *sm;
932 const char *sm_name;
933 char *name;
934 struct symbol *sym;
935 int len;
936 char printed_name[256];
937 int is_address = 0;
938 bool add_star;
939 struct symbol *type;
941 expr = strip_expr(expr);
942 if (!expr)
943 return;
944 type = get_type(expr);
945 if (!new && type && type_bits(type) < type_bits(&ulong_ctype))
946 return;
948 if (expr->type == EXPR_PREOP && expr->op == '&') {
949 expr = strip_expr(expr->unop);
950 is_address = 1;
953 name = expr_to_var_sym(expr, &sym);
954 if (!name || !sym)
955 goto free;
957 len = strlen(name);
958 FOR_EACH_SM(__get_cur_stree(), sm) {
959 if (sm->owner != owner || sm->sym != sym)
960 continue;
961 sm_name = sm->name;
962 add_star = false;
963 if (sm_name[0] == '*') {
964 add_star = true;
965 sm_name++;
967 // FIXME: simplify?
968 if (!add_star && strcmp(name, sm_name) == 0) {
969 if (is_address) {
970 snprintf(printed_name, sizeof(printed_name), "*$");
971 } else {
972 if (new)
973 snprintf(printed_name, sizeof(printed_name), "$");
974 else
975 continue;
977 } else if (add_star && strcmp(name, sm_name) == 0) {
978 snprintf(printed_name, sizeof(printed_name), "%s*$",
979 is_address ? "*" : "");
980 } else if (strncmp(name, sm_name, len) == 0) {
981 if (sm_name[len] != '.' && sm_name[len] != '-')
982 continue;
983 if (is_address && sm_name[len] == '.') {
984 snprintf(printed_name, sizeof(printed_name),
985 "%s$->%s", add_star ? "*" : "",
986 sm_name + len + 1);
987 } else if (is_address && sm_name[len] == '-') {
988 snprintf(printed_name, sizeof(printed_name),
989 "%s(*$)%s", add_star ? "*" : "",
990 sm_name + len);
991 } else {
992 snprintf(printed_name, sizeof(printed_name),
993 "%s$%s", add_star ? "*" : "",
994 sm_name + len);
996 } else {
997 continue;
999 if (is_recursive_member(printed_name))
1000 continue;
1001 callback(call, param, printed_name, sm);
1002 } END_FOR_EACH_SM(sm);
1003 free:
1004 free_string(name);
1007 static void match_call_info(struct expression *call)
1009 struct member_info_callback *cb;
1010 struct expression *arg;
1011 int i;
1013 FOR_EACH_PTR(member_callbacks, cb) {
1014 i = -1;
1015 FOR_EACH_PTR(call->args, arg) {
1016 i++;
1017 print_struct_members(call, arg, i, cb->owner, cb->callback, 0);
1018 } END_FOR_EACH_PTR(arg);
1019 } END_FOR_EACH_PTR(cb);
1022 static struct expression *get_fake_variable(struct expression *expr)
1024 struct expression *tmp;
1026 tmp = expr_get_fake_parent_expr(expr);
1027 if (!tmp || tmp->type != EXPR_ASSIGNMENT)
1028 return NULL;
1030 return tmp->left;
1033 static void match_call_info_new(struct expression *call)
1035 struct member_info_callback *cb;
1036 struct expression *arg, *tmp;
1037 int i;
1039 FOR_EACH_PTR(member_callbacks_new, cb) {
1040 i = -1;
1041 FOR_EACH_PTR(call->args, arg) {
1042 i++;
1043 tmp = get_fake_variable(arg);
1044 if (!tmp)
1045 tmp = arg;
1046 print_struct_members(call, tmp, i, cb->owner, cb->callback, 1);
1047 } END_FOR_EACH_PTR(arg);
1048 } END_FOR_EACH_PTR(cb);
1051 static int get_param(int param, char **name, struct symbol **sym)
1053 struct symbol *arg;
1054 int i;
1056 i = 0;
1057 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
1059 * this is a temporary hack to work around a bug (I think in sparse?)
1060 * 2.6.37-rc1:fs/reiserfs/journal.o
1061 * If there is a function definition without parameter name found
1062 * after a function implementation then it causes a crash.
1063 * int foo() {}
1064 * int bar(char *);
1066 if (arg->ident->name < (char *)100)
1067 continue;
1068 if (i == param) {
1069 *name = arg->ident->name;
1070 *sym = arg;
1071 return TRUE;
1073 i++;
1074 } END_FOR_EACH_PTR(arg);
1076 return FALSE;
1079 static int function_signature_matches(const char *sig)
1081 char *my_sig;
1083 my_sig = function_signature();
1084 if (!sig || !my_sig)
1085 return 1; /* default to matching */
1086 if (strcmp(my_sig, sig) == 0)
1087 return 1;
1088 return 0;
1091 static int caller_info_callback(void *_data, int argc, char **argv, char **azColName)
1093 struct select_caller_info_data *data = _data;
1094 int func_id;
1095 long type;
1096 long param;
1097 char *key;
1098 char *value;
1099 char *name = NULL;
1100 struct symbol *sym = NULL;
1101 struct def_callback *def_callback;
1102 struct stree *stree;
1103 struct timeval cur_time;
1105 data->results = 1;
1107 if (argc != 5)
1108 return 0;
1110 gettimeofday(&cur_time, NULL);
1111 if (cur_time.tv_sec - data->start_time.tv_sec > 10)
1112 return 0;
1114 func_id = atoi(argv[0]);
1115 errno = 0;
1116 type = strtol(argv[1], NULL, 10);
1117 param = strtol(argv[2], NULL, 10);
1118 if (errno)
1119 return 0;
1120 key = argv[3];
1121 value = argv[4];
1123 if (data->prev_func_id == -1)
1124 data->prev_func_id = func_id;
1125 if (func_id != data->prev_func_id) {
1126 stree = __pop_fake_cur_stree();
1127 if (!data->ignore)
1128 merge_stree(&data->final_states, stree);
1129 free_stree(&stree);
1130 __push_fake_cur_stree();
1131 __unnullify_path();
1132 data->prev_func_id = func_id;
1133 data->ignore = 0;
1136 if (data->ignore)
1137 return 0;
1138 if (type == INTERNAL &&
1139 !function_signature_matches(value)) {
1140 data->ignore = 1;
1141 return 0;
1144 if (param >= 0 && !get_param(param, &name, &sym))
1145 return 0;
1147 FOR_EACH_PTR(select_caller_info_callbacks, def_callback) {
1148 if (def_callback->hook_type == type)
1149 def_callback->callback(name, sym, key, value);
1150 } END_FOR_EACH_PTR(def_callback);
1152 return 0;
1155 static struct string_list *ptr_names_done;
1156 static struct string_list *ptr_names;
1158 static int get_ptr_name(void *unused, int argc, char **argv, char **azColName)
1160 insert_string(&ptr_names, alloc_string(argv[0]));
1161 return 0;
1164 static char *get_next_ptr_name(void)
1166 char *ptr;
1168 FOR_EACH_PTR(ptr_names, ptr) {
1169 if (!insert_string(&ptr_names_done, ptr))
1170 continue;
1171 return ptr;
1172 } END_FOR_EACH_PTR(ptr);
1173 return NULL;
1176 static void get_ptr_names(const char *file, const char *name)
1178 char sql_filter[1024];
1179 int before, after;
1181 if (file) {
1182 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
1183 file, name);
1184 } else {
1185 snprintf(sql_filter, 1024, "function = '%s';", name);
1188 before = ptr_list_size((struct ptr_list *)ptr_names);
1190 run_sql(get_ptr_name, NULL,
1191 "select distinct ptr from function_ptr where %s",
1192 sql_filter);
1194 after = ptr_list_size((struct ptr_list *)ptr_names);
1195 if (before == after)
1196 return;
1198 while ((name = get_next_ptr_name()))
1199 get_ptr_names(NULL, name);
1202 static void match_data_from_db(struct symbol *sym)
1204 struct select_caller_info_data data = { .prev_func_id = -1 };
1205 struct sm_state *sm;
1206 struct stree *stree;
1207 struct timeval end_time;
1209 if (!sym || !sym->ident)
1210 return;
1212 set_fn_mtag(sym);
1213 gettimeofday(&data.start_time, NULL);
1215 __push_fake_cur_stree();
1216 __unnullify_path();
1218 if (!__inline_fn) {
1219 char *ptr;
1221 if (sym->ctype.modifiers & MOD_STATIC)
1222 get_ptr_names(get_base_file(), sym->ident->name);
1223 else
1224 get_ptr_names(NULL, sym->ident->name);
1226 if (ptr_list_size((struct ptr_list *)ptr_names) > 20) {
1227 __free_ptr_list((struct ptr_list **)&ptr_names);
1228 __free_ptr_list((struct ptr_list **)&ptr_names_done);
1229 __free_fake_cur_stree();
1230 return;
1233 sql_select_caller_info(&data,
1234 "call_id, type, parameter, key, value",
1235 sym);
1238 stree = __pop_fake_cur_stree();
1239 if (!data.ignore)
1240 merge_stree(&data.final_states, stree);
1241 free_stree(&stree);
1242 __push_fake_cur_stree();
1243 __unnullify_path();
1244 data.prev_func_id = -1;
1245 data.ignore = 0;
1246 data.results = 0;
1248 FOR_EACH_PTR(ptr_names, ptr) {
1249 run_sql(caller_info_callback, &data,
1250 "select call_id, type, parameter, key, value"
1251 " from common_caller_info where function = '%s' order by call_id",
1252 ptr);
1253 } END_FOR_EACH_PTR(ptr);
1255 if (data.results) {
1256 FOR_EACH_PTR(ptr_names, ptr) {
1257 free_string(ptr);
1258 } END_FOR_EACH_PTR(ptr);
1259 goto free_ptr_names;
1262 FOR_EACH_PTR(ptr_names, ptr) {
1263 run_sql(caller_info_callback, &data,
1264 "select call_id, type, parameter, key, value"
1265 " from caller_info where function = '%s' order by call_id",
1266 ptr);
1267 free_string(ptr);
1268 } END_FOR_EACH_PTR(ptr);
1270 free_ptr_names:
1271 __free_ptr_list((struct ptr_list **)&ptr_names);
1272 __free_ptr_list((struct ptr_list **)&ptr_names_done);
1273 } else {
1274 sql_select_caller_info(&data,
1275 "call_id, type, parameter, key, value",
1276 sym);
1279 stree = __pop_fake_cur_stree();
1280 if (!data.ignore)
1281 merge_stree(&data.final_states, stree);
1282 free_stree(&stree);
1284 gettimeofday(&end_time, NULL);
1285 if (end_time.tv_sec - data.start_time.tv_sec <= 10) {
1286 FOR_EACH_SM(data.final_states, sm) {
1287 __set_sm(sm);
1288 } END_FOR_EACH_SM(sm);
1291 free_stree(&data.final_states);
1294 static int return_implies_callbacks(void *_info, int argc, char **argv, char **azColName)
1296 struct implies_info *info = _info;
1297 struct db_implies_callback *cb;
1298 struct expression *arg = NULL;
1299 int type;
1300 int param;
1302 if (argc != 5)
1303 return 0;
1305 type = atoi(argv[1]);
1306 param = atoi(argv[2]);
1308 FOR_EACH_PTR(info->cb_list, cb) {
1309 if (cb->type != type)
1310 continue;
1311 if (param != -1) {
1312 arg = get_argument_from_call_expr(info->expr->args, param);
1313 if (!arg)
1314 continue;
1316 cb->callback(info->expr, arg, argv[3], argv[4]);
1317 } END_FOR_EACH_PTR(cb);
1319 return 0;
1322 static int call_implies_callbacks(void *_info, int argc, char **argv, char **azColName)
1324 struct implies_info *info = _info;
1325 struct db_implies_callback *cb;
1326 struct expression *arg;
1327 struct symbol *sym;
1328 char *name;
1329 int type;
1330 int param;
1332 if (argc != 5)
1333 return 0;
1335 type = atoi(argv[1]);
1336 param = atoi(argv[2]);
1338 if (!get_param(param, &name, &sym))
1339 return 0;
1340 arg = symbol_expression(sym);
1341 if (!arg)
1342 return 0;
1344 FOR_EACH_PTR(info->cb_list, cb) {
1345 if (cb->type != type)
1346 continue;
1347 cb->callback(info->expr, arg, argv[3], argv[4]);
1348 } END_FOR_EACH_PTR(cb);
1350 return 0;
1353 static void match_return_implies(struct expression *expr)
1355 struct implies_info info = {
1356 .type = RETURN_IMPLIES,
1357 .cb_list = return_implies_cb_list,
1360 if (expr->fn->type != EXPR_SYMBOL ||
1361 !expr->fn->symbol)
1362 return;
1363 info.expr = expr;
1364 info.sym = expr->fn->symbol;
1365 sql_select_implies("function, type, parameter, key, value", &info,
1366 return_implies_callbacks);
1369 static void match_call_implies(struct symbol *sym)
1371 struct implies_info info = {
1372 .type = CALL_IMPLIES,
1373 .cb_list = call_implies_cb_list,
1376 if (!sym || !sym->ident)
1377 return;
1379 info.sym = sym;
1380 sql_select_implies("function, type, parameter, key, value", &info,
1381 call_implies_callbacks);
1384 static char *get_fn_param_str(struct expression *expr)
1386 struct expression *tmp;
1387 int param;
1388 char buf[32];
1390 tmp = get_assigned_expr(expr);
1391 if (tmp)
1392 expr = tmp;
1393 expr = strip_expr(expr);
1394 if (!expr || expr->type != EXPR_CALL)
1395 return NULL;
1396 expr = strip_expr(expr->fn);
1397 if (!expr || expr->type != EXPR_SYMBOL)
1398 return NULL;
1399 param = get_param_num(expr);
1400 if (param < 0)
1401 return NULL;
1403 snprintf(buf, sizeof(buf), "[r $%d]", param);
1404 return alloc_sname(buf);
1407 static char *get_return_compare_is_param(struct expression *expr)
1409 char *var;
1410 char buf[256];
1411 int comparison;
1412 int param;
1414 param = get_param_num(expr);
1415 if (param < 0)
1416 return NULL;
1418 var = expr_to_var(expr);
1419 if (!var)
1420 return NULL;
1421 snprintf(buf, sizeof(buf), "%s orig", var);
1422 comparison = get_comparison_strings(var, buf);
1423 free_string(var);
1425 if (!comparison)
1426 return NULL;
1428 snprintf(buf, sizeof(buf), "[%s$%d]", show_special(comparison), param);
1429 return alloc_sname(buf);
1432 static char *get_return_compare_str(struct expression *expr)
1434 char *compare_str;
1436 compare_str = get_return_compare_is_param(expr);
1437 if (compare_str)
1438 return compare_str;
1440 compare_str = expr_lte_to_param(expr, -1);
1441 if (compare_str)
1442 return compare_str;
1444 return expr_param_comparison(expr, -1);
1447 static const char *get_return_ranges_str(struct expression *expr, struct range_list **rl_p)
1449 struct range_list *rl;
1450 char *return_ranges;
1451 sval_t sval;
1452 char *fn_param_str;
1453 char *compare_str;
1454 char *math_str;
1455 char buf[128];
1457 *rl_p = NULL;
1459 if (!expr)
1460 return alloc_sname("");
1462 if (get_implied_value(expr, &sval)) {
1463 sval = sval_cast(cur_func_return_type(), sval);
1464 *rl_p = alloc_rl(sval, sval);
1465 return sval_to_str_or_err_ptr(sval);
1468 fn_param_str = get_fn_param_str(expr);
1469 compare_str = expr_equal_to_param(expr, -1);
1470 math_str = get_value_in_terms_of_parameter_math(expr);
1472 if (get_implied_rl(expr, &rl) && !is_whole_rl(rl)) {
1473 rl = cast_rl(cur_func_return_type(), rl);
1474 return_ranges = show_rl(rl);
1475 } else if (get_imaginary_absolute(expr, &rl)){
1476 rl = cast_rl(cur_func_return_type(), rl);
1477 return alloc_sname(show_rl(rl));
1478 } else {
1479 get_absolute_rl(expr, &rl);
1480 rl = cast_rl(cur_func_return_type(), rl);
1481 return_ranges = show_rl(rl);
1483 *rl_p = rl;
1485 if (fn_param_str) {
1486 snprintf(buf, sizeof(buf), "%s%s", return_ranges, fn_param_str);
1487 return alloc_sname(buf);
1489 if (compare_str) {
1490 snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
1491 return alloc_sname(buf);
1493 if (math_str) {
1494 snprintf(buf, sizeof(buf), "%s[%s]", return_ranges, math_str);
1495 return alloc_sname(buf);
1497 compare_str = get_return_compare_str(expr);
1498 if (compare_str) {
1499 snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
1500 return alloc_sname(buf);
1503 return return_ranges;
1506 static void match_return_info(int return_id, char *return_ranges, struct expression *expr)
1508 sql_insert_return_states(return_id, return_ranges, INTERNAL, -1, "", function_signature());
1511 static bool call_return_state_hooks_conditional(struct expression *expr)
1513 int final_pass_orig = final_pass;
1514 static int recurse;
1516 if (recurse >= 2)
1517 return false;
1518 if (!expr ||
1519 (expr->type != EXPR_CONDITIONAL && expr->type != EXPR_SELECT))
1520 return false;
1522 recurse++;
1524 __push_fake_cur_stree();
1526 final_pass = 0;
1527 __split_whole_condition(expr->conditional);
1528 final_pass = final_pass_orig;
1530 call_return_state_hooks(expr->cond_true ?: expr->conditional);
1532 __push_true_states();
1533 __use_false_states();
1535 call_return_state_hooks(expr->cond_false);
1537 __merge_true_states();
1538 __free_fake_cur_stree();
1540 recurse--;
1541 return true;
1544 static void call_return_state_hooks_compare(struct expression *expr)
1546 struct returned_state_callback *cb;
1547 char *return_ranges;
1548 int final_pass_orig = final_pass;
1549 sval_t sval = { .type = &int_ctype };
1550 sval_t ret;
1552 if (!get_implied_value(expr, &ret))
1553 ret.value = -1;
1555 __push_fake_cur_stree();
1557 final_pass = 0;
1558 __split_whole_condition(expr);
1559 final_pass = final_pass_orig;
1561 if (ret.value != 0) {
1562 return_ranges = alloc_sname("1");
1563 sval.value = 1;
1564 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_sval(sval));
1566 return_id++;
1567 FOR_EACH_PTR(returned_state_callbacks, cb) {
1568 cb->callback(return_id, return_ranges, expr);
1569 } END_FOR_EACH_PTR(cb);
1572 __push_true_states();
1573 __use_false_states();
1575 if (ret.value != 1) {
1576 return_ranges = alloc_sname("0");
1577 sval.value = 0;
1578 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_sval(sval));
1580 return_id++;
1581 FOR_EACH_PTR(returned_state_callbacks, cb) {
1582 cb->callback(return_id, return_ranges, expr);
1583 } END_FOR_EACH_PTR(cb);
1586 __merge_true_states();
1587 __free_fake_cur_stree();
1590 static bool is_implies_function(struct expression *expr)
1592 struct range_list *rl;
1594 if (!expr)
1595 return false;
1597 rl = get_range_implications(get_function());
1598 if (!rl)
1599 return false;
1601 sm_msg("%s: is implied", __func__);
1602 return true;
1605 static int ptr_in_list(struct sm_state *sm, struct state_list *slist)
1607 struct sm_state *tmp;
1609 FOR_EACH_PTR(slist, tmp) {
1610 if (strcmp(tmp->state->name, sm->state->name) == 0)
1611 return 1;
1612 } END_FOR_EACH_PTR(tmp);
1614 return 0;
1617 static int split_possible_helper(struct sm_state *sm, struct expression *expr)
1619 struct returned_state_callback *cb;
1620 struct range_list *rl;
1621 char *return_ranges;
1622 struct sm_state *tmp;
1623 int ret = 0;
1624 int nr_possible, nr_states;
1625 char *compare_str;
1626 char buf[128];
1627 struct state_list *already_handled = NULL;
1628 sval_t sval;
1630 if (!sm || !sm->merged)
1631 return 0;
1633 if (too_many_possible(sm) && !is_implies_function(expr))
1634 return 0;
1636 /* bail if it gets too complicated */
1637 nr_possible = 0;
1638 FOR_EACH_PTR(sm->possible, tmp) {
1639 if (tmp->merged)
1640 continue;
1641 if (ptr_in_list(tmp, already_handled))
1642 continue;
1643 add_ptr_list(&already_handled, tmp);
1644 nr_possible++;
1645 } END_FOR_EACH_PTR(tmp);
1646 free_slist(&already_handled);
1647 nr_states = get_db_state_count();
1648 if (nr_states * nr_possible >= 2000 && !is_implies_function(expr))
1649 return 0;
1651 FOR_EACH_PTR(sm->possible, tmp) {
1652 if (tmp->merged)
1653 continue;
1654 if (ptr_in_list(tmp, already_handled))
1655 continue;
1656 add_ptr_list(&already_handled, tmp);
1658 ret = 1;
1659 __push_fake_cur_stree();
1661 overwrite_states_using_pool(sm, tmp);
1663 rl = cast_rl(cur_func_return_type(), estate_rl(tmp->state));
1664 return_ranges = show_rl(rl);
1665 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(clone_rl(rl)));
1666 compare_str = get_return_compare_str(expr);
1667 /* ignore obvious stuff like 0 <= param */
1668 /* Is this worthile when we have PARAM_COMPARE? */
1669 if (compare_str &&
1670 strncmp(compare_str, "[=", 2) != 0 &&
1671 rl_to_sval(rl, &sval))
1672 compare_str = NULL;
1673 if (compare_str) {
1674 snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
1675 return_ranges = alloc_sname(buf);
1678 return_id++;
1679 FOR_EACH_PTR(returned_state_callbacks, cb) {
1680 cb->callback(return_id, return_ranges, expr);
1681 } END_FOR_EACH_PTR(cb);
1683 __free_fake_cur_stree();
1684 } END_FOR_EACH_PTR(tmp);
1686 free_slist(&already_handled);
1688 return ret;
1691 static int call_return_state_hooks_split_possible(struct expression *expr)
1693 struct expression *fake;
1694 struct sm_state *sm;
1696 if (!expr)
1697 return 0;
1699 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
1700 if (!sm) {
1701 fake = expr_get_fake_parent_expr(expr);
1702 if (!fake || fake->type != EXPR_ASSIGNMENT || fake->op != '=')
1703 return 0;
1704 fake = fake->left;
1705 sm = get_sm_state_expr(SMATCH_EXTRA, fake);
1707 return split_possible_helper(sm, expr);
1710 static bool has_possible_negative(struct sm_state *sm)
1712 struct sm_state *tmp;
1714 if (!type_signed(estate_type(sm->state)))
1715 return false;
1717 FOR_EACH_PTR(sm->possible, tmp) {
1718 if (!estate_rl(tmp->state))
1719 continue;
1720 if (sval_is_negative(estate_min(tmp->state)) &&
1721 sval_is_negative(estate_max(tmp->state)))
1722 return true;
1723 } END_FOR_EACH_PTR(tmp);
1725 return false;
1728 static bool has_separate_zero_null(struct sm_state *sm)
1730 struct sm_state *tmp;
1731 sval_t sval;
1733 FOR_EACH_PTR(sm->possible, tmp) {
1734 if (!estate_get_single_value(tmp->state, &sval))
1735 continue;
1736 if (sval.value == 0)
1737 return true;
1738 } END_FOR_EACH_PTR(tmp);
1740 return false;
1743 static int split_positive_from_negative(struct expression *expr)
1745 struct sm_state *sm;
1746 struct returned_state_callback *cb;
1747 struct range_list *rl;
1748 const char *return_ranges;
1749 struct range_list *ret_rl;
1750 bool separate_zero;
1751 int undo;
1753 /* We're going to print the states 3 times */
1754 if (get_db_state_count() > 10000 / 3)
1755 return 0;
1757 if (!get_implied_rl(expr, &rl) || !rl)
1758 return 0;
1759 /* Forget about INT_MAX and larger */
1760 if (rl_max(rl).value <= 0)
1761 return 0;
1762 if (!sval_is_negative(rl_min(rl)))
1763 return 0;
1765 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
1766 if (!sm)
1767 return 0;
1768 if (!has_possible_negative(sm))
1769 return 0;
1770 separate_zero = has_separate_zero_null(sm);
1772 if (!assume(compare_expression(expr, separate_zero ? '>' : SPECIAL_GTE, zero_expr())))
1773 return 0;
1775 return_id++;
1776 return_ranges = get_return_ranges_str(expr, &ret_rl);
1777 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
1778 FOR_EACH_PTR(returned_state_callbacks, cb) {
1779 cb->callback(return_id, (char *)return_ranges, expr);
1780 } END_FOR_EACH_PTR(cb);
1782 end_assume();
1784 if (separate_zero) {
1785 undo = assume(compare_expression(expr, SPECIAL_EQUAL, zero_expr()));
1787 return_id++;
1788 return_ranges = get_return_ranges_str(expr, &ret_rl);
1789 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
1790 FOR_EACH_PTR(returned_state_callbacks, cb) {
1791 cb->callback(return_id, (char *)return_ranges, expr);
1792 } END_FOR_EACH_PTR(cb);
1794 if (undo)
1795 end_assume();
1798 undo = assume(compare_expression(expr, '<', zero_expr()));
1800 return_id++;
1801 return_ranges = get_return_ranges_str(expr, &ret_rl);
1802 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
1803 FOR_EACH_PTR(returned_state_callbacks, cb) {
1804 cb->callback(return_id, (char *)return_ranges, expr);
1805 } END_FOR_EACH_PTR(cb);
1807 if (undo)
1808 end_assume();
1810 return 1;
1813 static int call_return_state_hooks_split_null_non_null_zero(struct expression *expr)
1815 struct returned_state_callback *cb;
1816 struct range_list *rl;
1817 struct range_list *nonnull_rl;
1818 sval_t null_sval;
1819 struct range_list *null_rl = NULL;
1820 char *return_ranges;
1821 struct sm_state *sm;
1822 struct smatch_state *state;
1823 int nr_states;
1824 int final_pass_orig = final_pass;
1826 if (!expr || expr_equal_to_param(expr, -1))
1827 return 0;
1828 if (expr->type == EXPR_CALL)
1829 return 0;
1831 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
1832 if (!sm)
1833 return 0;
1834 if (ptr_list_size((struct ptr_list *)sm->possible) == 1)
1835 return 0;
1836 state = sm->state;
1837 if (!estate_rl(state))
1838 return 0;
1839 if (estate_min(state).value == 0 && estate_max(state).value == 0)
1840 return 0;
1841 if (has_possible_negative(sm))
1842 return 0;
1843 if (!has_separate_zero_null(sm))
1844 return 0;
1846 nr_states = get_db_state_count();
1847 if (option_info && nr_states >= 1500)
1848 return 0;
1850 rl = estate_rl(state);
1852 __push_fake_cur_stree();
1854 final_pass = 0;
1855 __split_whole_condition(expr);
1856 final_pass = final_pass_orig;
1858 nonnull_rl = rl_filter(rl, rl_zero());
1859 return_ranges = show_rl(nonnull_rl);
1860 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(nonnull_rl));
1862 return_id++;
1863 FOR_EACH_PTR(returned_state_callbacks, cb) {
1864 cb->callback(return_id, return_ranges, expr);
1865 } END_FOR_EACH_PTR(cb);
1867 __push_true_states();
1868 __use_false_states();
1870 return_ranges = alloc_sname("0");
1871 null_sval = sval_type_val(rl_type(rl), 0);
1872 add_range(&null_rl, null_sval, null_sval);
1873 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(null_rl));
1874 return_id++;
1875 FOR_EACH_PTR(returned_state_callbacks, cb) {
1876 cb->callback(return_id, return_ranges, expr);
1877 } END_FOR_EACH_PTR(cb);
1879 __merge_true_states();
1880 __free_fake_cur_stree();
1882 return 1;
1885 static bool is_kernel_success_fail(struct sm_state *sm)
1887 struct sm_state *tmp;
1888 struct range_list *rl;
1889 bool has_zero = false;
1890 bool has_neg = false;
1892 if (!type_signed(estate_type(sm->state)))
1893 return false;
1895 FOR_EACH_PTR(sm->possible, tmp) {
1896 rl = estate_rl(tmp->state);
1897 if (!rl)
1898 return false;
1899 if (rl_min(rl).value == 0 && rl_max(rl).value == 0) {
1900 has_zero = true;
1901 continue;
1903 has_neg = true;
1904 if (rl_min(rl).value >= -4095 && rl_max(rl).value < 0)
1905 continue;
1906 if (strcmp(tmp->state->name, "s32min-(-1)") == 0)
1907 continue;
1908 if (strcmp(tmp->state->name, "s32min-(-1),1-s32max") == 0)
1909 continue;
1910 return false;
1911 } END_FOR_EACH_PTR(tmp);
1913 return has_zero && has_neg;
1916 static int call_return_state_hooks_split_success_fail(struct expression *expr)
1918 struct sm_state *sm;
1919 struct range_list *rl;
1920 struct range_list *nonzero_rl;
1921 sval_t zero_sval;
1922 struct range_list *zero_rl = NULL;
1923 int nr_states;
1924 struct returned_state_callback *cb;
1925 char *return_ranges;
1926 int final_pass_orig = final_pass;
1928 if (option_project != PROJ_KERNEL)
1929 return 0;
1931 nr_states = get_db_state_count();
1932 if (nr_states > 2000)
1933 return 0;
1935 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
1936 if (!sm)
1937 return 0;
1938 if (ptr_list_size((struct ptr_list *)sm->possible) == 1)
1939 return 0;
1940 if (!is_kernel_success_fail(sm))
1941 return 0;
1943 rl = estate_rl(sm->state);
1944 if (!rl)
1945 return 0;
1947 __push_fake_cur_stree();
1949 final_pass = 0;
1950 __split_whole_condition(expr);
1951 final_pass = final_pass_orig;
1953 nonzero_rl = rl_filter(rl, rl_zero());
1954 nonzero_rl = cast_rl(cur_func_return_type(), nonzero_rl);
1955 return_ranges = show_rl(nonzero_rl);
1956 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(nonzero_rl));
1958 return_id++;
1959 FOR_EACH_PTR(returned_state_callbacks, cb) {
1960 cb->callback(return_id, return_ranges, expr);
1961 } END_FOR_EACH_PTR(cb);
1963 __push_true_states();
1964 __use_false_states();
1966 return_ranges = alloc_sname("0");
1967 zero_sval = sval_type_val(rl_type(rl), 0);
1968 add_range(&zero_rl, zero_sval, zero_sval);
1969 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(zero_rl));
1970 return_id++;
1971 FOR_EACH_PTR(returned_state_callbacks, cb) {
1972 cb->callback(return_id, return_ranges, expr);
1973 } END_FOR_EACH_PTR(cb);
1975 __merge_true_states();
1976 __free_fake_cur_stree();
1978 return 1;
1981 static int is_boolean(struct expression *expr)
1983 struct range_list *rl;
1985 if (!get_implied_rl(expr, &rl))
1986 return 0;
1987 if (rl_min(rl).value == 0 && rl_max(rl).value == 1)
1988 return 1;
1989 return 0;
1992 static int splitable_function_call(struct expression *expr)
1994 struct sm_state *sm;
1996 if (!expr || expr->type != EXPR_CALL)
1997 return 0;
1998 sm = get_extra_sm_state(expr);
1999 return split_possible_helper(sm, expr);
2002 static struct sm_state *find_bool_param(void)
2004 struct stree *start_states;
2005 struct symbol *arg;
2006 struct sm_state *sm, *tmp;
2007 sval_t sval;
2009 start_states = get_start_states();
2011 FOR_EACH_PTR_REVERSE(cur_func_sym->ctype.base_type->arguments, arg) {
2012 if (!arg->ident)
2013 continue;
2014 sm = get_sm_state_stree(start_states, SMATCH_EXTRA, arg->ident->name, arg);
2015 if (!sm)
2016 continue;
2017 if (rl_min(estate_rl(sm->state)).value != 0 ||
2018 rl_max(estate_rl(sm->state)).value != 1)
2019 continue;
2020 goto found;
2021 } END_FOR_EACH_PTR_REVERSE(arg);
2023 return NULL;
2025 found:
2027 * Check if it's splitable. If not, then splitting it up is likely not
2028 * useful for the callers.
2030 FOR_EACH_PTR(sm->possible, tmp) {
2031 if (is_merged(tmp))
2032 continue;
2033 if (!estate_get_single_value(tmp->state, &sval))
2034 return NULL;
2035 } END_FOR_EACH_PTR(tmp);
2037 return sm;
2040 static int split_on_bool_sm(struct sm_state *sm, struct expression *expr)
2042 struct returned_state_callback *cb;
2043 struct range_list *ret_rl;
2044 const char *return_ranges;
2045 struct sm_state *tmp;
2046 int ret = 0;
2047 struct state_list *already_handled = NULL;
2049 if (!sm || !sm->merged)
2050 return 0;
2052 if (too_many_possible(sm))
2053 return 0;
2055 FOR_EACH_PTR(sm->possible, tmp) {
2056 if (tmp->merged)
2057 continue;
2058 if (ptr_in_list(tmp, already_handled))
2059 continue;
2060 add_ptr_list(&already_handled, tmp);
2062 ret = 1;
2063 __push_fake_cur_stree();
2065 overwrite_states_using_pool(sm, tmp);
2067 return_ranges = get_return_ranges_str(expr, &ret_rl);
2068 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
2069 return_id++;
2070 FOR_EACH_PTR(returned_state_callbacks, cb) {
2071 cb->callback(return_id, (char *)return_ranges, expr);
2072 } END_FOR_EACH_PTR(cb);
2074 __free_fake_cur_stree();
2075 } END_FOR_EACH_PTR(tmp);
2077 free_slist(&already_handled);
2079 return ret;
2082 static int split_by_bool_param(struct expression *expr)
2084 struct sm_state *start_sm, *sm;
2085 sval_t sval;
2087 start_sm = find_bool_param();
2088 if (!start_sm)
2089 return 0;
2090 sm = get_sm_state(SMATCH_EXTRA, start_sm->name, start_sm->sym);
2091 if (!sm || estate_get_single_value(sm->state, &sval))
2092 return 0;
2094 if (get_db_state_count() * 2 >= 2000)
2095 return 0;
2097 return split_on_bool_sm(sm, expr);
2100 static int split_by_null_nonnull_param(struct expression *expr)
2102 struct symbol *arg;
2103 struct sm_state *sm;
2104 int nr_possible;
2106 /* function must only take one pointer */
2107 if (ptr_list_size((struct ptr_list *)cur_func_sym->ctype.base_type->arguments) != 1)
2108 return 0;
2109 arg = first_ptr_list((struct ptr_list *)cur_func_sym->ctype.base_type->arguments);
2110 if (!arg->ident)
2111 return 0;
2112 if (get_real_base_type(arg)->type != SYM_PTR)
2113 return 0;
2115 if (param_was_set_var_sym(arg->ident->name, arg))
2116 return 0;
2117 sm = get_sm_state(SMATCH_EXTRA, arg->ident->name, arg);
2118 if (!sm)
2119 return 0;
2121 if (!has_separate_zero_null(sm))
2122 return 0;
2124 nr_possible = ptr_list_size((struct ptr_list *)sm->possible);
2125 if (get_db_state_count() * nr_possible >= 2000)
2126 return 0;
2128 return split_on_bool_sm(sm, expr);
2131 struct expression *strip_expr_statement(struct expression *expr)
2133 struct expression *orig = expr;
2134 struct statement *stmt, *last_stmt;
2136 if (!expr)
2137 return NULL;
2138 if (expr->type == EXPR_PREOP && expr->op == '(')
2139 expr = expr->unop;
2140 if (expr->type != EXPR_STATEMENT)
2141 return orig;
2142 stmt = expr->statement;
2143 if (!stmt || stmt->type != STMT_COMPOUND)
2144 return orig;
2146 last_stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
2147 if (!last_stmt || last_stmt->type == STMT_LABEL)
2148 last_stmt = last_stmt->label_statement;
2149 if (!last_stmt || last_stmt->type != STMT_EXPRESSION)
2150 return orig;
2151 return strip_expr(last_stmt->expression);
2154 static bool is_kernel_error_path(struct expression *expr)
2156 struct range_list *rl;
2159 * Splitting up returns requires resources. It also requires resources
2160 * for the caller. It doesn't seem worth it to split anything up.
2162 if (!get_implied_rl(expr, &rl))
2163 return false;
2164 if (rl_type(rl) != &int_ctype)
2165 return false;
2166 if (rl_min(rl).value >= -4095 &&
2167 rl_max(rl).value < 0)
2168 return true;
2169 return false;
2172 static void call_return_state_hooks(struct expression *expr)
2174 struct returned_state_callback *cb;
2175 struct range_list *ret_rl;
2176 const char *return_ranges;
2177 int nr_states;
2178 sval_t sval;
2180 if (__path_is_null())
2181 return;
2183 expr = strip_expr(expr);
2184 expr = strip_expr_statement(expr);
2186 if (is_impossible_path())
2187 goto vanilla;
2189 if (expr && (expr->type == EXPR_COMPARE ||
2190 !get_implied_value(expr, &sval)) &&
2191 (is_condition(expr) || is_boolean(expr))) {
2192 call_return_state_hooks_compare(expr);
2193 return;
2194 } else if (call_return_state_hooks_conditional(expr)) {
2195 return;
2196 } else if (is_kernel_error_path(expr)) {
2197 goto vanilla;
2198 } else if (call_return_state_hooks_split_possible(expr)) {
2199 return;
2200 } else if (split_positive_from_negative(expr)) {
2201 return;
2202 } else if (call_return_state_hooks_split_null_non_null_zero(expr)) {
2203 return;
2204 } else if (call_return_state_hooks_split_success_fail(expr)) {
2205 return;
2206 } else if (splitable_function_call(expr)) {
2207 return;
2208 } else if (split_by_bool_param(expr)) {
2209 } else if (split_by_null_nonnull_param(expr)) {
2210 return;
2213 vanilla:
2214 return_ranges = get_return_ranges_str(expr, &ret_rl);
2215 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
2217 return_id++;
2218 nr_states = get_db_state_count();
2219 if (nr_states >= 10000) {
2220 match_return_info(return_id, (char *)return_ranges, expr);
2221 print_limited_param_set(return_id, (char *)return_ranges, expr);
2222 mark_all_params_untracked(return_id, (char *)return_ranges, expr);
2223 return;
2225 FOR_EACH_PTR(returned_state_callbacks, cb) {
2226 cb->callback(return_id, (char *)return_ranges, expr);
2227 } END_FOR_EACH_PTR(cb);
2230 static void print_returned_struct_members(int return_id, char *return_ranges, struct expression *expr)
2232 struct returned_member_callback *cb;
2233 struct sm_state *sm;
2234 struct symbol *type;
2235 char *name;
2236 char member_name[256];
2237 int len;
2239 type = get_type(expr);
2240 if (!type || type->type != SYM_PTR)
2241 return;
2242 name = expr_to_var(expr);
2243 if (!name)
2244 return;
2246 len = strlen(name);
2247 FOR_EACH_PTR(returned_member_callbacks, cb) {
2248 FOR_EACH_MY_SM(cb->owner, __get_cur_stree(), sm) {
2249 if (sm->name[0] == '*' && strcmp(sm->name + 1, name) == 0) {
2250 strcpy(member_name, "*$");
2251 cb->callback(return_id, return_ranges, expr, member_name, sm->state);
2252 continue;
2254 if (strncmp(sm->name, name, len) != 0)
2255 continue;
2256 if (strncmp(sm->name + len, "->", 2) != 0)
2257 continue;
2258 snprintf(member_name, sizeof(member_name), "$%s", sm->name + len);
2259 cb->callback(return_id, return_ranges, expr, member_name, sm->state);
2260 } END_FOR_EACH_SM(sm);
2261 } END_FOR_EACH_PTR(cb);
2263 free_string(name);
2266 static void print_return_struct_info(int return_id, char *return_ranges,
2267 struct expression *expr,
2268 struct symbol *sym,
2269 struct return_info_callback *cb)
2271 struct sm_state *sm;
2272 const char *printed_name;
2273 int param;
2275 FOR_EACH_MY_SM(cb->owner, __get_cur_stree(), sm) {
2276 if (sm->sym && sm->sym == sym) {
2277 param = -1;
2278 } else {
2279 param = get_param_num_from_sym(sm->sym);
2280 if (param < 0)
2281 continue;
2284 printed_name = get_param_name(sm);
2285 if (!printed_name)
2286 continue;
2288 cb->callback(return_id, return_ranges, expr, param, printed_name, sm);
2289 } END_FOR_EACH_SM(sm);
2292 static void print_return_info(int return_id, char *return_ranges, struct expression *expr)
2294 struct return_info_callback *cb;
2295 struct expression *tmp;
2296 struct symbol *sym;
2298 tmp = get_fake_variable(expr);
2299 if (tmp)
2300 expr = tmp;
2301 sym = expr_to_sym(expr);
2303 FOR_EACH_PTR(return_callbacks, cb) {
2304 print_return_struct_info(return_id, return_ranges, expr, sym, cb);
2305 } END_FOR_EACH_PTR(cb);
2308 static void reset_memdb(struct symbol *sym)
2310 mem_sql(NULL, NULL, "delete from caller_info;");
2311 mem_sql(NULL, NULL, "delete from return_states;");
2312 mem_sql(NULL, NULL, "delete from call_implies;");
2313 mem_sql(NULL, NULL, "delete from return_implies;");
2316 static void match_end_func_info(struct symbol *sym)
2318 if (__path_is_null())
2319 return;
2320 call_return_state_hooks(NULL);
2323 static void match_after_func(struct symbol *sym)
2325 if (!__inline_fn)
2326 reset_memdb(sym);
2329 static void init_memdb(void)
2331 char *err = NULL;
2332 int rc;
2333 const char *schema_files[] = {
2334 "db/db.schema",
2335 "db/caller_info.schema",
2336 "db/common_caller_info.schema",
2337 "db/return_states.schema",
2338 "db/function_type_size.schema",
2339 "db/type_size.schema",
2340 "db/function_type_info.schema",
2341 "db/type_info.schema",
2342 "db/call_implies.schema",
2343 "db/return_implies.schema",
2344 "db/function_ptr.schema",
2345 "db/local_values.schema",
2346 "db/function_type_value.schema",
2347 "db/type_value.schema",
2348 "db/function_type.schema",
2349 "db/data_info.schema",
2350 "db/parameter_name.schema",
2351 "db/constraints.schema",
2352 "db/constraints_required.schema",
2353 "db/fn_ptr_data_link.schema",
2354 "db/fn_data_link.schema",
2355 "db/mtag_about.schema",
2356 "db/mtag_info.schema",
2357 "db/mtag_map.schema",
2358 "db/mtag_data.schema",
2359 "db/mtag_alias.schema",
2361 static char buf[4096];
2362 int fd;
2363 int ret;
2364 int i;
2366 rc = sqlite3_open(":memory:", &mem_db);
2367 if (rc != SQLITE_OK) {
2368 sm_ierror("starting In-Memory database.");
2369 return;
2372 for (i = 0; i < ARRAY_SIZE(schema_files); i++) {
2373 fd = open_schema_file(schema_files[i]);
2374 if (fd < 0)
2375 continue;
2376 ret = read(fd, buf, sizeof(buf));
2377 if (ret < 0) {
2378 sm_ierror("failed to read: %s", schema_files[i]);
2379 continue;
2381 close(fd);
2382 if (ret == sizeof(buf)) {
2383 sm_ierror("Schema file too large: %s (limit %zd bytes)",
2384 schema_files[i], sizeof(buf));
2385 continue;
2387 buf[ret] = '\0';
2388 rc = sqlite3_exec(mem_db, buf, NULL, NULL, &err);
2389 if (rc != SQLITE_OK) {
2390 sm_ierror("SQL error #2: %s", err);
2391 sm_ierror("%s", buf);
2396 static void init_cachedb(void)
2398 char *err = NULL;
2399 int rc;
2400 const char *schema_files[] = {
2401 "db/call_implies.schema",
2402 "db/return_implies.schema",
2403 "db/type_info.schema",
2404 "db/mtag_about.schema",
2405 "db/mtag_data.schema",
2406 "db/mtag_info.schema",
2407 "db/sink_info.schema",
2409 static char buf[4096];
2410 int fd;
2411 int ret;
2412 int i;
2414 rc = sqlite3_open(":memory:", &cache_db);
2415 if (rc != SQLITE_OK) {
2416 sm_ierror("starting In-Memory database.");
2417 return;
2420 for (i = 0; i < ARRAY_SIZE(schema_files); i++) {
2421 fd = open_schema_file(schema_files[i]);
2422 if (fd < 0)
2423 continue;
2424 ret = read(fd, buf, sizeof(buf));
2425 if (ret < 0) {
2426 sm_ierror("failed to read: %s", schema_files[i]);
2427 continue;
2429 close(fd);
2430 if (ret == sizeof(buf)) {
2431 sm_ierror("Schema file too large: %s (limit %zd bytes)",
2432 schema_files[i], sizeof(buf));
2433 continue;
2435 buf[ret] = '\0';
2436 rc = sqlite3_exec(cache_db, buf, NULL, NULL, &err);
2437 if (rc != SQLITE_OK) {
2438 sm_ierror("SQL error #2: %s", err);
2439 sm_ierror("%s", buf);
2444 static int save_cache_data(void *_table, int argc, char **argv, char **azColName)
2446 static char buf[4096];
2447 char tmp[256];
2448 char *p = buf;
2449 char *table = _table;
2450 int i;
2453 p += snprintf(p, 4096 - (p - buf), "insert or ignore into %s values (", table);
2454 for (i = 0; i < argc; i++) {
2455 if (i)
2456 p += snprintf(p, 4096 - (p - buf), ", ");
2457 sqlite3_snprintf(sizeof(tmp), tmp, "%q", escape_newlines(argv[i]));
2458 p += snprintf(p, 4096 - (p - buf), "'%s'", tmp);
2461 p += snprintf(p, 4096 - (p - buf), ");");
2462 if (p - buf > 4096)
2463 return 0;
2465 sm_msg("SQL: %s", buf);
2466 return 0;
2469 static void dump_cache(struct symbol_list *sym_list)
2471 const char *cache_tables[] = {
2472 "type_info", "return_implies", "call_implies", "mtag_data",
2473 "mtag_info", "mtag_about", "sink_info",
2475 char buf[64];
2476 int i;
2478 if (!option_info)
2479 return;
2481 for (i = 0; i < ARRAY_SIZE(cache_tables); i++) {
2482 snprintf(buf, sizeof(buf), "select * from %s;", cache_tables[i]);
2483 cache_sql(&save_cache_data, (char *)cache_tables[i], buf);
2487 void open_smatch_db(char *db_file)
2489 int rc;
2491 if (option_no_db)
2492 return;
2494 use_states = malloc(num_checks + 1);
2495 memset(use_states, 0xff, num_checks + 1);
2497 init_memdb();
2498 init_cachedb();
2500 rc = sqlite3_open_v2(db_file, &smatch_db, SQLITE_OPEN_READONLY, NULL);
2501 if (rc != SQLITE_OK) {
2502 option_no_db = 1;
2503 return;
2505 run_sql(NULL, NULL,
2506 "PRAGMA cache_size = %d;", SQLITE_CACHE_PAGES);
2507 return;
2510 static void register_common_funcs(void)
2512 struct token *token;
2513 char *func;
2514 char filename[256];
2516 if (option_project == PROJ_NONE)
2517 strcpy(filename, "common_functions");
2518 else
2519 snprintf(filename, 256, "%s.common_functions", option_project_str);
2521 token = get_tokens_file(filename);
2522 if (!token)
2523 return;
2524 if (token_type(token) != TOKEN_STREAMBEGIN)
2525 return;
2526 token = token->next;
2527 while (token_type(token) != TOKEN_STREAMEND) {
2528 if (token_type(token) != TOKEN_IDENT)
2529 return;
2530 func = alloc_string(show_ident(token->ident));
2531 add_ptr_list(&common_funcs, func);
2532 token = token->next;
2534 clear_token_alloc();
2537 static char *get_next_string(char **str)
2539 static char string[256];
2540 char *start;
2541 char *p = *str;
2542 int len, i, j;
2544 if (*p == '\0')
2545 return NULL;
2546 start = p;
2548 while (*p != '\0' && *p != '\n') {
2549 if (*p == '\\' && *(p + 1) == ' ') {
2550 p += 2;
2551 continue;
2553 if (*p == ' ')
2554 break;
2555 p++;
2558 len = p - start;
2559 if (len >= sizeof(string)) {
2560 memcpy(string, start, sizeof(string));
2561 string[sizeof(string) - 1] = '\0';
2562 sm_ierror("return_fix: '%s' too long", string);
2563 **str = '\0';
2564 return NULL;
2566 memcpy(string, start, len);
2567 string[len] = '\0';
2568 for (i = 0; i < sizeof(string) - 1; i++) {
2569 if (string[i] == '\\' && string[i + 1] == ' ') {
2570 for (j = i; string[j] != '\0'; j++)
2571 string[j] = string[j + 1];
2574 if (*p != '\0')
2575 p++;
2576 *str = p;
2577 return string;
2580 static void register_return_replacements(void)
2582 char *func, *orig, *new;
2583 char filename[256];
2584 char buf[4096];
2585 int fd, ret, i;
2586 char *p;
2588 snprintf(filename, 256, "db/%s.return_fixes", option_project_str);
2589 fd = open_schema_file(filename);
2590 if (fd < 0)
2591 return;
2592 ret = read(fd, buf, sizeof(buf));
2593 close(fd);
2594 if (ret < 0)
2595 return;
2596 if (ret == sizeof(buf)) {
2597 sm_ierror("file too large: %s (limit %zd bytes)",
2598 filename, sizeof(buf));
2599 return;
2601 buf[ret] = '\0';
2603 p = buf;
2604 while (*p) {
2605 get_next_string(&p);
2606 replace_count++;
2608 if (replace_count == 0 || replace_count % 3 != 0) {
2609 replace_count = 0;
2610 return;
2612 replace_table = malloc(replace_count * sizeof(char *));
2614 p = buf;
2615 i = 0;
2616 while (*p) {
2617 func = alloc_string(get_next_string(&p));
2618 orig = alloc_string(get_next_string(&p));
2619 new = alloc_string(get_next_string(&p));
2621 replace_table[i++] = func;
2622 replace_table[i++] = orig;
2623 replace_table[i++] = new;
2627 void register_definition_db_callbacks(int id)
2629 my_id = id;
2631 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
2632 add_hook(&match_call_info_new, FUNCTION_CALL_HOOK);
2633 add_split_return_callback(match_return_info);
2634 add_split_return_callback(print_returned_struct_members);
2635 add_split_return_callback(print_return_info);
2636 add_hook(&call_return_state_hooks, RETURN_HOOK);
2637 add_hook(&match_end_func_info, END_FUNC_HOOK);
2638 add_hook(&match_after_func, AFTER_FUNC_HOOK);
2640 add_hook(&match_data_from_db, FUNC_DEF_HOOK);
2641 add_hook(&match_call_implies, FUNC_DEF_HOOK);
2642 add_hook(&match_return_implies, CALL_HOOK_AFTER_INLINE);
2644 register_common_funcs();
2645 register_return_replacements();
2647 add_hook(&dump_cache, END_FILE_HOOK);
2650 void register_db_call_marker(int id)
2652 add_hook(&match_call_marker, FUNCTION_CALL_HOOK);
2655 char *get_data_info_name(struct expression *expr)
2657 struct symbol *sym;
2658 char *name;
2659 char buf[256];
2660 char *ret = NULL;
2662 expr = strip_expr(expr);
2663 name = get_member_name(expr);
2664 if (name)
2665 return name;
2666 name = expr_to_var_sym(expr, &sym);
2667 if (!name || !sym)
2668 goto free;
2669 if (!(sym->ctype.modifiers & MOD_TOPLEVEL))
2670 goto free;
2671 if (sym->ctype.modifiers & MOD_STATIC)
2672 snprintf(buf, sizeof(buf), "static %s", name);
2673 else
2674 snprintf(buf, sizeof(buf), "global %s", name);
2675 ret = alloc_sname(buf);
2676 free:
2677 free_string(name);
2678 return ret;