Print this page
12724 update smatch to 0.6.1-rc1-il-5
*** 48,57 ****
--- 48,58 ----
void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm);
};
ALLOCATOR(member_info_callback, "caller_info callbacks");
DECLARE_PTR_LIST(member_info_cb_list, struct member_info_callback);
static struct member_info_cb_list *member_callbacks;
+ static struct member_info_cb_list *member_callbacks_new;
struct returned_state_callback {
void (*callback)(int return_id, char *return_ranges, struct expression *return_expr);
};
ALLOCATOR(returned_state_callback, "returned state callbacks");
*** 176,194 ****
void db_ignore_states(int id)
{
use_states[id] = 0;
}
void sql_insert_return_states(int return_id, const char *return_ranges,
int type, int param, const char *key, const char *value)
{
if (key && strlen(key) >= 80)
return;
return_ranges = replace_return_ranges(return_ranges);
! sql_insert(return_states, "'%s', '%s', %lu, %d, '%s', %d, %d, %d, '%s', '%s'",
! get_base_file(), get_function(), (unsigned long)__inline_fn,
! return_id, return_ranges, fn_static(), type, param, key, value);
}
static struct string_list *common_funcs;
static int is_common_function(const char *fn)
{
--- 177,216 ----
void db_ignore_states(int id)
{
use_states[id] = 0;
}
+ unsigned long long __fn_mtag;
+ static void set_fn_mtag(struct symbol *sym)
+ {
+ char buf[128];
+
+ if (cur_func_sym->ctype.modifiers & MOD_STATIC)
+ snprintf(buf, sizeof(buf), "%s %s", get_base_file(), get_function());
+ else
+ snprintf(buf, sizeof(buf), "extern %s", get_function());
+
+ __fn_mtag = str_to_mtag(buf);
+ }
+
void sql_insert_return_states(int return_id, const char *return_ranges,
int type, int param, const char *key, const char *value)
{
+ unsigned long long id;
+
+
if (key && strlen(key) >= 80)
return;
+ if (__inline_fn)
+ id = (unsigned long)__inline_fn;
+ else
+ id = __fn_mtag;
+
return_ranges = replace_return_ranges(return_ranges);
! sql_insert(return_states, "'%s', '%s', %llu, %d, '%s', %d, %d, %d, '%s', '%s'",
! get_base_file(), get_function(), id, return_id,
! return_ranges, fn_static(), type, param, key, value);
}
static struct string_list *common_funcs;
static int is_common_function(const char *fn)
{
*** 370,388 ****
type, param, key, value);
}
void sql_insert_mtag_about(mtag_t tag, const char *left_name, const char *right_name)
{
! sql_insert(mtag_about, "%lld, '%s', '%s', %d, '%s', '%s'",
! tag, get_filename(), get_function(), get_lineno(), left_name, right_name);
}
! void sql_insert_mtag_map(mtag_t tag, int offset, mtag_t container)
{
! sql_insert(mtag_map, "%lld, %d, %lld", tag, offset, container);
}
void sql_insert_mtag_alias(mtag_t orig, mtag_t alias)
{
sql_insert(mtag_alias, "%lld, %lld", orig, alias);
}
--- 392,416 ----
type, param, key, value);
}
void sql_insert_mtag_about(mtag_t tag, const char *left_name, const char *right_name)
{
! sql_insert_cache(mtag_about, "%lld, '%s', '%s', %d, '%s', '%s'",
! tag, get_filename(), get_function(), get_lineno(),
! left_name, right_name);
}
! void sql_insert_mtag_info(mtag_t tag, int type, const char *value)
{
! sql_insert_cache(mtag_info, "'%s', %lld, %d, '%s'", get_filename(), tag, type, value);
}
+ void sql_insert_mtag_map(mtag_t container, int container_offset, mtag_t tag, int tag_offset)
+ {
+ sql_insert(mtag_map, "%lld, %d, %lld, %d", container, container_offset, tag, tag_offset);
+ }
+
void sql_insert_mtag_alias(mtag_t orig, mtag_t alias)
{
sql_insert(mtag_alias, "%lld, %lld", orig, alias);
}
*** 399,415 ****
*saved_tag = -1ULL;
return 0;
}
! int mtag_map_select_container(mtag_t tag, int offset, mtag_t *container)
{
mtag_t tmp = 0;
run_sql(save_mtag, &tmp,
! "select container from mtag_map where tag = %lld and offset = %d;",
! tag, offset);
if (tmp == 0 || tmp == -1ULL)
return 0;
*container = tmp;
return 1;
--- 427,443 ----
*saved_tag = -1ULL;
return 0;
}
! int mtag_map_select_container(mtag_t tag, int container_offset, mtag_t *container)
{
mtag_t tmp = 0;
run_sql(save_mtag, &tmp,
! "select container from mtag_map where tag = %lld and container_offset = %d and tag_offset = 0;",
! tag, container_offset);
if (tmp == 0 || tmp == -1ULL)
return 0;
*container = tmp;
return 1;
*** 418,428 ****
int mtag_map_select_tag(mtag_t container, int offset, mtag_t *tag)
{
mtag_t tmp = 0;
run_sql(save_mtag, &tmp,
! "select tag from mtag_map where container = %lld and offset = %d;",
container, offset);
if (tmp == 0 || tmp == -1ULL)
return 0;
*tag = tmp;
--- 446,456 ----
int mtag_map_select_tag(mtag_t container, int offset, mtag_t *tag)
{
mtag_t tmp = 0;
run_sql(save_mtag, &tmp,
! "select tag from mtag_map where container = %lld and container_offset = %d;",
container, offset);
if (tmp == 0 || tmp == -1ULL)
return 0;
*tag = tmp;
*** 620,629 ****
--- 648,666 ----
member_callback->owner = owner;
member_callback->callback = callback;
add_ptr_list(&member_callbacks, member_callback);
}
+ void add_caller_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
+ {
+ struct member_info_callback *member_callback = __alloc_member_info_callback(0);
+
+ member_callback->owner = owner;
+ member_callback->callback = callback;
+ add_ptr_list(&member_callbacks_new, member_callback);
+ }
+
void add_split_return_callback(void (*fn)(int return_id, char *return_ranges, struct expression *returned_expr))
{
struct returned_state_callback *callback = __alloc_returned_state_callback(0);
callback->callback = fn;
*** 849,859 ****
free_string(name);
return ret;
}
static void print_struct_members(struct expression *call, struct expression *expr, int param, struct stree *stree,
! void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
{
struct sm_state *sm;
const char *sm_name;
char *name;
struct symbol *sym;
--- 886,897 ----
free_string(name);
return ret;
}
static void print_struct_members(struct expression *call, struct expression *expr, int param, struct stree *stree,
! void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm),
! bool new)
{
struct sm_state *sm;
const char *sm_name;
char *name;
struct symbol *sym;
*** 889,916 ****
add_star = true;
sm_name++;
}
// FIXME: simplify?
if (!add_star && strcmp(name, sm_name) == 0) {
! if (is_address)
snprintf(printed_name, sizeof(printed_name), "*$");
! else /* these are already handled. fixme: handle them here */
continue;
} else if (add_star && strcmp(name, sm_name) == 0) {
snprintf(printed_name, sizeof(printed_name), "%s*$",
is_address ? "*" : "");
} else if (strncmp(name, sm_name, len) == 0) {
if (sm_name[len] != '.' && sm_name[len] != '-')
continue;
! if (is_address)
snprintf(printed_name, sizeof(printed_name),
"%s$->%s", add_star ? "*" : "",
sm_name + len + 1);
! else
snprintf(printed_name, sizeof(printed_name),
"%s$%s", add_star ? "*" : "",
sm_name + len);
} else {
continue;
}
if (is_recursive_member(printed_name))
continue;
--- 927,963 ----
add_star = true;
sm_name++;
}
// FIXME: simplify?
if (!add_star && strcmp(name, sm_name) == 0) {
! if (is_address) {
snprintf(printed_name, sizeof(printed_name), "*$");
! } else {
! if (new)
! snprintf(printed_name, sizeof(printed_name), "$");
! else
continue;
+ }
} else if (add_star && strcmp(name, sm_name) == 0) {
snprintf(printed_name, sizeof(printed_name), "%s*$",
is_address ? "*" : "");
} else if (strncmp(name, sm_name, len) == 0) {
if (sm_name[len] != '.' && sm_name[len] != '-')
continue;
! if (is_address && sm_name[len] == '.') {
snprintf(printed_name, sizeof(printed_name),
"%s$->%s", add_star ? "*" : "",
sm_name + len + 1);
! } else if (is_address && sm_name[len] == '-') {
snprintf(printed_name, sizeof(printed_name),
+ "%s(*$)%s", add_star ? "*" : "",
+ sm_name + len);
+ } else {
+ snprintf(printed_name, sizeof(printed_name),
"%s$%s", add_star ? "*" : "",
sm_name + len);
+ }
} else {
continue;
}
if (is_recursive_member(printed_name))
continue;
*** 934,952 ****
FOR_EACH_PTR(member_callbacks, cb) {
stree = get_all_states_stree(cb->owner);
i = 0;
FOR_EACH_PTR(call->args, arg) {
! print_struct_members(call, arg, i, stree, cb->callback);
i++;
} END_FOR_EACH_PTR(arg);
free_stree(&stree);
} END_FOR_EACH_PTR(cb);
free_string(name);
}
static int get_param(int param, char **name, struct symbol **sym)
{
struct symbol *arg;
int i;
--- 981,1024 ----
FOR_EACH_PTR(member_callbacks, cb) {
stree = get_all_states_stree(cb->owner);
i = 0;
FOR_EACH_PTR(call->args, arg) {
! print_struct_members(call, arg, i, stree, cb->callback, 0);
i++;
} END_FOR_EACH_PTR(arg);
free_stree(&stree);
} END_FOR_EACH_PTR(cb);
free_string(name);
}
+ static void match_call_info_new(struct expression *call)
+ {
+ struct member_info_callback *cb;
+ struct expression *arg;
+ struct stree *stree;
+ char *name;
+ int i;
+
+ name = get_fnptr_name(call->fn);
+ if (!name)
+ return;
+
+ FOR_EACH_PTR(member_callbacks_new, cb) {
+ stree = get_all_states_stree(cb->owner);
+ i = 0;
+ FOR_EACH_PTR(call->args, arg) {
+ print_struct_members(call, arg, i, stree, cb->callback, 1);
+ i++;
+ } END_FOR_EACH_PTR(arg);
+ free_stree(&stree);
+ } END_FOR_EACH_PTR(cb);
+
+ free_string(name);
+ }
+
static int get_param(int param, char **name, struct symbol **sym)
{
struct symbol *arg;
int i;
*** 1104,1113 ****
--- 1176,1186 ----
struct timeval end_time;
if (!sym || !sym->ident)
return;
+ set_fn_mtag(sym);
gettimeofday(&data.start_time, NULL);
__push_fake_cur_stree();
__unnullify_path();
*** 1567,1577 ****
static int call_return_state_hooks_split_possible(struct expression *expr)
{
struct sm_state *sm;
! if (!expr || expr_equal_to_param(expr, -1))
return 0;
sm = get_sm_state_expr(SMATCH_EXTRA, expr);
return split_possible_helper(sm, expr);
}
--- 1640,1650 ----
static int call_return_state_hooks_split_possible(struct expression *expr)
{
struct sm_state *sm;
! if (!expr)
return 0;
sm = get_sm_state_expr(SMATCH_EXTRA, expr);
return split_possible_helper(sm, expr);
}
*** 1705,1714 ****
--- 1778,1789 ----
state = sm->state;
if (!estate_rl(state))
return 0;
if (estate_min(state).value == 0 && estate_max(state).value == 0)
return 0;
+ if (has_possible_negative(sm))
+ return 0;
if (!has_separate_zero_null(sm))
return 0;
nr_states = get_db_state_count();
if (option_info && nr_states >= 1500)
*** 2018,2027 ****
--- 2093,2120 ----
if (!last_stmt || last_stmt->type != STMT_EXPRESSION)
return orig;
return strip_expr(last_stmt->expression);
}
+ static bool is_kernel_error_path(struct expression *expr)
+ {
+ struct range_list *rl;
+
+ /*
+ * Splitting up returns requires resources. It also requires resources
+ * for the caller. It doesn't seem worth it to split anything up.
+ */
+ if (!get_implied_rl(expr, &rl))
+ return false;
+ if (rl_type(rl) != &int_ctype)
+ return false;
+ if (rl_min(rl).value >= -4095 &&
+ rl_max(rl).value < 0)
+ return true;
+ return false;
+ }
+
static void call_return_state_hooks(struct expression *expr)
{
struct returned_state_callback *cb;
struct range_list *ret_rl;
const char *return_ranges;
*** 2042,2051 ****
--- 2135,2146 ----
(is_condition(expr) || is_boolean(expr))) {
call_return_state_hooks_compare(expr);
return;
} else if (call_return_state_hooks_conditional(expr)) {
return;
+ } else if (is_kernel_error_path(expr)) {
+ goto vanilla;
} else if (call_return_state_hooks_split_possible(expr)) {
return;
} else if (split_positive_from_negative(expr)) {
return;
} else if (call_return_state_hooks_split_null_non_null_zero(expr)) {
*** 2163,2172 ****
--- 2258,2268 ----
"db/constraints.schema",
"db/constraints_required.schema",
"db/fn_ptr_data_link.schema",
"db/fn_data_link.schema",
"db/mtag_about.schema",
+ "db/mtag_info.schema",
"db/mtag_map.schema",
"db/mtag_data.schema",
"db/mtag_alias.schema",
};
static char buf[4096];
*** 2210,2220 ****
--- 2306,2318 ----
int rc;
const char *schema_files[] = {
"db/call_implies.schema",
"db/return_implies.schema",
"db/type_info.schema",
+ "db/mtag_about.schema",
"db/mtag_data.schema",
+ "db/mtag_info.schema",
"db/sink_info.schema",
};
static char buf[4096];
int fd;
int ret;
*** 2275,2291 ****
return 0;
}
static void dump_cache(struct symbol_list *sym_list)
{
if (!option_info)
return;
! cache_sql(&save_cache_data, (char *)"type_info", "select * from type_info;");
! cache_sql(&save_cache_data, (char *)"return_implies", "select * from return_implies;");
! cache_sql(&save_cache_data, (char *)"call_implies", "select * from call_implies;");
! cache_sql(&save_cache_data, (char *)"mtag_data", "select * from mtag_data;");
! cache_sql(&save_cache_data, (char *)"sink_info", "select * from sink_info;");
}
void open_smatch_db(char *db_file)
{
int rc;
--- 2373,2396 ----
return 0;
}
static void dump_cache(struct symbol_list *sym_list)
{
+ const char *cache_tables[] = {
+ "type_info", "return_implies", "call_implies", "mtag_data",
+ "mtag_info", "mtag_about", "sink_info",
+ };
+ char buf[64];
+ int i;
+
if (!option_info)
return;
!
! for (i = 0; i < ARRAY_SIZE(cache_tables); i++) {
! snprintf(buf, sizeof(buf), "select * from %s;", cache_tables[i]);
! cache_sql(&save_cache_data, (char *)cache_tables[i], buf);
! }
}
void open_smatch_db(char *db_file)
{
int rc;
*** 2427,2436 ****
--- 2532,2542 ----
}
void register_definition_db_callbacks(int id)
{
add_hook(&match_call_info, FUNCTION_CALL_HOOK);
+ add_hook(&match_call_info_new, FUNCTION_CALL_HOOK);
add_split_return_callback(match_return_info);
add_split_return_callback(print_returned_struct_members);
add_hook(&call_return_state_hooks, RETURN_HOOK);
add_hook(&match_end_func_info, END_FUNC_HOOK);
add_hook(&match_after_func, AFTER_FUNC_HOOK);
*** 2491,2503 ****
--- 2597,2611 ----
return get_variable_from_key(arg, key, sym);
}
char *get_variable_from_key(struct expression *arg, const char *key, struct symbol **sym)
{
+ struct symbol *type;
char buf[256];
char *tmp;
int star_cnt = 0;
+ bool add_dot = false;
if (!arg)
return NULL;
arg = strip_expr(arg);
*** 2517,2532 ****
free_string(tmp);
return alloc_string(buf);
}
}
while (key[0] == '*') {
star_cnt++;
key++;
}
! if (arg->type == EXPR_PREOP && arg->op == '&' && star_cnt) {
arg = strip_expr(arg->unop);
star_cnt--;
}
if (arg->type == EXPR_PREOP && arg->op == '&') {
--- 2625,2665 ----
free_string(tmp);
return alloc_string(buf);
}
}
+ if (strncmp(key, "(*$)", 4) == 0) {
+ char buf[64];
+
+ if (arg->type == EXPR_PREOP && arg->op == '&') {
+ arg = strip_expr(arg->unop);
+ snprintf(buf, sizeof(buf), "$%s", key + 4);
+ return get_variable_from_key(arg, buf, sym);
+ } else {
+ tmp = expr_to_var_sym(arg, sym);
+ if (!tmp)
+ return NULL;
+ snprintf(buf, sizeof(buf), "(*%s)%s", tmp, key + 4);
+ free_string(tmp);
+ return alloc_string(buf);
+ }
+ }
+
while (key[0] == '*') {
star_cnt++;
key++;
}
! /*
! * FIXME: This is a hack.
! * We should be able to parse expressions like (*$)->foo and *$->foo.
! */
! type = get_type(arg);
! if (is_struct_ptr(type))
! add_dot = true;
!
! if (arg->type == EXPR_PREOP && arg->op == '&' && star_cnt && !add_dot) {
arg = strip_expr(arg->unop);
star_cnt--;
}
if (arg->type == EXPR_PREOP && arg->op == '&') {
*** 2571,2580 ****
--- 2704,2721 ----
/* ten out of ten stars! */
if (star_cnt > 10)
return NULL;
+ if (strncmp(state_name, "(*", 2) == 0 &&
+ strncmp(state_name + 2, param_name, name_len) == 0 &&
+ state_name[name_len + 2] == ')') {
+ snprintf(buf, sizeof(buf), "%.*s(*$)%s", star_cnt, "**********",
+ state_name + name_len + 3);
+ return alloc_sname(buf);
+ }
+
if (strcmp(state_name, param_name) == 0) {
snprintf(buf, sizeof(buf), "%.*s$", star_cnt, "**********");
return alloc_sname(buf);
}