Print this page
12724 update smatch to 0.6.1-rc1-il-5


  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 }