Print this page
12166 resync smatch to 0.6.1-rc1-il-3

*** 20,34 **** #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; --- 20,29 ----
*** 82,206 **** 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]; --- 77,86 ----
*** 219,256 **** /* 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) { --- 99,108 ----
*** 297,400 **** } return n; } ! static char *get_shared_str(struct expression *container, struct expression *expr) { struct expression *one, *two; ! int cont, exp, min, ret, n; static char buf[48]; - cont = get_deref_count(container); exp = get_deref_count(expr); ! if (cont < 0 || exp < 0) return NULL; ! min = (cont < exp) ? cont : exp; while (min >= 0) { ! one = get_partial_deref(container, cont - min); ! two = get_partial_deref(expr, exp - min); if (expr_equiv(one, two)) goto found; min--; } return NULL; found: ! ret = partial_deref_to_offset_str(container, cont - 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); if (ret < 0) return NULL; n += ret; if (n >= sizeof(buf)) return NULL; return buf; } char *get_container_name(struct expression *container, struct expression *expr) { struct symbol *container_sym, *sym; struct expression *tmp; static char buf[64]; ! char *shared; bool star; int cnt; ! container_sym = expr_to_sym(container); sym = expr_to_sym(expr); ! if (container_sym && container_sym == sym) goto found; cnt = 0; ! while ((tmp = get_assigned_expr(expr))) { ! expr = tmp; if (cnt++ > 3) break; } cnt = 0; ! while ((tmp = get_assigned_expr(container))) { ! container = tmp; if (cnt++ > 3) break; } found: ! expr = strip_expr(expr); star = true; ! if (expr->type == EXPR_PREOP && expr->op == '&') { ! expr = strip_expr(expr->unop); star = false; - } ! container_sym = expr_to_sym(container); ! if (!container_sym) ! return NULL; sym = expr_to_sym(expr); ! if (!sym || container_sym != sym) return NULL; ! shared = get_shared_str(container, expr); if (star) snprintf(buf, sizeof(buf), "*(%s)", shared); else snprintf(buf, sizeof(buf), "%s", shared); return buf; } static void match_call(struct expression *call) { ! struct expression *fn, *arg; 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, ...); --- 149,312 ---- } return n; } ! static char *get_shared_str(struct expression *expr, struct expression *container) { struct expression *one, *two; ! int exp, cont, min, ret, n; static char buf[48]; exp = get_deref_count(expr); ! cont = get_deref_count(container); ! if (exp < 0 || cont < 0) return NULL; ! min = (exp < cont) ? exp : cont; while (min >= 0) { ! 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(expr, exp - min, '-', buf, sizeof(buf)); if (ret < 0) return NULL; n = 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 *ret, *shared; bool star; int cnt; ! expr = strip_expr(expr); ! container = strip_expr(container); ! ! ret = get_stored_container_name(container, expr); ! if (ret) ! return ret; ! sym = expr_to_sym(expr); ! container_sym = expr_to_sym(container); ! if (sym && sym == container_sym) goto found; cnt = 0; ! while ((tmp = get_assigned_expr(container))) { ! container = strip_expr(tmp); if (cnt++ > 3) break; } cnt = 0; ! while ((tmp = get_assigned_expr(expr))) { ! expr = strip_expr(tmp); if (cnt++ > 3) break; } found: ! ! if (container->type == EXPR_DEREF) star = true; ! else star = false; ! 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) return NULL; + container_sym = expr_to_sym(container); + if (!container_sym || sym != container_sym) + return NULL; ! 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, *tmp; ! bool found = false; ! int fn_param, param; ! char buf[32]; char *name; /* * We're trying to link the function with the parameter. There are a * couple ways this can be passed: * foo->func(foo, ...);
*** 412,432 **** param = -1; FOR_EACH_PTR(call->args, arg) { param++; ! name = get_container_name(fn, arg); if (!name) continue; sql_insert_caller_info(call, CONTAINER, param, name, "$(-1)"); } 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)); } struct db_info { struct symbol *arg; int prev_offset; --- 324,374 ---- param = -1; FOR_EACH_PTR(call->args, arg) { param++; ! 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) { ! 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,503 **** snprintf(fullname, sizeof(fullname), "*%s", name); return fullname; } member = get_member_from_offset(arg, offset); ! if (!member) return NULL; snprintf(fullname, sizeof(fullname), "%s->%s", name, member->ident->name); return fullname; } --- 435,445 ---- snprintf(fullname, sizeof(fullname), "*%s", name); return fullname; } member = get_member_from_offset(arg, offset); ! if (!member || !member->ident) return NULL; snprintf(fullname, sizeof(fullname), "%s->%s", name, member->ident->name); return fullname; }
*** 603,622 **** 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; bool star = 0; if (p[0] == '*') { star = 1; p += 2; } if (!get_toplevel_mtag(cur_func_sym, &cur_tag)) return; while (true) { container_offset = strtoul(p, &p, 0); --- 545,575 ---- static void load_container_data(struct symbol *arg, const char *info) { mtag_t cur_tag, container_tag, arg_tag; int container_offset, arg_offset; 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,695 **** 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) { --- 626,636 ----