33
34 static void call_return_state_hooks(struct expression *expr);
35
36 #define SQLITE_CACHE_PAGES 1000
37
38 struct def_callback {
39 int hook_type;
40 void (*callback)(const char *name, struct symbol *sym, char *key, char *value);
41 };
42 ALLOCATOR(def_callback, "definition db hook callbacks");
43 DECLARE_PTR_LIST(callback_list, struct def_callback);
44 static struct callback_list *select_caller_info_callbacks;
45
46 struct member_info_callback {
47 int owner;
48 void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm);
49 };
50 ALLOCATOR(member_info_callback, "caller_info callbacks");
51 DECLARE_PTR_LIST(member_info_cb_list, struct member_info_callback);
52 static struct member_info_cb_list *member_callbacks;
53
54 struct returned_state_callback {
55 void (*callback)(int return_id, char *return_ranges, struct expression *return_expr);
56 };
57 ALLOCATOR(returned_state_callback, "returned state callbacks");
58 DECLARE_PTR_LIST(returned_state_cb_list, struct returned_state_callback);
59 static struct returned_state_cb_list *returned_state_callbacks;
60
61 struct returned_member_callback {
62 int owner;
63 void (*callback)(int return_id, char *return_ranges, struct expression *expr, char *printed_name, struct smatch_state *state);
64 };
65 ALLOCATOR(returned_member_callback, "returned member callbacks");
66 DECLARE_PTR_LIST(returned_member_cb_list, struct returned_member_callback);
67 static struct returned_member_cb_list *returned_member_callbacks;
68
69 struct db_implies_callback {
70 int type;
71 void (*callback)(struct expression *call, struct expression *arg, char *key, char *value);
72 };
161 static char *use_states;
162 static int get_db_state_count(void)
163 {
164 struct sm_state *sm;
165 int count = 0;
166
167 FOR_EACH_SM(__get_cur_stree(), sm) {
168 if (sm->owner == USHRT_MAX)
169 continue;
170 if (use_states[sm->owner])
171 count++;
172 } END_FOR_EACH_SM(sm);
173 return count;
174 }
175
176 void db_ignore_states(int id)
177 {
178 use_states[id] = 0;
179 }
180
181 void sql_insert_return_states(int return_id, const char *return_ranges,
182 int type, int param, const char *key, const char *value)
183 {
184 if (key && strlen(key) >= 80)
185 return;
186 return_ranges = replace_return_ranges(return_ranges);
187 sql_insert(return_states, "'%s', '%s', %lu, %d, '%s', %d, %d, %d, '%s', '%s'",
188 get_base_file(), get_function(), (unsigned long)__inline_fn,
189 return_id, return_ranges, fn_static(), type, param, key, value);
190 }
191
192 static struct string_list *common_funcs;
193 static int is_common_function(const char *fn)
194 {
195 char *tmp;
196
197 if (!fn)
198 return 0;
199
200 if (strncmp(fn, "__builtin_", 10) == 0)
201 return 1;
202
203 FOR_EACH_PTR(common_funcs, tmp) {
204 if (strcmp(tmp, fn) == 0)
205 return 1;
206 } END_FOR_EACH_PTR(tmp);
207
208 return 0;
209 }
355
356 void sql_insert_fn_ptr_data_link(const char *ptr, const char *data)
357 {
358 sql_insert_or_ignore(fn_ptr_data_link, "'%s', '%s'", ptr, data);
359 }
360
361 void sql_insert_fn_data_link(struct expression *fn, int type, int param, const char *key, const char *value)
362 {
363 if (fn->type != EXPR_SYMBOL || !fn->symbol->ident)
364 return;
365
366 sql_insert(fn_data_link, "'%s', '%s', %d, %d, %d, '%s', '%s'",
367 (fn->symbol->ctype.modifiers & MOD_STATIC) ? get_base_file() : "extern",
368 fn->symbol->ident->name,
369 !!(fn->symbol->ctype.modifiers & MOD_STATIC),
370 type, param, key, value);
371 }
372
373 void sql_insert_mtag_about(mtag_t tag, const char *left_name, const char *right_name)
374 {
375 sql_insert(mtag_about, "%lld, '%s', '%s', %d, '%s', '%s'",
376 tag, get_filename(), get_function(), get_lineno(), left_name, right_name);
377 }
378
379 void sql_insert_mtag_map(mtag_t tag, int offset, mtag_t container)
380 {
381 sql_insert(mtag_map, "%lld, %d, %lld", tag, offset, container);
382 }
383
384 void sql_insert_mtag_alias(mtag_t orig, mtag_t alias)
385 {
386 sql_insert(mtag_alias, "%lld, %lld", orig, alias);
387 }
388
389 static int save_mtag(void *_tag, int argc, char **argv, char **azColName)
390 {
391 mtag_t *saved_tag = _tag;
392 mtag_t new_tag;
393
394 new_tag = strtoll(argv[0], NULL, 10);
395
396 if (!*saved_tag)
397 *saved_tag = new_tag;
398 else if (*saved_tag != new_tag)
399 *saved_tag = -1ULL;
400
401 return 0;
402 }
403
404 int mtag_map_select_container(mtag_t tag, int offset, mtag_t *container)
405 {
406 mtag_t tmp = 0;
407
408 run_sql(save_mtag, &tmp,
409 "select container from mtag_map where tag = %lld and offset = %d;",
410 tag, offset);
411
412 if (tmp == 0 || tmp == -1ULL)
413 return 0;
414 *container = tmp;
415 return 1;
416 }
417
418 int mtag_map_select_tag(mtag_t container, int offset, mtag_t *tag)
419 {
420 mtag_t tmp = 0;
421
422 run_sql(save_mtag, &tmp,
423 "select tag from mtag_map where container = %lld and offset = %d;",
424 container, offset);
425
426 if (tmp == 0 || tmp == -1ULL)
427 return 0;
428 *tag = tmp;
429 return 1;
430 }
431
432 char *get_static_filter(struct symbol *sym)
433 {
434 static char sql_filter[1024];
435
436 /* This can only happen on buggy code. Return invalid SQL. */
437 if (!sym) {
438 sql_filter[0] = '\0';
439 return sql_filter;
440 }
441
442 if (sym->ctype.modifiers & MOD_STATIC) {
443 snprintf(sql_filter, sizeof(sql_filter),
605
606 def_callback->hook_type = type;
607 def_callback->callback = callback;
608 add_ptr_list(&select_caller_info_callbacks, def_callback);
609 }
610
611 /*
612 * These call backs are used when the --info option is turned on to print struct
613 * member information. For example foo->bar could have a state in
614 * smatch_extra.c and also check_user.c.
615 */
616 void add_member_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
617 {
618 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
619
620 member_callback->owner = owner;
621 member_callback->callback = callback;
622 add_ptr_list(&member_callbacks, member_callback);
623 }
624
625 void add_split_return_callback(void (*fn)(int return_id, char *return_ranges, struct expression *returned_expr))
626 {
627 struct returned_state_callback *callback = __alloc_returned_state_callback(0);
628
629 callback->callback = fn;
630 add_ptr_list(&returned_state_callbacks, callback);
631 }
632
633 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))
634 {
635 struct returned_member_callback *member_callback = __alloc_returned_member_callback(0);
636
637 member_callback->owner = owner;
638 member_callback->callback = callback;
639 add_ptr_list(&returned_member_callbacks, member_callback);
640 }
641
642 void select_call_implies_hook(int type, void (*callback)(struct expression *call, struct expression *arg, char *key, char *value))
643 {
644 struct db_implies_callback *cb = __alloc_db_implies_callback(0);
834 if (sm_name[len] == '\0') {
835 snprintf(buf, sizeof(buf), "%s%s$",
836 add_star ? "*" : "", is_address ? "*" : "");
837 } else {
838 if (sm_name[len] != '.' && sm_name[len] != '-')
839 goto free;
840 if (sm_name[len] == '-')
841 len++;
842 // FIXME does is_address really imply that sm_name[len] == '-'
843 snprintf(buf, sizeof(buf), "%s$->%s", add_star ? "*" : "",
844 sm_name + len);
845 }
846
847 ret = alloc_sname(buf);
848 free:
849 free_string(name);
850 return ret;
851 }
852
853 static void print_struct_members(struct expression *call, struct expression *expr, int param, struct stree *stree,
854 void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
855 {
856 struct sm_state *sm;
857 const char *sm_name;
858 char *name;
859 struct symbol *sym;
860 int len;
861 char printed_name[256];
862 int is_address = 0;
863 bool add_star;
864 struct symbol *type;
865
866 expr = strip_expr(expr);
867 if (!expr)
868 return;
869 type = get_type(expr);
870 if (type && type_bits(type) < type_bits(&ulong_ctype))
871 return;
872
873 if (expr->type == EXPR_PREOP && expr->op == '&') {
874 expr = strip_expr(expr->unop);
875 is_address = 1;
876 }
877
878 name = expr_to_var_sym(expr, &sym);
879 if (!name || !sym)
880 goto free;
881
882 len = strlen(name);
883 FOR_EACH_SM(stree, sm) {
884 if (sm->sym != sym)
885 continue;
886 sm_name = sm->name;
887 add_star = false;
888 if (sm_name[0] == '*') {
889 add_star = true;
890 sm_name++;
891 }
892 // FIXME: simplify?
893 if (!add_star && strcmp(name, sm_name) == 0) {
894 if (is_address)
895 snprintf(printed_name, sizeof(printed_name), "*$");
896 else /* these are already handled. fixme: handle them here */
897 continue;
898 } else if (add_star && strcmp(name, sm_name) == 0) {
899 snprintf(printed_name, sizeof(printed_name), "%s*$",
900 is_address ? "*" : "");
901 } else if (strncmp(name, sm_name, len) == 0) {
902 if (sm_name[len] != '.' && sm_name[len] != '-')
903 continue;
904 if (is_address)
905 snprintf(printed_name, sizeof(printed_name),
906 "%s$->%s", add_star ? "*" : "",
907 sm_name + len + 1);
908 else
909 snprintf(printed_name, sizeof(printed_name),
910 "%s$%s", add_star ? "*" : "",
911 sm_name + len);
912 } else {
913 continue;
914 }
915 if (is_recursive_member(printed_name))
916 continue;
917 callback(call, param, printed_name, sm);
918 } END_FOR_EACH_SM(sm);
919 free:
920 free_string(name);
921 }
922
923 static void match_call_info(struct expression *call)
924 {
925 struct member_info_callback *cb;
926 struct expression *arg;
927 struct stree *stree;
928 char *name;
929 int i;
930
931 name = get_fnptr_name(call->fn);
932 if (!name)
933 return;
934
935 FOR_EACH_PTR(member_callbacks, cb) {
936 stree = get_all_states_stree(cb->owner);
937 i = 0;
938 FOR_EACH_PTR(call->args, arg) {
939 print_struct_members(call, arg, i, stree, cb->callback);
940 i++;
941 } END_FOR_EACH_PTR(arg);
942 free_stree(&stree);
943 } END_FOR_EACH_PTR(cb);
944
945 free_string(name);
946 }
947
948 static int get_param(int param, char **name, struct symbol **sym)
949 {
950 struct symbol *arg;
951 int i;
952
953 i = 0;
954 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
955 /*
956 * this is a temporary hack to work around a bug (I think in sparse?)
957 * 2.6.37-rc1:fs/reiserfs/journal.o
958 * If there is a function definition without parameter name found
959 * after a function implementation then it causes a crash.
960 * int foo() {}
961 * int bar(char *);
962 */
963 if (arg->ident->name < (char *)100)
964 continue;
965 if (i == param) {
966 *name = arg->ident->name;
967 *sym = arg;
1089 sql_filter);
1090
1091 after = ptr_list_size((struct ptr_list *)ptr_names);
1092 if (before == after)
1093 return;
1094
1095 while ((name = get_next_ptr_name()))
1096 get_ptr_names(NULL, name);
1097 }
1098
1099 static void match_data_from_db(struct symbol *sym)
1100 {
1101 struct select_caller_info_data data = { .prev_func_id = -1 };
1102 struct sm_state *sm;
1103 struct stree *stree;
1104 struct timeval end_time;
1105
1106 if (!sym || !sym->ident)
1107 return;
1108
1109 gettimeofday(&data.start_time, NULL);
1110
1111 __push_fake_cur_stree();
1112 __unnullify_path();
1113
1114 if (!__inline_fn) {
1115 char *ptr;
1116
1117 if (sym->ctype.modifiers & MOD_STATIC)
1118 get_ptr_names(get_base_file(), sym->ident->name);
1119 else
1120 get_ptr_names(NULL, sym->ident->name);
1121
1122 if (ptr_list_size((struct ptr_list *)ptr_names) > 20) {
1123 __free_ptr_list((struct ptr_list **)&ptr_names);
1124 __free_ptr_list((struct ptr_list **)&ptr_names_done);
1125 __free_fake_cur_stree();
1126 return;
1127 }
1128
1552 }
1553 }
1554
1555 return_id++;
1556 FOR_EACH_PTR(returned_state_callbacks, cb) {
1557 cb->callback(return_id, return_ranges, expr);
1558 } END_FOR_EACH_PTR(cb);
1559
1560 __free_fake_cur_stree();
1561 } END_FOR_EACH_PTR(tmp);
1562
1563 free_slist(&already_handled);
1564
1565 return ret;
1566 }
1567
1568 static int call_return_state_hooks_split_possible(struct expression *expr)
1569 {
1570 struct sm_state *sm;
1571
1572 if (!expr || expr_equal_to_param(expr, -1))
1573 return 0;
1574
1575 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
1576 return split_possible_helper(sm, expr);
1577 }
1578
1579 static bool has_possible_negative(struct sm_state *sm)
1580 {
1581 struct sm_state *tmp;
1582
1583 if (!type_signed(estate_type(sm->state)))
1584 return false;
1585
1586 FOR_EACH_PTR(sm->possible, tmp) {
1587 if (!estate_rl(tmp->state))
1588 continue;
1589 if (sval_is_negative(estate_min(tmp->state)) &&
1590 sval_is_negative(estate_max(tmp->state)))
1591 return true;
1592 } END_FOR_EACH_PTR(tmp);
1690 struct sm_state *sm;
1691 struct smatch_state *state;
1692 int nr_states;
1693 int final_pass_orig = final_pass;
1694
1695 if (!expr || expr_equal_to_param(expr, -1))
1696 return 0;
1697 if (expr->type == EXPR_CALL)
1698 return 0;
1699
1700 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
1701 if (!sm)
1702 return 0;
1703 if (ptr_list_size((struct ptr_list *)sm->possible) == 1)
1704 return 0;
1705 state = sm->state;
1706 if (!estate_rl(state))
1707 return 0;
1708 if (estate_min(state).value == 0 && estate_max(state).value == 0)
1709 return 0;
1710 if (!has_separate_zero_null(sm))
1711 return 0;
1712
1713 nr_states = get_db_state_count();
1714 if (option_info && nr_states >= 1500)
1715 return 0;
1716
1717 rl = estate_rl(state);
1718
1719 __push_fake_cur_stree();
1720
1721 final_pass = 0;
1722 __split_whole_condition(expr);
1723 final_pass = final_pass_orig;
1724
1725 nonnull_rl = rl_filter(rl, rl_zero());
1726 return_ranges = show_rl(nonnull_rl);
1727 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(nonnull_rl));
1728
1729 return_id++;
2003 struct statement *stmt, *last_stmt;
2004
2005 if (!expr)
2006 return NULL;
2007 if (expr->type == EXPR_PREOP && expr->op == '(')
2008 expr = expr->unop;
2009 if (expr->type != EXPR_STATEMENT)
2010 return orig;
2011 stmt = expr->statement;
2012 if (!stmt || stmt->type != STMT_COMPOUND)
2013 return orig;
2014
2015 last_stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
2016 if (!last_stmt || last_stmt->type == STMT_LABEL)
2017 last_stmt = last_stmt->label_statement;
2018 if (!last_stmt || last_stmt->type != STMT_EXPRESSION)
2019 return orig;
2020 return strip_expr(last_stmt->expression);
2021 }
2022
2023 static void call_return_state_hooks(struct expression *expr)
2024 {
2025 struct returned_state_callback *cb;
2026 struct range_list *ret_rl;
2027 const char *return_ranges;
2028 int nr_states;
2029 sval_t sval;
2030
2031 if (__path_is_null())
2032 return;
2033
2034 expr = strip_expr(expr);
2035 expr = strip_expr_statement(expr);
2036
2037 if (is_impossible_path())
2038 goto vanilla;
2039
2040 if (expr && (expr->type == EXPR_COMPARE ||
2041 !get_implied_value(expr, &sval)) &&
2042 (is_condition(expr) || is_boolean(expr))) {
2043 call_return_state_hooks_compare(expr);
2044 return;
2045 } else if (call_return_state_hooks_conditional(expr)) {
2046 return;
2047 } else if (call_return_state_hooks_split_possible(expr)) {
2048 return;
2049 } else if (split_positive_from_negative(expr)) {
2050 return;
2051 } else if (call_return_state_hooks_split_null_non_null_zero(expr)) {
2052 return;
2053 } else if (call_return_state_hooks_split_success_fail(expr)) {
2054 return;
2055 } else if (splitable_function_call(expr)) {
2056 return;
2057 } else if (split_by_bool_param(expr)) {
2058 } else if (split_by_null_nonnull_param(expr)) {
2059 return;
2060 }
2061
2062 vanilla:
2063 return_ranges = get_return_ranges_str(expr, &ret_rl);
2064 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
2065
2066 return_id++;
2148 "db/common_caller_info.schema",
2149 "db/return_states.schema",
2150 "db/function_type_size.schema",
2151 "db/type_size.schema",
2152 "db/function_type_info.schema",
2153 "db/type_info.schema",
2154 "db/call_implies.schema",
2155 "db/return_implies.schema",
2156 "db/function_ptr.schema",
2157 "db/local_values.schema",
2158 "db/function_type_value.schema",
2159 "db/type_value.schema",
2160 "db/function_type.schema",
2161 "db/data_info.schema",
2162 "db/parameter_name.schema",
2163 "db/constraints.schema",
2164 "db/constraints_required.schema",
2165 "db/fn_ptr_data_link.schema",
2166 "db/fn_data_link.schema",
2167 "db/mtag_about.schema",
2168 "db/mtag_map.schema",
2169 "db/mtag_data.schema",
2170 "db/mtag_alias.schema",
2171 };
2172 static char buf[4096];
2173 int fd;
2174 int ret;
2175 int i;
2176
2177 rc = sqlite3_open(":memory:", &mem_db);
2178 if (rc != SQLITE_OK) {
2179 sm_ierror("starting In-Memory database.");
2180 return;
2181 }
2182
2183 for (i = 0; i < ARRAY_SIZE(schema_files); i++) {
2184 fd = open_schema_file(schema_files[i]);
2185 if (fd < 0)
2186 continue;
2187 ret = read(fd, buf, sizeof(buf));
2195 schema_files[i], sizeof(buf));
2196 continue;
2197 }
2198 buf[ret] = '\0';
2199 rc = sqlite3_exec(mem_db, buf, NULL, NULL, &err);
2200 if (rc != SQLITE_OK) {
2201 sm_ierror("SQL error #2: %s", err);
2202 sm_ierror("%s", buf);
2203 }
2204 }
2205 }
2206
2207 static void init_cachedb(void)
2208 {
2209 char *err = NULL;
2210 int rc;
2211 const char *schema_files[] = {
2212 "db/call_implies.schema",
2213 "db/return_implies.schema",
2214 "db/type_info.schema",
2215 "db/mtag_data.schema",
2216 "db/sink_info.schema",
2217 };
2218 static char buf[4096];
2219 int fd;
2220 int ret;
2221 int i;
2222
2223 rc = sqlite3_open(":memory:", &cache_db);
2224 if (rc != SQLITE_OK) {
2225 sm_ierror("starting In-Memory database.");
2226 return;
2227 }
2228
2229 for (i = 0; i < ARRAY_SIZE(schema_files); i++) {
2230 fd = open_schema_file(schema_files[i]);
2231 if (fd < 0)
2232 continue;
2233 ret = read(fd, buf, sizeof(buf));
2234 if (ret < 0) {
2235 sm_ierror("failed to read: %s", schema_files[i]);
2260
2261
2262 p += snprintf(p, 4096 - (p - buf), "insert or ignore into %s values (", table);
2263 for (i = 0; i < argc; i++) {
2264 if (i)
2265 p += snprintf(p, 4096 - (p - buf), ", ");
2266 sqlite3_snprintf(sizeof(tmp), tmp, "%q", escape_newlines(argv[i]));
2267 p += snprintf(p, 4096 - (p - buf), "'%s'", tmp);
2268
2269 }
2270 p += snprintf(p, 4096 - (p - buf), ");");
2271 if (p - buf > 4096)
2272 return 0;
2273
2274 sm_msg("SQL: %s", buf);
2275 return 0;
2276 }
2277
2278 static void dump_cache(struct symbol_list *sym_list)
2279 {
2280 if (!option_info)
2281 return;
2282 cache_sql(&save_cache_data, (char *)"type_info", "select * from type_info;");
2283 cache_sql(&save_cache_data, (char *)"return_implies", "select * from return_implies;");
2284 cache_sql(&save_cache_data, (char *)"call_implies", "select * from call_implies;");
2285 cache_sql(&save_cache_data, (char *)"mtag_data", "select * from mtag_data;");
2286 cache_sql(&save_cache_data, (char *)"sink_info", "select * from sink_info;");
2287 }
2288
2289 void open_smatch_db(char *db_file)
2290 {
2291 int rc;
2292
2293 if (option_no_db)
2294 return;
2295
2296 use_states = malloc(num_checks + 1);
2297 memset(use_states, 0xff, num_checks + 1);
2298
2299 init_memdb();
2300 init_cachedb();
2301
2302 rc = sqlite3_open_v2(db_file, &smatch_db, SQLITE_OPEN_READONLY, NULL);
2303 if (rc != SQLITE_OK) {
2304 option_no_db = 1;
2305 return;
2306 }
2412 return;
2413 }
2414 replace_table = malloc(replace_count * sizeof(char *));
2415
2416 p = buf;
2417 i = 0;
2418 while (*p) {
2419 func = alloc_string(get_next_string(&p));
2420 orig = alloc_string(get_next_string(&p));
2421 new = alloc_string(get_next_string(&p));
2422
2423 replace_table[i++] = func;
2424 replace_table[i++] = orig;
2425 replace_table[i++] = new;
2426 }
2427 }
2428
2429 void register_definition_db_callbacks(int id)
2430 {
2431 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
2432 add_split_return_callback(match_return_info);
2433 add_split_return_callback(print_returned_struct_members);
2434 add_hook(&call_return_state_hooks, RETURN_HOOK);
2435 add_hook(&match_end_func_info, END_FUNC_HOOK);
2436 add_hook(&match_after_func, AFTER_FUNC_HOOK);
2437
2438 add_hook(&match_data_from_db, FUNC_DEF_HOOK);
2439 add_hook(&match_call_implies, FUNC_DEF_HOOK);
2440 add_hook(&match_return_implies, CALL_HOOK_AFTER_INLINE);
2441
2442 register_common_funcs();
2443 register_return_replacements();
2444
2445 add_hook(&dump_cache, END_FILE_HOOK);
2446 }
2447
2448 void register_db_call_marker(int id)
2449 {
2450 add_hook(&match_call_marker, FUNCTION_CALL_HOOK);
2451 }
2476 return name;
2477 snprintf(member_name, sizeof(member_name), "%s%s%s", star, name, key + 1);
2478 free_string(name);
2479 return alloc_string(member_name);
2480 }
2481
2482 while (expr->type == EXPR_ASSIGNMENT)
2483 expr = strip_expr(expr->right);
2484 if (expr->type != EXPR_CALL)
2485 return NULL;
2486
2487 arg = get_argument_from_call_expr(expr->args, param);
2488 if (!arg)
2489 return NULL;
2490
2491 return get_variable_from_key(arg, key, sym);
2492 }
2493
2494 char *get_variable_from_key(struct expression *arg, const char *key, struct symbol **sym)
2495 {
2496 char buf[256];
2497 char *tmp;
2498 int star_cnt = 0;
2499
2500 if (!arg)
2501 return NULL;
2502
2503 arg = strip_expr(arg);
2504
2505 if (strcmp(key, "$") == 0)
2506 return expr_to_var_sym(arg, sym);
2507
2508 if (strcmp(key, "*$") == 0) {
2509 if (arg->type == EXPR_PREOP && arg->op == '&') {
2510 arg = strip_expr(arg->unop);
2511 return expr_to_var_sym(arg, sym);
2512 } else {
2513 tmp = expr_to_var_sym(arg, sym);
2514 if (!tmp)
2515 return NULL;
2516 snprintf(buf, sizeof(buf), "*%s", tmp);
2517 free_string(tmp);
2518 return alloc_string(buf);
2519 }
2520 }
2521
2522 while (key[0] == '*') {
2523 star_cnt++;
2524 key++;
2525 }
2526
2527 if (arg->type == EXPR_PREOP && arg->op == '&' && star_cnt) {
2528 arg = strip_expr(arg->unop);
2529 star_cnt--;
2530 }
2531
2532 if (arg->type == EXPR_PREOP && arg->op == '&') {
2533 arg = strip_expr(arg->unop);
2534 tmp = expr_to_var_sym(arg, sym);
2535 if (!tmp)
2536 return NULL;
2537 snprintf(buf, sizeof(buf), "%.*s%s.%s",
2538 star_cnt, "**********", tmp, key + 3);
2539 return alloc_string(buf);
2540 }
2541
2542 tmp = expr_to_var_sym(arg, sym);
2543 if (!tmp)
2544 return NULL;
2545 snprintf(buf, sizeof(buf), "%.*s%s%s", star_cnt, "**********", tmp, key + 1);
2546 free_string(tmp);
2547 return alloc_string(buf);
2556 return get_variable_from_key(arg, key, sym);
2557 }
2558
2559 const char *state_name_to_param_name(const char *state_name, const char *param_name)
2560 {
2561 int star_cnt = 0;
2562 int name_len;
2563 char buf[256];
2564
2565 name_len = strlen(param_name);
2566
2567 while (state_name[0] == '*') {
2568 star_cnt++;
2569 state_name++;
2570 }
2571
2572 /* ten out of ten stars! */
2573 if (star_cnt > 10)
2574 return NULL;
2575
2576 if (strcmp(state_name, param_name) == 0) {
2577 snprintf(buf, sizeof(buf), "%.*s$", star_cnt, "**********");
2578 return alloc_sname(buf);
2579 }
2580
2581 if (state_name[name_len] == '-' && /* check for '-' from "->" */
2582 strncmp(state_name, param_name, name_len) == 0) {
2583 snprintf(buf, sizeof(buf), "%.*s$%s", star_cnt, "**********", state_name + name_len);
2584 return alloc_sname(buf);
2585 }
2586 return NULL;
2587 }
2588
2589 const char *get_param_name_var_sym(const char *name, struct symbol *sym)
2590 {
2591 if (!sym || !sym->ident)
2592 return NULL;
2593
2594 return state_name_to_param_name(name, sym->ident->name);
2595 }
|
33
34 static void call_return_state_hooks(struct expression *expr);
35
36 #define SQLITE_CACHE_PAGES 1000
37
38 struct def_callback {
39 int hook_type;
40 void (*callback)(const char *name, struct symbol *sym, char *key, char *value);
41 };
42 ALLOCATOR(def_callback, "definition db hook callbacks");
43 DECLARE_PTR_LIST(callback_list, struct def_callback);
44 static struct callback_list *select_caller_info_callbacks;
45
46 struct member_info_callback {
47 int owner;
48 void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm);
49 };
50 ALLOCATOR(member_info_callback, "caller_info callbacks");
51 DECLARE_PTR_LIST(member_info_cb_list, struct member_info_callback);
52 static struct member_info_cb_list *member_callbacks;
53 static struct member_info_cb_list *member_callbacks_new;
54
55 struct returned_state_callback {
56 void (*callback)(int return_id, char *return_ranges, struct expression *return_expr);
57 };
58 ALLOCATOR(returned_state_callback, "returned state callbacks");
59 DECLARE_PTR_LIST(returned_state_cb_list, struct returned_state_callback);
60 static struct returned_state_cb_list *returned_state_callbacks;
61
62 struct returned_member_callback {
63 int owner;
64 void (*callback)(int return_id, char *return_ranges, struct expression *expr, char *printed_name, struct smatch_state *state);
65 };
66 ALLOCATOR(returned_member_callback, "returned member callbacks");
67 DECLARE_PTR_LIST(returned_member_cb_list, struct returned_member_callback);
68 static struct returned_member_cb_list *returned_member_callbacks;
69
70 struct db_implies_callback {
71 int type;
72 void (*callback)(struct expression *call, struct expression *arg, char *key, char *value);
73 };
162 static char *use_states;
163 static int get_db_state_count(void)
164 {
165 struct sm_state *sm;
166 int count = 0;
167
168 FOR_EACH_SM(__get_cur_stree(), sm) {
169 if (sm->owner == USHRT_MAX)
170 continue;
171 if (use_states[sm->owner])
172 count++;
173 } END_FOR_EACH_SM(sm);
174 return count;
175 }
176
177 void db_ignore_states(int id)
178 {
179 use_states[id] = 0;
180 }
181
182 unsigned long long __fn_mtag;
183 static void set_fn_mtag(struct symbol *sym)
184 {
185 char buf[128];
186
187 if (cur_func_sym->ctype.modifiers & MOD_STATIC)
188 snprintf(buf, sizeof(buf), "%s %s", get_base_file(), get_function());
189 else
190 snprintf(buf, sizeof(buf), "extern %s", get_function());
191
192 __fn_mtag = str_to_mtag(buf);
193 }
194
195 void sql_insert_return_states(int return_id, const char *return_ranges,
196 int type, int param, const char *key, const char *value)
197 {
198 unsigned long long id;
199
200
201 if (key && strlen(key) >= 80)
202 return;
203 if (__inline_fn)
204 id = (unsigned long)__inline_fn;
205 else
206 id = __fn_mtag;
207
208 return_ranges = replace_return_ranges(return_ranges);
209 sql_insert(return_states, "'%s', '%s', %llu, %d, '%s', %d, %d, %d, '%s', '%s'",
210 get_base_file(), get_function(), id, return_id,
211 return_ranges, fn_static(), type, param, key, value);
212 }
213
214 static struct string_list *common_funcs;
215 static int is_common_function(const char *fn)
216 {
217 char *tmp;
218
219 if (!fn)
220 return 0;
221
222 if (strncmp(fn, "__builtin_", 10) == 0)
223 return 1;
224
225 FOR_EACH_PTR(common_funcs, tmp) {
226 if (strcmp(tmp, fn) == 0)
227 return 1;
228 } END_FOR_EACH_PTR(tmp);
229
230 return 0;
231 }
377
378 void sql_insert_fn_ptr_data_link(const char *ptr, const char *data)
379 {
380 sql_insert_or_ignore(fn_ptr_data_link, "'%s', '%s'", ptr, data);
381 }
382
383 void sql_insert_fn_data_link(struct expression *fn, int type, int param, const char *key, const char *value)
384 {
385 if (fn->type != EXPR_SYMBOL || !fn->symbol->ident)
386 return;
387
388 sql_insert(fn_data_link, "'%s', '%s', %d, %d, %d, '%s', '%s'",
389 (fn->symbol->ctype.modifiers & MOD_STATIC) ? get_base_file() : "extern",
390 fn->symbol->ident->name,
391 !!(fn->symbol->ctype.modifiers & MOD_STATIC),
392 type, param, key, value);
393 }
394
395 void sql_insert_mtag_about(mtag_t tag, const char *left_name, const char *right_name)
396 {
397 sql_insert_cache(mtag_about, "%lld, '%s', '%s', %d, '%s', '%s'",
398 tag, get_filename(), get_function(), get_lineno(),
399 left_name, right_name);
400 }
401
402 void sql_insert_mtag_info(mtag_t tag, int type, const char *value)
403 {
404 sql_insert_cache(mtag_info, "'%s', %lld, %d, '%s'", get_filename(), tag, type, value);
405 }
406
407 void sql_insert_mtag_map(mtag_t container, int container_offset, mtag_t tag, int tag_offset)
408 {
409 sql_insert(mtag_map, "%lld, %d, %lld, %d", container, container_offset, tag, tag_offset);
410 }
411
412 void sql_insert_mtag_alias(mtag_t orig, mtag_t alias)
413 {
414 sql_insert(mtag_alias, "%lld, %lld", orig, alias);
415 }
416
417 static int save_mtag(void *_tag, int argc, char **argv, char **azColName)
418 {
419 mtag_t *saved_tag = _tag;
420 mtag_t new_tag;
421
422 new_tag = strtoll(argv[0], NULL, 10);
423
424 if (!*saved_tag)
425 *saved_tag = new_tag;
426 else if (*saved_tag != new_tag)
427 *saved_tag = -1ULL;
428
429 return 0;
430 }
431
432 int mtag_map_select_container(mtag_t tag, int container_offset, mtag_t *container)
433 {
434 mtag_t tmp = 0;
435
436 run_sql(save_mtag, &tmp,
437 "select container from mtag_map where tag = %lld and container_offset = %d and tag_offset = 0;",
438 tag, container_offset);
439
440 if (tmp == 0 || tmp == -1ULL)
441 return 0;
442 *container = tmp;
443 return 1;
444 }
445
446 int mtag_map_select_tag(mtag_t container, int offset, mtag_t *tag)
447 {
448 mtag_t tmp = 0;
449
450 run_sql(save_mtag, &tmp,
451 "select tag from mtag_map where container = %lld and container_offset = %d;",
452 container, offset);
453
454 if (tmp == 0 || tmp == -1ULL)
455 return 0;
456 *tag = tmp;
457 return 1;
458 }
459
460 char *get_static_filter(struct symbol *sym)
461 {
462 static char sql_filter[1024];
463
464 /* This can only happen on buggy code. Return invalid SQL. */
465 if (!sym) {
466 sql_filter[0] = '\0';
467 return sql_filter;
468 }
469
470 if (sym->ctype.modifiers & MOD_STATIC) {
471 snprintf(sql_filter, sizeof(sql_filter),
633
634 def_callback->hook_type = type;
635 def_callback->callback = callback;
636 add_ptr_list(&select_caller_info_callbacks, def_callback);
637 }
638
639 /*
640 * These call backs are used when the --info option is turned on to print struct
641 * member information. For example foo->bar could have a state in
642 * smatch_extra.c and also check_user.c.
643 */
644 void add_member_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
645 {
646 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
647
648 member_callback->owner = owner;
649 member_callback->callback = callback;
650 add_ptr_list(&member_callbacks, member_callback);
651 }
652
653 void add_caller_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
654 {
655 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
656
657 member_callback->owner = owner;
658 member_callback->callback = callback;
659 add_ptr_list(&member_callbacks_new, member_callback);
660 }
661
662 void add_split_return_callback(void (*fn)(int return_id, char *return_ranges, struct expression *returned_expr))
663 {
664 struct returned_state_callback *callback = __alloc_returned_state_callback(0);
665
666 callback->callback = fn;
667 add_ptr_list(&returned_state_callbacks, callback);
668 }
669
670 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))
671 {
672 struct returned_member_callback *member_callback = __alloc_returned_member_callback(0);
673
674 member_callback->owner = owner;
675 member_callback->callback = callback;
676 add_ptr_list(&returned_member_callbacks, member_callback);
677 }
678
679 void select_call_implies_hook(int type, void (*callback)(struct expression *call, struct expression *arg, char *key, char *value))
680 {
681 struct db_implies_callback *cb = __alloc_db_implies_callback(0);
871 if (sm_name[len] == '\0') {
872 snprintf(buf, sizeof(buf), "%s%s$",
873 add_star ? "*" : "", is_address ? "*" : "");
874 } else {
875 if (sm_name[len] != '.' && sm_name[len] != '-')
876 goto free;
877 if (sm_name[len] == '-')
878 len++;
879 // FIXME does is_address really imply that sm_name[len] == '-'
880 snprintf(buf, sizeof(buf), "%s$->%s", add_star ? "*" : "",
881 sm_name + len);
882 }
883
884 ret = alloc_sname(buf);
885 free:
886 free_string(name);
887 return ret;
888 }
889
890 static void print_struct_members(struct expression *call, struct expression *expr, int param, struct stree *stree,
891 void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm),
892 bool new)
893 {
894 struct sm_state *sm;
895 const char *sm_name;
896 char *name;
897 struct symbol *sym;
898 int len;
899 char printed_name[256];
900 int is_address = 0;
901 bool add_star;
902 struct symbol *type;
903
904 expr = strip_expr(expr);
905 if (!expr)
906 return;
907 type = get_type(expr);
908 if (type && type_bits(type) < type_bits(&ulong_ctype))
909 return;
910
911 if (expr->type == EXPR_PREOP && expr->op == '&') {
912 expr = strip_expr(expr->unop);
913 is_address = 1;
914 }
915
916 name = expr_to_var_sym(expr, &sym);
917 if (!name || !sym)
918 goto free;
919
920 len = strlen(name);
921 FOR_EACH_SM(stree, sm) {
922 if (sm->sym != sym)
923 continue;
924 sm_name = sm->name;
925 add_star = false;
926 if (sm_name[0] == '*') {
927 add_star = true;
928 sm_name++;
929 }
930 // FIXME: simplify?
931 if (!add_star && strcmp(name, sm_name) == 0) {
932 if (is_address) {
933 snprintf(printed_name, sizeof(printed_name), "*$");
934 } else {
935 if (new)
936 snprintf(printed_name, sizeof(printed_name), "$");
937 else
938 continue;
939 }
940 } else if (add_star && strcmp(name, sm_name) == 0) {
941 snprintf(printed_name, sizeof(printed_name), "%s*$",
942 is_address ? "*" : "");
943 } else if (strncmp(name, sm_name, len) == 0) {
944 if (sm_name[len] != '.' && sm_name[len] != '-')
945 continue;
946 if (is_address && sm_name[len] == '.') {
947 snprintf(printed_name, sizeof(printed_name),
948 "%s$->%s", add_star ? "*" : "",
949 sm_name + len + 1);
950 } else if (is_address && sm_name[len] == '-') {
951 snprintf(printed_name, sizeof(printed_name),
952 "%s(*$)%s", add_star ? "*" : "",
953 sm_name + len);
954 } else {
955 snprintf(printed_name, sizeof(printed_name),
956 "%s$%s", add_star ? "*" : "",
957 sm_name + len);
958 }
959 } else {
960 continue;
961 }
962 if (is_recursive_member(printed_name))
963 continue;
964 callback(call, param, printed_name, sm);
965 } END_FOR_EACH_SM(sm);
966 free:
967 free_string(name);
968 }
969
970 static void match_call_info(struct expression *call)
971 {
972 struct member_info_callback *cb;
973 struct expression *arg;
974 struct stree *stree;
975 char *name;
976 int i;
977
978 name = get_fnptr_name(call->fn);
979 if (!name)
980 return;
981
982 FOR_EACH_PTR(member_callbacks, cb) {
983 stree = get_all_states_stree(cb->owner);
984 i = 0;
985 FOR_EACH_PTR(call->args, arg) {
986 print_struct_members(call, arg, i, stree, cb->callback, 0);
987 i++;
988 } END_FOR_EACH_PTR(arg);
989 free_stree(&stree);
990 } END_FOR_EACH_PTR(cb);
991
992 free_string(name);
993 }
994
995 static void match_call_info_new(struct expression *call)
996 {
997 struct member_info_callback *cb;
998 struct expression *arg;
999 struct stree *stree;
1000 char *name;
1001 int i;
1002
1003 name = get_fnptr_name(call->fn);
1004 if (!name)
1005 return;
1006
1007 FOR_EACH_PTR(member_callbacks_new, cb) {
1008 stree = get_all_states_stree(cb->owner);
1009 i = 0;
1010 FOR_EACH_PTR(call->args, arg) {
1011 print_struct_members(call, arg, i, stree, cb->callback, 1);
1012 i++;
1013 } END_FOR_EACH_PTR(arg);
1014 free_stree(&stree);
1015 } END_FOR_EACH_PTR(cb);
1016
1017 free_string(name);
1018 }
1019
1020 static int get_param(int param, char **name, struct symbol **sym)
1021 {
1022 struct symbol *arg;
1023 int i;
1024
1025 i = 0;
1026 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
1027 /*
1028 * this is a temporary hack to work around a bug (I think in sparse?)
1029 * 2.6.37-rc1:fs/reiserfs/journal.o
1030 * If there is a function definition without parameter name found
1031 * after a function implementation then it causes a crash.
1032 * int foo() {}
1033 * int bar(char *);
1034 */
1035 if (arg->ident->name < (char *)100)
1036 continue;
1037 if (i == param) {
1038 *name = arg->ident->name;
1039 *sym = arg;
1161 sql_filter);
1162
1163 after = ptr_list_size((struct ptr_list *)ptr_names);
1164 if (before == after)
1165 return;
1166
1167 while ((name = get_next_ptr_name()))
1168 get_ptr_names(NULL, name);
1169 }
1170
1171 static void match_data_from_db(struct symbol *sym)
1172 {
1173 struct select_caller_info_data data = { .prev_func_id = -1 };
1174 struct sm_state *sm;
1175 struct stree *stree;
1176 struct timeval end_time;
1177
1178 if (!sym || !sym->ident)
1179 return;
1180
1181 set_fn_mtag(sym);
1182 gettimeofday(&data.start_time, NULL);
1183
1184 __push_fake_cur_stree();
1185 __unnullify_path();
1186
1187 if (!__inline_fn) {
1188 char *ptr;
1189
1190 if (sym->ctype.modifiers & MOD_STATIC)
1191 get_ptr_names(get_base_file(), sym->ident->name);
1192 else
1193 get_ptr_names(NULL, sym->ident->name);
1194
1195 if (ptr_list_size((struct ptr_list *)ptr_names) > 20) {
1196 __free_ptr_list((struct ptr_list **)&ptr_names);
1197 __free_ptr_list((struct ptr_list **)&ptr_names_done);
1198 __free_fake_cur_stree();
1199 return;
1200 }
1201
1625 }
1626 }
1627
1628 return_id++;
1629 FOR_EACH_PTR(returned_state_callbacks, cb) {
1630 cb->callback(return_id, return_ranges, expr);
1631 } END_FOR_EACH_PTR(cb);
1632
1633 __free_fake_cur_stree();
1634 } END_FOR_EACH_PTR(tmp);
1635
1636 free_slist(&already_handled);
1637
1638 return ret;
1639 }
1640
1641 static int call_return_state_hooks_split_possible(struct expression *expr)
1642 {
1643 struct sm_state *sm;
1644
1645 if (!expr)
1646 return 0;
1647
1648 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
1649 return split_possible_helper(sm, expr);
1650 }
1651
1652 static bool has_possible_negative(struct sm_state *sm)
1653 {
1654 struct sm_state *tmp;
1655
1656 if (!type_signed(estate_type(sm->state)))
1657 return false;
1658
1659 FOR_EACH_PTR(sm->possible, tmp) {
1660 if (!estate_rl(tmp->state))
1661 continue;
1662 if (sval_is_negative(estate_min(tmp->state)) &&
1663 sval_is_negative(estate_max(tmp->state)))
1664 return true;
1665 } END_FOR_EACH_PTR(tmp);
1763 struct sm_state *sm;
1764 struct smatch_state *state;
1765 int nr_states;
1766 int final_pass_orig = final_pass;
1767
1768 if (!expr || expr_equal_to_param(expr, -1))
1769 return 0;
1770 if (expr->type == EXPR_CALL)
1771 return 0;
1772
1773 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
1774 if (!sm)
1775 return 0;
1776 if (ptr_list_size((struct ptr_list *)sm->possible) == 1)
1777 return 0;
1778 state = sm->state;
1779 if (!estate_rl(state))
1780 return 0;
1781 if (estate_min(state).value == 0 && estate_max(state).value == 0)
1782 return 0;
1783 if (has_possible_negative(sm))
1784 return 0;
1785 if (!has_separate_zero_null(sm))
1786 return 0;
1787
1788 nr_states = get_db_state_count();
1789 if (option_info && nr_states >= 1500)
1790 return 0;
1791
1792 rl = estate_rl(state);
1793
1794 __push_fake_cur_stree();
1795
1796 final_pass = 0;
1797 __split_whole_condition(expr);
1798 final_pass = final_pass_orig;
1799
1800 nonnull_rl = rl_filter(rl, rl_zero());
1801 return_ranges = show_rl(nonnull_rl);
1802 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(nonnull_rl));
1803
1804 return_id++;
2078 struct statement *stmt, *last_stmt;
2079
2080 if (!expr)
2081 return NULL;
2082 if (expr->type == EXPR_PREOP && expr->op == '(')
2083 expr = expr->unop;
2084 if (expr->type != EXPR_STATEMENT)
2085 return orig;
2086 stmt = expr->statement;
2087 if (!stmt || stmt->type != STMT_COMPOUND)
2088 return orig;
2089
2090 last_stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
2091 if (!last_stmt || last_stmt->type == STMT_LABEL)
2092 last_stmt = last_stmt->label_statement;
2093 if (!last_stmt || last_stmt->type != STMT_EXPRESSION)
2094 return orig;
2095 return strip_expr(last_stmt->expression);
2096 }
2097
2098 static bool is_kernel_error_path(struct expression *expr)
2099 {
2100 struct range_list *rl;
2101
2102 /*
2103 * Splitting up returns requires resources. It also requires resources
2104 * for the caller. It doesn't seem worth it to split anything up.
2105 */
2106 if (!get_implied_rl(expr, &rl))
2107 return false;
2108 if (rl_type(rl) != &int_ctype)
2109 return false;
2110 if (rl_min(rl).value >= -4095 &&
2111 rl_max(rl).value < 0)
2112 return true;
2113 return false;
2114 }
2115
2116 static void call_return_state_hooks(struct expression *expr)
2117 {
2118 struct returned_state_callback *cb;
2119 struct range_list *ret_rl;
2120 const char *return_ranges;
2121 int nr_states;
2122 sval_t sval;
2123
2124 if (__path_is_null())
2125 return;
2126
2127 expr = strip_expr(expr);
2128 expr = strip_expr_statement(expr);
2129
2130 if (is_impossible_path())
2131 goto vanilla;
2132
2133 if (expr && (expr->type == EXPR_COMPARE ||
2134 !get_implied_value(expr, &sval)) &&
2135 (is_condition(expr) || is_boolean(expr))) {
2136 call_return_state_hooks_compare(expr);
2137 return;
2138 } else if (call_return_state_hooks_conditional(expr)) {
2139 return;
2140 } else if (is_kernel_error_path(expr)) {
2141 goto vanilla;
2142 } else if (call_return_state_hooks_split_possible(expr)) {
2143 return;
2144 } else if (split_positive_from_negative(expr)) {
2145 return;
2146 } else if (call_return_state_hooks_split_null_non_null_zero(expr)) {
2147 return;
2148 } else if (call_return_state_hooks_split_success_fail(expr)) {
2149 return;
2150 } else if (splitable_function_call(expr)) {
2151 return;
2152 } else if (split_by_bool_param(expr)) {
2153 } else if (split_by_null_nonnull_param(expr)) {
2154 return;
2155 }
2156
2157 vanilla:
2158 return_ranges = get_return_ranges_str(expr, &ret_rl);
2159 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
2160
2161 return_id++;
2243 "db/common_caller_info.schema",
2244 "db/return_states.schema",
2245 "db/function_type_size.schema",
2246 "db/type_size.schema",
2247 "db/function_type_info.schema",
2248 "db/type_info.schema",
2249 "db/call_implies.schema",
2250 "db/return_implies.schema",
2251 "db/function_ptr.schema",
2252 "db/local_values.schema",
2253 "db/function_type_value.schema",
2254 "db/type_value.schema",
2255 "db/function_type.schema",
2256 "db/data_info.schema",
2257 "db/parameter_name.schema",
2258 "db/constraints.schema",
2259 "db/constraints_required.schema",
2260 "db/fn_ptr_data_link.schema",
2261 "db/fn_data_link.schema",
2262 "db/mtag_about.schema",
2263 "db/mtag_info.schema",
2264 "db/mtag_map.schema",
2265 "db/mtag_data.schema",
2266 "db/mtag_alias.schema",
2267 };
2268 static char buf[4096];
2269 int fd;
2270 int ret;
2271 int i;
2272
2273 rc = sqlite3_open(":memory:", &mem_db);
2274 if (rc != SQLITE_OK) {
2275 sm_ierror("starting In-Memory database.");
2276 return;
2277 }
2278
2279 for (i = 0; i < ARRAY_SIZE(schema_files); i++) {
2280 fd = open_schema_file(schema_files[i]);
2281 if (fd < 0)
2282 continue;
2283 ret = read(fd, buf, sizeof(buf));
2291 schema_files[i], sizeof(buf));
2292 continue;
2293 }
2294 buf[ret] = '\0';
2295 rc = sqlite3_exec(mem_db, buf, NULL, NULL, &err);
2296 if (rc != SQLITE_OK) {
2297 sm_ierror("SQL error #2: %s", err);
2298 sm_ierror("%s", buf);
2299 }
2300 }
2301 }
2302
2303 static void init_cachedb(void)
2304 {
2305 char *err = NULL;
2306 int rc;
2307 const char *schema_files[] = {
2308 "db/call_implies.schema",
2309 "db/return_implies.schema",
2310 "db/type_info.schema",
2311 "db/mtag_about.schema",
2312 "db/mtag_data.schema",
2313 "db/mtag_info.schema",
2314 "db/sink_info.schema",
2315 };
2316 static char buf[4096];
2317 int fd;
2318 int ret;
2319 int i;
2320
2321 rc = sqlite3_open(":memory:", &cache_db);
2322 if (rc != SQLITE_OK) {
2323 sm_ierror("starting In-Memory database.");
2324 return;
2325 }
2326
2327 for (i = 0; i < ARRAY_SIZE(schema_files); i++) {
2328 fd = open_schema_file(schema_files[i]);
2329 if (fd < 0)
2330 continue;
2331 ret = read(fd, buf, sizeof(buf));
2332 if (ret < 0) {
2333 sm_ierror("failed to read: %s", schema_files[i]);
2358
2359
2360 p += snprintf(p, 4096 - (p - buf), "insert or ignore into %s values (", table);
2361 for (i = 0; i < argc; i++) {
2362 if (i)
2363 p += snprintf(p, 4096 - (p - buf), ", ");
2364 sqlite3_snprintf(sizeof(tmp), tmp, "%q", escape_newlines(argv[i]));
2365 p += snprintf(p, 4096 - (p - buf), "'%s'", tmp);
2366
2367 }
2368 p += snprintf(p, 4096 - (p - buf), ");");
2369 if (p - buf > 4096)
2370 return 0;
2371
2372 sm_msg("SQL: %s", buf);
2373 return 0;
2374 }
2375
2376 static void dump_cache(struct symbol_list *sym_list)
2377 {
2378 const char *cache_tables[] = {
2379 "type_info", "return_implies", "call_implies", "mtag_data",
2380 "mtag_info", "mtag_about", "sink_info",
2381 };
2382 char buf[64];
2383 int i;
2384
2385 if (!option_info)
2386 return;
2387
2388 for (i = 0; i < ARRAY_SIZE(cache_tables); i++) {
2389 snprintf(buf, sizeof(buf), "select * from %s;", cache_tables[i]);
2390 cache_sql(&save_cache_data, (char *)cache_tables[i], buf);
2391 }
2392 }
2393
2394 void open_smatch_db(char *db_file)
2395 {
2396 int rc;
2397
2398 if (option_no_db)
2399 return;
2400
2401 use_states = malloc(num_checks + 1);
2402 memset(use_states, 0xff, num_checks + 1);
2403
2404 init_memdb();
2405 init_cachedb();
2406
2407 rc = sqlite3_open_v2(db_file, &smatch_db, SQLITE_OPEN_READONLY, NULL);
2408 if (rc != SQLITE_OK) {
2409 option_no_db = 1;
2410 return;
2411 }
2517 return;
2518 }
2519 replace_table = malloc(replace_count * sizeof(char *));
2520
2521 p = buf;
2522 i = 0;
2523 while (*p) {
2524 func = alloc_string(get_next_string(&p));
2525 orig = alloc_string(get_next_string(&p));
2526 new = alloc_string(get_next_string(&p));
2527
2528 replace_table[i++] = func;
2529 replace_table[i++] = orig;
2530 replace_table[i++] = new;
2531 }
2532 }
2533
2534 void register_definition_db_callbacks(int id)
2535 {
2536 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
2537 add_hook(&match_call_info_new, FUNCTION_CALL_HOOK);
2538 add_split_return_callback(match_return_info);
2539 add_split_return_callback(print_returned_struct_members);
2540 add_hook(&call_return_state_hooks, RETURN_HOOK);
2541 add_hook(&match_end_func_info, END_FUNC_HOOK);
2542 add_hook(&match_after_func, AFTER_FUNC_HOOK);
2543
2544 add_hook(&match_data_from_db, FUNC_DEF_HOOK);
2545 add_hook(&match_call_implies, FUNC_DEF_HOOK);
2546 add_hook(&match_return_implies, CALL_HOOK_AFTER_INLINE);
2547
2548 register_common_funcs();
2549 register_return_replacements();
2550
2551 add_hook(&dump_cache, END_FILE_HOOK);
2552 }
2553
2554 void register_db_call_marker(int id)
2555 {
2556 add_hook(&match_call_marker, FUNCTION_CALL_HOOK);
2557 }
2582 return name;
2583 snprintf(member_name, sizeof(member_name), "%s%s%s", star, name, key + 1);
2584 free_string(name);
2585 return alloc_string(member_name);
2586 }
2587
2588 while (expr->type == EXPR_ASSIGNMENT)
2589 expr = strip_expr(expr->right);
2590 if (expr->type != EXPR_CALL)
2591 return NULL;
2592
2593 arg = get_argument_from_call_expr(expr->args, param);
2594 if (!arg)
2595 return NULL;
2596
2597 return get_variable_from_key(arg, key, sym);
2598 }
2599
2600 char *get_variable_from_key(struct expression *arg, const char *key, struct symbol **sym)
2601 {
2602 struct symbol *type;
2603 char buf[256];
2604 char *tmp;
2605 int star_cnt = 0;
2606 bool add_dot = false;
2607
2608 if (!arg)
2609 return NULL;
2610
2611 arg = strip_expr(arg);
2612
2613 if (strcmp(key, "$") == 0)
2614 return expr_to_var_sym(arg, sym);
2615
2616 if (strcmp(key, "*$") == 0) {
2617 if (arg->type == EXPR_PREOP && arg->op == '&') {
2618 arg = strip_expr(arg->unop);
2619 return expr_to_var_sym(arg, sym);
2620 } else {
2621 tmp = expr_to_var_sym(arg, sym);
2622 if (!tmp)
2623 return NULL;
2624 snprintf(buf, sizeof(buf), "*%s", tmp);
2625 free_string(tmp);
2626 return alloc_string(buf);
2627 }
2628 }
2629
2630 if (strncmp(key, "(*$)", 4) == 0) {
2631 char buf[64];
2632
2633 if (arg->type == EXPR_PREOP && arg->op == '&') {
2634 arg = strip_expr(arg->unop);
2635 snprintf(buf, sizeof(buf), "$%s", key + 4);
2636 return get_variable_from_key(arg, buf, sym);
2637 } else {
2638 tmp = expr_to_var_sym(arg, sym);
2639 if (!tmp)
2640 return NULL;
2641 snprintf(buf, sizeof(buf), "(*%s)%s", tmp, key + 4);
2642 free_string(tmp);
2643 return alloc_string(buf);
2644 }
2645 }
2646
2647 while (key[0] == '*') {
2648 star_cnt++;
2649 key++;
2650 }
2651
2652 /*
2653 * FIXME: This is a hack.
2654 * We should be able to parse expressions like (*$)->foo and *$->foo.
2655 */
2656 type = get_type(arg);
2657 if (is_struct_ptr(type))
2658 add_dot = true;
2659
2660 if (arg->type == EXPR_PREOP && arg->op == '&' && star_cnt && !add_dot) {
2661 arg = strip_expr(arg->unop);
2662 star_cnt--;
2663 }
2664
2665 if (arg->type == EXPR_PREOP && arg->op == '&') {
2666 arg = strip_expr(arg->unop);
2667 tmp = expr_to_var_sym(arg, sym);
2668 if (!tmp)
2669 return NULL;
2670 snprintf(buf, sizeof(buf), "%.*s%s.%s",
2671 star_cnt, "**********", tmp, key + 3);
2672 return alloc_string(buf);
2673 }
2674
2675 tmp = expr_to_var_sym(arg, sym);
2676 if (!tmp)
2677 return NULL;
2678 snprintf(buf, sizeof(buf), "%.*s%s%s", star_cnt, "**********", tmp, key + 1);
2679 free_string(tmp);
2680 return alloc_string(buf);
2689 return get_variable_from_key(arg, key, sym);
2690 }
2691
2692 const char *state_name_to_param_name(const char *state_name, const char *param_name)
2693 {
2694 int star_cnt = 0;
2695 int name_len;
2696 char buf[256];
2697
2698 name_len = strlen(param_name);
2699
2700 while (state_name[0] == '*') {
2701 star_cnt++;
2702 state_name++;
2703 }
2704
2705 /* ten out of ten stars! */
2706 if (star_cnt > 10)
2707 return NULL;
2708
2709 if (strncmp(state_name, "(*", 2) == 0 &&
2710 strncmp(state_name + 2, param_name, name_len) == 0 &&
2711 state_name[name_len + 2] == ')') {
2712 snprintf(buf, sizeof(buf), "%.*s(*$)%s", star_cnt, "**********",
2713 state_name + name_len + 3);
2714 return alloc_sname(buf);
2715 }
2716
2717 if (strcmp(state_name, param_name) == 0) {
2718 snprintf(buf, sizeof(buf), "%.*s$", star_cnt, "**********");
2719 return alloc_sname(buf);
2720 }
2721
2722 if (state_name[name_len] == '-' && /* check for '-' from "->" */
2723 strncmp(state_name, param_name, name_len) == 0) {
2724 snprintf(buf, sizeof(buf), "%.*s$%s", star_cnt, "**********", state_name + name_len);
2725 return alloc_sname(buf);
2726 }
2727 return NULL;
2728 }
2729
2730 const char *get_param_name_var_sym(const char *name, struct symbol *sym)
2731 {
2732 if (!sym || !sym->ident)
2733 return NULL;
2734
2735 return state_name_to_param_name(name, sym->ident->name);
2736 }
|