Print this page
12166 resync smatch to 0.6.1-rc1-il-3
*** 25,36 ****
--- 25,40 ----
struct sqlite3 *smatch_db;
struct sqlite3 *mem_db;
struct sqlite3 *cache_db;
+ int debug_db;
+
static int return_id;
+ static void call_return_state_hooks(struct expression *expr);
+
#define SQLITE_CACHE_PAGES 1000
struct def_callback {
int hook_type;
void (*callback)(const char *name, struct symbol *sym, char *key, char *value);
*** 103,113 ****
{
int i;
for (i = 0; i < argc; i++) {
if (i != 0)
! printf(", ");
sm_printf("%s", argv[i]);
}
sm_printf("\n");
return 0;
}
--- 107,117 ----
{
int i;
for (i = 0; i < argc; i++) {
if (i != 0)
! sm_printf(", ");
sm_printf("%s", argv[i]);
}
sm_printf("\n");
return 0;
}
*** 118,128 ****
int rc;
if (!db)
return;
! if (option_debug) {
sm_msg("%s", sql);
if (strncasecmp(sql, "select", strlen("select")) == 0)
sqlite3_exec(db, sql, print_sql_output, NULL, NULL);
}
--- 122,132 ----
int rc;
if (!db)
return;
! if (option_debug || debug_db) {
sm_msg("%s", sql);
if (strncasecmp(sql, "select", strlen("select")) == 0)
sqlite3_exec(db, sql, print_sql_output, NULL, NULL);
}
*** 799,808 ****
--- 803,867 ----
return 1;
p = next;
}
}
+ char *sm_to_arg_name(struct expression *expr, struct sm_state *sm)
+ {
+ struct symbol *sym;
+ const char *sm_name;
+ char *name;
+ bool is_address = false;
+ bool add_star = false;
+ char buf[256];
+ char *ret = NULL;
+ int len;
+
+ expr = strip_expr(expr);
+ if (!expr)
+ return NULL;
+
+ if (expr->type == EXPR_PREOP && expr->op == '&') {
+ expr = strip_expr(expr->unop);
+ is_address = true;
+ }
+
+ name = expr_to_var_sym(expr, &sym);
+ if (!name || !sym)
+ goto free;
+ if (sym != sm->sym)
+ goto free;
+
+ sm_name = sm->name;
+ add_star = false;
+ if (sm_name[0] == '*') {
+ add_star = true;
+ sm_name++;
+ }
+
+ len = strlen(name);
+ if (strncmp(name, sm_name, len) != 0)
+ goto free;
+ if (sm_name[len] == '\0') {
+ snprintf(buf, sizeof(buf), "%s%s$",
+ add_star ? "*" : "", is_address ? "*" : "");
+ } else {
+ if (sm_name[len] != '.' && sm_name[len] != '-')
+ goto free;
+ if (sm_name[len] == '-')
+ len++;
+ // FIXME does is_address really imply that sm_name[len] == '-'
+ snprintf(buf, sizeof(buf), "%s$->%s", add_star ? "*" : "",
+ sm_name + len);
+ }
+
+ ret = alloc_sname(buf);
+ free:
+ free_string(name);
+ return ret;
+ }
+
static void print_struct_members(struct expression *call, struct expression *expr, int param, int offset, 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;
*** 1415,1459 ****
static void match_return_info(int return_id, char *return_ranges, struct expression *expr)
{
sql_insert_return_states(return_id, return_ranges, INTERNAL, -1, "", function_signature());
}
! static void call_return_state_hooks_conditional(struct expression *expr)
{
- struct returned_state_callback *cb;
- struct range_list *rl;
- const char *return_ranges;
int final_pass_orig = final_pass;
__push_fake_cur_stree();
final_pass = 0;
__split_whole_condition(expr->conditional);
final_pass = final_pass_orig;
! return_ranges = get_return_ranges_str(expr->cond_true ?: expr->conditional, &rl);
- set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(rl));
-
- return_id++;
- FOR_EACH_PTR(returned_state_callbacks, cb) {
- cb->callback(return_id, (char *)return_ranges, expr->cond_true);
- } END_FOR_EACH_PTR(cb);
-
__push_true_states();
__use_false_states();
! return_ranges = get_return_ranges_str(expr->cond_false, &rl);
! set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(rl));
- return_id++;
- FOR_EACH_PTR(returned_state_callbacks, cb) {
- cb->callback(return_id, (char *)return_ranges, expr->cond_false);
- } END_FOR_EACH_PTR(cb);
-
__merge_true_states();
__free_fake_cur_stree();
}
static void call_return_state_hooks_compare(struct expression *expr)
{
struct returned_state_callback *cb;
--- 1474,1514 ----
static void match_return_info(int return_id, char *return_ranges, struct expression *expr)
{
sql_insert_return_states(return_id, return_ranges, INTERNAL, -1, "", function_signature());
}
! static bool call_return_state_hooks_conditional(struct expression *expr)
{
int final_pass_orig = final_pass;
+ static int recurse;
+ if (recurse >= 2)
+ return false;
+ if (!expr ||
+ (expr->type != EXPR_CONDITIONAL && expr->type != EXPR_SELECT))
+ return false;
+
+ recurse++;
+
__push_fake_cur_stree();
final_pass = 0;
__split_whole_condition(expr->conditional);
final_pass = final_pass_orig;
! call_return_state_hooks(expr->cond_true ?: expr->conditional);
__push_true_states();
__use_false_states();
! call_return_state_hooks(expr->cond_false);
__merge_true_states();
__free_fake_cur_stree();
+
+ recurse--;
+ return true;
}
static void call_return_state_hooks_compare(struct expression *expr)
{
struct returned_state_callback *cb;
*** 1534,1545 ****
--- 1589,1604 ----
/* bail if it gets too complicated */
nr_possible = 0;
FOR_EACH_PTR(sm->possible, tmp) {
if (tmp->merged)
continue;
+ if (ptr_in_list(tmp, already_handled))
+ continue;
+ add_ptr_list(&already_handled, tmp);
nr_possible++;
} END_FOR_EACH_PTR(tmp);
+ free_slist(&already_handled);
nr_states = get_db_state_count();
if (nr_states * nr_possible >= 2000)
return 0;
FOR_EACH_PTR(sm->possible, tmp) {
*** 1591,1600 ****
--- 1650,1662 ----
static bool has_possible_negative(struct sm_state *sm)
{
struct sm_state *tmp;
+ if (!type_signed(estate_type(sm->state)))
+ return false;
+
FOR_EACH_PTR(sm->possible, tmp) {
if (!estate_rl(tmp->state))
continue;
if (sval_is_negative(estate_min(tmp->state)) &&
sval_is_negative(estate_max(tmp->state)))
*** 1602,1612 ****
} END_FOR_EACH_PTR(tmp);
return false;
}
! static bool has_possible_zero_null(struct sm_state *sm)
{
struct sm_state *tmp;
sval_t sval;
FOR_EACH_PTR(sm->possible, tmp) {
--- 1664,1674 ----
} END_FOR_EACH_PTR(tmp);
return false;
}
! static bool has_separate_zero_null(struct sm_state *sm)
{
struct sm_state *tmp;
sval_t sval;
FOR_EACH_PTR(sm->possible, tmp) {
*** 1624,1644 ****
struct sm_state *sm;
struct returned_state_callback *cb;
struct range_list *rl;
const char *return_ranges;
struct range_list *ret_rl;
int undo;
- bool has_zero;
/* We're going to print the states 3 times */
if (get_db_state_count() > 10000 / 3)
return 0;
if (!get_implied_rl(expr, &rl) || !rl)
return 0;
- if (is_whole_rl(rl) || is_whole_rl_non_zero(rl))
- return 0;
/* Forget about INT_MAX and larger */
if (rl_max(rl).value <= 0)
return 0;
if (!sval_is_negative(rl_min(rl)))
return 0;
--- 1686,1704 ----
struct sm_state *sm;
struct returned_state_callback *cb;
struct range_list *rl;
const char *return_ranges;
struct range_list *ret_rl;
+ bool separate_zero;
int undo;
/* We're going to print the states 3 times */
if (get_db_state_count() > 10000 / 3)
return 0;
if (!get_implied_rl(expr, &rl) || !rl)
return 0;
/* Forget about INT_MAX and larger */
if (rl_max(rl).value <= 0)
return 0;
if (!sval_is_negative(rl_min(rl)))
return 0;
*** 1646,1658 ****
sm = get_sm_state_expr(SMATCH_EXTRA, expr);
if (!sm)
return 0;
if (!has_possible_negative(sm))
return 0;
! has_zero = has_possible_zero_null(sm);
! if (!assume(compare_expression(expr, has_zero ? '>' : SPECIAL_GTE, zero_expr())))
return 0;
return_id++;
return_ranges = get_return_ranges_str(expr, &ret_rl);
set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
--- 1706,1718 ----
sm = get_sm_state_expr(SMATCH_EXTRA, expr);
if (!sm)
return 0;
if (!has_possible_negative(sm))
return 0;
! separate_zero = has_separate_zero_null(sm);
! if (!assume(compare_expression(expr, separate_zero ? '>' : SPECIAL_GTE, zero_expr())))
return 0;
return_id++;
return_ranges = get_return_ranges_str(expr, &ret_rl);
set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
*** 1660,1670 ****
cb->callback(return_id, (char *)return_ranges, expr);
} END_FOR_EACH_PTR(cb);
end_assume();
! if (has_zero) {
undo = assume(compare_expression(expr, SPECIAL_EQUAL, zero_expr()));
return_id++;
return_ranges = get_return_ranges_str(expr, &ret_rl);
set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
--- 1720,1730 ----
cb->callback(return_id, (char *)return_ranges, expr);
} END_FOR_EACH_PTR(cb);
end_assume();
! if (separate_zero) {
undo = assume(compare_expression(expr, SPECIAL_EQUAL, zero_expr()));
return_id++;
return_ranges = get_return_ranges_str(expr, &ret_rl);
set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
*** 1717,1727 ****
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_zero_null(sm))
return 0;
nr_states = get_db_state_count();
if (option_info && nr_states >= 1500)
return 0;
--- 1777,1787 ----
state = sm->state;
if (!estate_rl(state))
return 0;
if (estate_min(state).value == 0 && estate_max(state).value == 0)
return 0;
! if (!has_separate_zero_null(sm))
return 0;
nr_states = get_db_state_count();
if (option_info && nr_states >= 1500)
return 0;
*** 1759,1768 ****
--- 1819,1859 ----
__free_fake_cur_stree();
return 1;
}
+ static bool is_kernel_success_fail(struct sm_state *sm)
+ {
+ struct sm_state *tmp;
+ struct range_list *rl;
+ bool has_zero = false;
+ bool has_neg = false;
+
+ if (!type_signed(estate_type(sm->state)))
+ return false;
+
+ FOR_EACH_PTR(sm->possible, tmp) {
+ rl = estate_rl(tmp->state);
+ if (!rl)
+ return false;
+ if (rl_min(rl).value == 0 && rl_max(rl).value == 0) {
+ has_zero = true;
+ continue;
+ }
+ has_neg = true;
+ if (rl_min(rl).value >= -4095 && rl_max(rl).value < 0)
+ continue;
+ if (strcmp(tmp->state->name, "s32min-(-1)") == 0)
+ continue;
+ if (strcmp(tmp->state->name, "s32min-(-1),1-s32max") == 0)
+ continue;
+ return false;
+ } END_FOR_EACH_PTR(tmp);
+
+ return has_zero && has_neg;
+ }
+
static int call_return_state_hooks_split_success_fail(struct expression *expr)
{
struct sm_state *sm;
struct range_list *rl;
struct range_list *nonzero_rl;
*** 1775,1804 ****
if (option_project != PROJ_KERNEL)
return 0;
nr_states = get_db_state_count();
! if (nr_states > 1500)
return 0;
sm = get_sm_state_expr(SMATCH_EXTRA, expr);
if (!sm)
return 0;
if (ptr_list_size((struct ptr_list *)sm->possible) == 1)
return 0;
rl = estate_rl(sm->state);
if (!rl)
return 0;
- if (rl_min(rl).value < -4095 || rl_min(rl).value >= 0)
- return 0;
- if (rl_max(rl).value != 0)
- return 0;
- if (!has_possible_zero_null(sm))
- return 0;
-
__push_fake_cur_stree();
final_pass = 0;
__split_whole_condition(expr);
final_pass = final_pass_orig;
--- 1866,1890 ----
if (option_project != PROJ_KERNEL)
return 0;
nr_states = get_db_state_count();
! if (nr_states > 2000)
return 0;
sm = get_sm_state_expr(SMATCH_EXTRA, expr);
if (!sm)
return 0;
if (ptr_list_size((struct ptr_list *)sm->possible) == 1)
return 0;
+ if (!is_kernel_success_fail(sm))
+ return 0;
rl = estate_rl(sm->state);
if (!rl)
return 0;
__push_fake_cur_stree();
final_pass = 0;
__split_whole_condition(expr);
final_pass = final_pass_orig;
*** 1840,1858 ****
if (rl_min(rl).value == 0 && rl_max(rl).value == 1)
return 1;
return 0;
}
- static int is_conditional(struct expression *expr)
- {
- if (!expr)
- return 0;
- if (expr->type == EXPR_CONDITIONAL || expr->type == EXPR_SELECT)
- return 1;
- return 0;
- }
-
static int splitable_function_call(struct expression *expr)
{
struct sm_state *sm;
char buf[64];
--- 1926,1935 ----
*** 1906,1930 ****
struct returned_state_callback *cb;
struct range_list *ret_rl;
const char *return_ranges;
struct sm_state *tmp;
int ret = 0;
- int nr_possible, nr_states;
struct state_list *already_handled = NULL;
if (!sm || !sm->merged)
return 0;
if (too_many_possible(sm))
return 0;
- /* bail if it gets too complicated */
- nr_possible = ptr_list_size((struct ptr_list *)sm->possible);
- nr_states = get_db_state_count();
- if (nr_states * nr_possible >= 2000)
- return 0;
-
FOR_EACH_PTR(sm->possible, tmp) {
if (tmp->merged)
continue;
if (ptr_in_list(tmp, already_handled))
continue;
--- 1983,2000 ----
*** 1959,1978 ****
if (!start_sm)
return 0;
sm = get_sm_state(SMATCH_EXTRA, start_sm->name, start_sm->sym);
if (!sm || estate_get_single_value(sm->state, &sval))
return 0;
return split_on_bool_sm(sm, expr);
}
static int split_by_null_nonnull_param(struct expression *expr)
{
struct symbol *arg;
struct sm_state *sm;
! sval_t zero = {
! .type = &ulong_ctype,
! };
/* function must only take one pointer */
if (ptr_list_size((struct ptr_list *)cur_func_sym->ctype.base_type->arguments) != 1)
return 0;
arg = first_ptr_list((struct ptr_list *)cur_func_sym->ctype.base_type->arguments);
--- 2029,2050 ----
if (!start_sm)
return 0;
sm = get_sm_state(SMATCH_EXTRA, start_sm->name, start_sm->sym);
if (!sm || estate_get_single_value(sm->state, &sval))
return 0;
+
+ if (get_db_state_count() * 2 >= 2000)
+ return 0;
+
return split_on_bool_sm(sm, expr);
}
static int split_by_null_nonnull_param(struct expression *expr)
{
struct symbol *arg;
struct sm_state *sm;
! int nr_possible;
/* function must only take one pointer */
if (ptr_list_size((struct ptr_list *)cur_func_sym->ctype.base_type->arguments) != 1)
return 0;
arg = first_ptr_list((struct ptr_list *)cur_func_sym->ctype.base_type->arguments);
*** 1985,1997 ****
return 0;
sm = get_sm_state(SMATCH_EXTRA, arg->ident->name, arg);
if (!sm)
return 0;
! if (!rl_has_sval(estate_rl(sm->state), zero))
return 0;
return split_on_bool_sm(sm, expr);
}
struct expression *strip_expr_statement(struct expression *expr)
{
--- 2057,2073 ----
return 0;
sm = get_sm_state(SMATCH_EXTRA, arg->ident->name, arg);
if (!sm)
return 0;
! if (!has_separate_zero_null(sm))
return 0;
+ nr_possible = ptr_list_size((struct ptr_list *)sm->possible);
+ if (get_db_state_count() * nr_possible >= 2000)
+ return 0;
+
return split_on_bool_sm(sm, expr);
}
struct expression *strip_expr_statement(struct expression *expr)
{
*** 2036,2047 ****
if (expr && (expr->type == EXPR_COMPARE ||
!get_implied_value(expr, &sval)) &&
(is_condition(expr) || is_boolean(expr))) {
call_return_state_hooks_compare(expr);
return;
! } else if (is_conditional(expr)) {
! call_return_state_hooks_conditional(expr);
return;
} else if (call_return_state_hooks_split_possible(expr)) {
return;
} else if (split_positive_from_negative(expr)) {
return;
--- 2112,2122 ----
if (expr && (expr->type == EXPR_COMPARE ||
!get_implied_value(expr, &sval)) &&
(is_condition(expr) || is_boolean(expr))) {
call_return_state_hooks_compare(expr);
return;
! } else if (call_return_state_hooks_conditional(expr)) {
return;
} else if (call_return_state_hooks_split_possible(expr)) {
return;
} else if (split_positive_from_negative(expr)) {
return;
*** 2490,2500 ****
char *get_variable_from_key(struct expression *arg, const char *key, struct symbol **sym)
{
char buf[256];
char *tmp;
! bool add_star = false;
if (!arg)
return NULL;
arg = strip_expr(arg);
--- 2565,2575 ----
char *get_variable_from_key(struct expression *arg, const char *key, struct symbol **sym)
{
char buf[256];
char *tmp;
! int star_cnt = 0;
if (!arg)
return NULL;
arg = strip_expr(arg);
*** 2514,2542 ****
free_string(tmp);
return alloc_string(buf);
}
}
! if (key[0] == '*') {
! add_star = true;
key++;
}
if (arg->type == EXPR_PREOP && arg->op == '&') {
arg = strip_expr(arg->unop);
tmp = expr_to_var_sym(arg, sym);
if (!tmp)
return NULL;
! snprintf(buf, sizeof(buf), "%s%s.%s",
! add_star ? "*" : "", tmp, key + 3);
return alloc_string(buf);
}
tmp = expr_to_var_sym(arg, sym);
if (!tmp)
return NULL;
! snprintf(buf, sizeof(buf), "%s%s%s", add_star ? "*" : "", tmp, key + 1);
free_string(tmp);
return alloc_string(buf);
}
char *get_chunk_from_key(struct expression *arg, char *key, struct symbol **sym, struct var_sym_list **vsl)
--- 2589,2622 ----
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 == '&') {
arg = strip_expr(arg->unop);
tmp = expr_to_var_sym(arg, sym);
if (!tmp)
return NULL;
! snprintf(buf, sizeof(buf), "%.*s%s.%s",
! star_cnt, "**********", tmp, key + 3);
return alloc_string(buf);
}
tmp = expr_to_var_sym(arg, sym);
if (!tmp)
return NULL;
! snprintf(buf, sizeof(buf), "%.*s%s%s", star_cnt, "**********", tmp, key + 1);
free_string(tmp);
return alloc_string(buf);
}
char *get_chunk_from_key(struct expression *arg, char *key, struct symbol **sym, struct var_sym_list **vsl)
*** 2548,2577 ****
return get_variable_from_key(arg, key, sym);
}
const char *state_name_to_param_name(const char *state_name, const char *param_name)
{
int name_len;
! static char buf[256];
! bool add_star = false;
name_len = strlen(param_name);
! if (state_name[0] == '*') {
! add_star = true;
state_name++;
}
if (strcmp(state_name, param_name) == 0) {
! snprintf(buf, sizeof(buf), "%s$", add_star ? "*" : "");
return alloc_sname(buf);
}
if (state_name[name_len] == '-' && /* check for '-' from "->" */
strncmp(state_name, param_name, name_len) == 0) {
! snprintf(buf, sizeof(buf), "%s$%s",
! add_star ? "*" : "", state_name + name_len);
return alloc_sname(buf);
}
return NULL;
}
--- 2628,2660 ----
return get_variable_from_key(arg, key, sym);
}
const char *state_name_to_param_name(const char *state_name, const char *param_name)
{
+ int star_cnt = 0;
int name_len;
! char buf[256];
name_len = strlen(param_name);
! while (state_name[0] == '*') {
! star_cnt++;
state_name++;
}
+ /* ten out of ten stars! */
+ if (star_cnt > 10)
+ return NULL;
+
if (strcmp(state_name, param_name) == 0) {
! snprintf(buf, sizeof(buf), "%.*s$", star_cnt, "**********");
return alloc_sname(buf);
}
if (state_name[name_len] == '-' && /* check for '-' from "->" */
strncmp(state_name, param_name, name_len) == 0) {
! snprintf(buf, sizeof(buf), "%.*s$%s", star_cnt, "**********", state_name + name_len);
return alloc_sname(buf);
}
return NULL;
}