Print this page
12166 resync smatch to 0.6.1-rc1-il-3
@@ -20,15 +20,10 @@
#include "smatch_extra.h"
static int my_id;
static int param_id;
-static struct stree *used_stree;
-static struct stree_stack *saved_stack;
-
-STATE(used);
-
int get_param_from_container_of(struct expression *expr)
{
struct expression *param_expr;
struct symbol *type;
sval_t sval;
@@ -82,125 +77,10 @@
return -1;
return sval.value;
}
-static int get_container_arg(struct symbol *sym)
-{
- struct expression *__mptr;
- int param;
-
- if (!sym || !sym->ident)
- return -1;
-
- __mptr = get_assigned_expr_name_sym(sym->ident->name, sym);
- param = get_param_from_container_of(__mptr);
-
- return param;
-}
-
-static int get_container_offset(struct symbol *sym)
-{
- struct expression *__mptr;
- int offset;
-
- if (!sym || !sym->ident)
- return -1;
-
- __mptr = get_assigned_expr_name_sym(sym->ident->name, sym);
- offset = get_offset_from_container_of(__mptr);
-
- return offset;
-}
-
-static char *get_container_name_sm(struct sm_state *sm, int offset)
-{
- static char buf[256];
- const char *name;
-
- name = get_param_name(sm);
- if (!name)
- return NULL;
-
- if (name[0] == '$')
- snprintf(buf, sizeof(buf), "$(-%d)%s", offset, name + 1);
- else if (name[0] == '*' || name[1] == '$')
- snprintf(buf, sizeof(buf), "*$(-%d)%s", offset, name + 2);
- else
- return NULL;
-
- return buf;
-}
-
-static void get_state_hook(int owner, const char *name, struct symbol *sym)
-{
- int arg;
-
- if (!option_info)
- return;
- if (__in_fake_assign)
- return;
-
- arg = get_container_arg(sym);
- if (arg >= 0)
- set_state_stree(&used_stree, my_id, name, sym, &used);
-}
-
-static void set_param_used(struct expression *call, struct expression *arg, char *key, char *unused)
-{
- struct symbol *sym;
- char *name;
- int arg_nr;
-
- name = get_variable_from_key(arg, key, &sym);
- if (!name || !sym)
- goto free;
-
- arg_nr = get_container_arg(sym);
- if (arg_nr >= 0)
- set_state(my_id, name, sym, &used);
-free:
- free_string(name);
-}
-
-static void process_states(void)
-{
- struct sm_state *tmp;
- int arg, offset;
- const char *name;
-
- FOR_EACH_SM(used_stree, tmp) {
- arg = get_container_arg(tmp->sym);
- offset = get_container_offset(tmp->sym);
- if (arg < 0 || offset < 0)
- continue;
- name = get_container_name_sm(tmp, offset);
- if (!name)
- continue;
- sql_insert_return_implies(CONTAINER, arg, name, "");
- } END_FOR_EACH_SM(tmp);
-
- free_stree(&used_stree);
-}
-
-static void match_function_def(struct symbol *sym)
-{
- free_stree(&used_stree);
-}
-
-static void match_save_states(struct expression *expr)
-{
- push_stree(&saved_stack, used_stree);
- used_stree = NULL;
-}
-
-static void match_restore_states(struct expression *expr)
-{
- free_stree(&used_stree);
- used_stree = pop_stree(&saved_stack);
-}
-
static void print_returns_container_of(int return_id, char *return_ranges, struct expression *expr)
{
int offset;
int param;
char key[64];
@@ -219,38 +99,10 @@
/* no need to add it to return_implies because it's not really param_used */
sql_insert_return_states(return_id, return_ranges, CONTAINER, -1,
key, value);
}
-static void returns_container_of(struct expression *expr, int param, char *key, char *value)
-{
- struct expression *call, *arg;
- int offset;
- char buf[64];
-
- if (expr->type != EXPR_ASSIGNMENT || expr->op != '=')
- return;
- call = strip_expr(expr->right);
- if (call->type != EXPR_CALL)
- return;
- if (param != -1)
- return;
- param = atoi(key);
- offset = atoi(value);
-
- arg = get_argument_from_call_expr(call->args, param);
- if (!arg)
- return;
- if (arg->type != EXPR_SYMBOL)
- return;
- param = get_param_num(arg);
- if (param < 0)
- return;
- snprintf(buf, sizeof(buf), "$(%d)", offset);
- sql_insert_return_implies(CONTAINER, param, buf, "");
-}
-
static int get_deref_count(struct expression *expr)
{
int cnt = 0;
while (expr && expr->type == EXPR_DEREF) {
@@ -297,104 +149,164 @@
}
return n;
}
-static char *get_shared_str(struct expression *container, struct expression *expr)
+static char *get_shared_str(struct expression *expr, struct expression *container)
{
struct expression *one, *two;
- int cont, exp, min, ret, n;
+ int exp, cont, min, ret, n;
static char buf[48];
- cont = get_deref_count(container);
exp = get_deref_count(expr);
- if (cont < 0 || exp < 0)
+ cont = get_deref_count(container);
+ if (exp < 0 || cont < 0)
return NULL;
- min = (cont < exp) ? cont : exp;
+ min = (exp < cont) ? exp : cont;
while (min >= 0) {
- one = get_partial_deref(container, cont - min);
- two = get_partial_deref(expr, exp - min);
+ one = get_partial_deref(expr, exp - min);
+ two = get_partial_deref(container, cont - min);
if (expr_equiv(one, two))
goto found;
min--;
}
return NULL;
found:
- ret = partial_deref_to_offset_str(container, cont - min, '-', buf, sizeof(buf));
+ ret = partial_deref_to_offset_str(expr, exp - min, '-', buf, sizeof(buf));
if (ret < 0)
return NULL;
n = ret;
- ret = partial_deref_to_offset_str(expr, exp - min, '+', buf + ret, sizeof(buf) - ret);
+ ret = partial_deref_to_offset_str(container, cont - min, '+', buf + ret, sizeof(buf) - ret);
if (ret < 0)
return NULL;
n += ret;
if (n >= sizeof(buf))
return NULL;
return buf;
}
+static char *get_stored_container_name(struct expression *container,
+ struct expression *expr)
+{
+ struct smatch_state *state;
+ static char buf[64];
+ char *p;
+ int param;
+
+ if (!container || container->type != EXPR_SYMBOL)
+ return NULL;
+ if (!expr || expr->type != EXPR_SYMBOL)
+ return NULL;
+ state = get_state_expr(param_id, expr);
+ if (!state)
+ return NULL;
+
+ snprintf(buf, sizeof(buf), "%s", state->name);
+ p = strchr(buf, '|');
+ if (!p)
+ return NULL;
+ *p = '\0';
+ param = atoi(p + 2);
+ if (get_param_sym_from_num(param) == container->symbol)
+ return buf;
+ return NULL;
+}
+
char *get_container_name(struct expression *container, struct expression *expr)
{
struct symbol *container_sym, *sym;
struct expression *tmp;
static char buf[64];
- char *shared;
+ char *ret, *shared;
bool star;
int cnt;
- container_sym = expr_to_sym(container);
+ expr = strip_expr(expr);
+ container = strip_expr(container);
+
+ ret = get_stored_container_name(container, expr);
+ if (ret)
+ return ret;
+
sym = expr_to_sym(expr);
- if (container_sym && container_sym == sym)
+ container_sym = expr_to_sym(container);
+ if (sym && sym == container_sym)
goto found;
cnt = 0;
- while ((tmp = get_assigned_expr(expr))) {
- expr = tmp;
+ while ((tmp = get_assigned_expr(container))) {
+ container = strip_expr(tmp);
if (cnt++ > 3)
break;
}
cnt = 0;
- while ((tmp = get_assigned_expr(container))) {
- container = tmp;
+ while ((tmp = get_assigned_expr(expr))) {
+ expr = strip_expr(tmp);
if (cnt++ > 3)
break;
}
found:
- expr = strip_expr(expr);
+
+ if (container->type == EXPR_DEREF)
star = true;
- if (expr->type == EXPR_PREOP && expr->op == '&') {
- expr = strip_expr(expr->unop);
+ else
star = false;
- }
- container_sym = expr_to_sym(container);
- if (!container_sym)
- return NULL;
+ if (container->type == EXPR_PREOP && container->op == '&')
+ container = strip_expr(container->unop);
+ if (expr->type == EXPR_PREOP && expr->op == '&')
+ expr = strip_expr(expr->unop);
+
sym = expr_to_sym(expr);
- if (!sym || container_sym != sym)
+ if (!sym)
return NULL;
+ container_sym = expr_to_sym(container);
+ if (!container_sym || sym != container_sym)
+ return NULL;
- shared = get_shared_str(container, expr);
+ shared = get_shared_str(expr, container);
+ if (!shared)
+ return NULL;
if (star)
snprintf(buf, sizeof(buf), "*(%s)", shared);
else
snprintf(buf, sizeof(buf), "%s", shared);
return buf;
}
+static bool is_fn_ptr(struct expression *expr)
+{
+ struct symbol *type;
+
+ if (!expr)
+ return false;
+ if (expr->type != EXPR_SYMBOL && expr->type != EXPR_DEREF)
+ return false;
+
+ type = get_type(expr);
+ if (!type || type->type != SYM_PTR)
+ return false;
+ type = get_real_base_type(type);
+ if (!type || type->type != SYM_FN)
+ return false;
+ return true;
+}
+
static void match_call(struct expression *call)
{
- struct expression *fn, *arg;
+ struct expression *fn, *arg, *tmp;
+ bool found = false;
+ int fn_param, param;
+ char buf[32];
char *name;
- int param;
/*
* We're trying to link the function with the parameter. There are a
* couple ways this can be passed:
* foo->func(foo, ...);
@@ -412,21 +324,51 @@
param = -1;
FOR_EACH_PTR(call->args, arg) {
param++;
- name = get_container_name(fn, arg);
+ name = get_container_name(arg, fn);
if (!name)
continue;
+ found = true;
sql_insert_caller_info(call, CONTAINER, param, name, "$(-1)");
} END_FOR_EACH_PTR(arg);
+
+ if (found)
+ return;
+
+ fn_param = -1;
+ FOR_EACH_PTR(call->args, arg) {
+ fn_param++;
+ if (!is_fn_ptr(arg))
+ continue;
+ param = -1;
+ FOR_EACH_PTR(call->args, tmp) {
+ param++;
+
+ /* the function isn't it's own container */
+ if (arg == tmp)
+ continue;
+
+ name = get_container_name(tmp, arg);
+ if (!name)
+ continue;
+
+ snprintf(buf, sizeof(buf), "$%d", param);
+ sql_insert_caller_info(call, CONTAINER, fn_param, name, buf);
+ return;
+ } END_FOR_EACH_PTR(tmp);
+ } END_FOR_EACH_PTR(arg);
}
static void db_passed_container(const char *name, struct symbol *sym, char *key, char *value)
{
- set_state(param_id, name, sym, alloc_state_str(key));
+ char buf[64];
+
+ snprintf(buf, sizeof(buf), "%s|%s", key, value);
+ set_state(param_id, name, sym, alloc_state_str(buf));
}
struct db_info {
struct symbol *arg;
int prev_offset;
@@ -493,11 +435,11 @@
snprintf(fullname, sizeof(fullname), "*%s", name);
return fullname;
}
member = get_member_from_offset(arg, offset);
- if (!member)
+ if (!member || !member->ident)
return NULL;
snprintf(fullname, sizeof(fullname), "%s->%s", name, member->ident->name);
return fullname;
}
@@ -603,20 +545,31 @@
static void load_container_data(struct symbol *arg, const char *info)
{
mtag_t cur_tag, container_tag, arg_tag;
int container_offset, arg_offset;
- char *p = (char *)info;
struct sm_state *sm;
struct stree *stree;
+ char *p, *cont;
+ char copy[64];
bool star = 0;
+ snprintf(copy, sizeof(copy), "%s", info);
+ p = strchr(copy, '|');
+ if (!p)
+ return;
+ *p = '\0';
+ cont = p + 1;
+ p = copy;
if (p[0] == '*') {
star = 1;
p += 2;
}
+ if (strcmp(cont, "$(-1)") != 0)
+ return;
+
if (!get_toplevel_mtag(cur_func_sym, &cur_tag))
return;
while (true) {
container_offset = strtoul(p, &p, 0);
@@ -673,23 +626,11 @@
void register_container_of(int id)
{
my_id = id;
- add_hook(&match_function_def, FUNC_DEF_HOOK);
-
- add_get_state_hook(&get_state_hook);
-
- add_hook(&match_save_states, INLINE_FN_START);
- add_hook(&match_restore_states, INLINE_FN_END);
-
- select_return_implies_hook(CONTAINER, &set_param_used);
- all_return_states_hook(&process_states);
-
add_split_return_callback(&print_returns_container_of);
- select_return_states_hook(CONTAINER, &returns_container_of);
-
add_hook(&match_call, FUNCTION_CALL_HOOK);
}
void register_container_of2(int id)
{