Print this page
11506 smatch resync
@@ -137,10 +137,20 @@
cb = alloc_fcall_back(RANGED_CALL, call_back, info);
cb->range = alloc_range_perm(ll_to_sval(start), ll_to_sval(end));
add_callback(func_hash, look_for, cb);
}
+void return_implies_state_sval(const char *look_for, sval_t start, sval_t end,
+ implication_hook *call_back, void *info)
+{
+ struct fcall_back *cb;
+
+ cb = alloc_fcall_back(RANGED_CALL, call_back, info);
+ cb->range = alloc_range_perm(start, end);
+ add_callback(func_hash, look_for, cb);
+}
+
void select_return_states_hook(int type, return_implies_hook *callback)
{
struct return_implies_callback *cb = __alloc_return_implies_callback(0);
cb->type = type;
@@ -244,10 +254,11 @@
struct smatch_state *estate;
struct stree *tmp_stree;
struct stree *final_states = NULL;
struct range_list *handled_ranges = NULL;
struct call_back_list *same_range_call_backs = NULL;
+ struct range_list *rl;
int handled = 0;
if (!call_backs)
return 0;
@@ -266,11 +277,13 @@
same_range_call_backs = get_same_ranged_call_backs(call_backs, tmp->range);
call_ranged_call_backs(same_range_call_backs, fn, expr->right, expr);
__free_ptr_list((struct ptr_list **)&same_range_call_backs);
- estate = alloc_estate_range(tmp->range->min, tmp->range->max);
+ rl = alloc_rl(tmp->range->min, tmp->range->max);
+ rl = cast_rl(get_type(expr->left), rl);
+ estate = alloc_estate_rl(rl);
set_extra_mod(var_name, sym, expr->left, estate);
tmp_stree = __pop_fake_cur_stree();
merge_fake_stree(&final_states, tmp_stree);
free_stree(&tmp_stree);
@@ -360,11 +373,11 @@
db_info->ret_state = state;
}
static bool fake_a_param_assignment(struct expression *expr, const char *return_str)
{
- struct expression *arg, *left, *right, *fake_assign;
+ struct expression *arg, *left, *right, *tmp, *fake_assign;
char *p;
int param;
char buf[256];
char *str;
@@ -400,10 +413,16 @@
*p = '\0';
arg = get_argument_from_call_expr(right->args, param);
if (!arg)
return false;
+
+ /* There should be a get_other_name() function which returns an expr */
+ tmp = get_assigned_expr(arg);
+ if (tmp)
+ arg = tmp;
+
/*
* This is a sanity check to prevent side effects from evaluating stuff
* twice.
*/
str = expr_to_chunk_sym_vsl(arg, NULL, NULL);
@@ -419,12 +438,13 @@
__split_expr(fake_assign);
__in_fake_parameter_assign--;
return true;
}
-static void set_return_state(struct expression *expr, struct db_callback_info *db_info)
+static void set_return_assign_state(struct db_callback_info *db_info)
{
+ struct expression *expr = db_info->expr->left;
struct smatch_state *state;
if (!db_info->ret_state)
return;
@@ -433,10 +453,24 @@
db_info->ret_state = NULL;
fake_a_param_assignment(db_info->expr, db_info->ret_str);
db_info->ret_str = NULL;
}
+static void set_other_side_state(struct db_callback_info *db_info)
+{
+ struct expression *expr = db_info->var_expr;
+ struct smatch_state *state;
+
+ if (!db_info->ret_state)
+ return;
+
+ state = alloc_estate_rl(cast_rl(get_type(expr), clone_rl(estate_rl(db_info->ret_state))));
+ set_extra_expr_nomod(expr, state);
+ db_info->ret_state = NULL;
+ db_info->ret_str = NULL;
+}
+
static void handle_ret_equals_param(char *ret_string, struct range_list *rl, struct expression *call)
{
char *str;
long long param;
struct expression *arg;
@@ -559,28 +593,29 @@
{
struct db_callback_info *db_info = _info;
struct range_list *var_rl = db_info->rl;
struct range_list *ret_range;
int type, param;
- char *key, *value;
+ char *ret_str, *key, *value;
struct return_implies_callback *tmp;
struct stree *stree;
int return_id;
int comparison;
if (argc != 6)
return 0;
return_id = atoi(argv[0]);
+ ret_str = argv[1];
type = atoi(argv[2]);
param = atoi(argv[3]);
key = argv[4];
value = argv[5];
db_info->has_states = 1;
if (db_info->prev_return_id != -1 && type == INTERNAL) {
- set_return_state(db_info->var_expr, db_info);
+ set_other_side_state(db_info);
stree = __pop_fake_cur_stree();
if (!db_info->cull)
merge_fake_stree(&db_info->stree, stree);
free_stree(&stree);
@@ -601,11 +636,11 @@
if (is_impossible_data(type, db_info->expr, param, key, value)) {
db_info->cull = 1;
return 0;
}
- call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), argv[1], &ret_range);
+ call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), ret_str, &ret_range);
ret_range = cast_rl(get_type(db_info->expr), ret_range);
if (!ret_range)
ret_range = alloc_whole_rl(get_type(db_info->expr));
comparison = db_info->comparison;
@@ -626,17 +661,17 @@
param_limit_implications(db_info->expr, param, key, value);
filter_by_comparison(&var_rl, negate_comparison(comparison), ret_range);
filter_by_comparison(&ret_range, flip_comparison(negate_comparison(comparison)), var_rl);
}
- handle_ret_equals_param(argv[1], ret_range, db_info->expr);
+ handle_ret_equals_param(ret_str, ret_range, db_info->expr);
if (type == INTERNAL) {
set_state(-1, "unnull_path", NULL, &true_state);
- __add_return_comparison(strip_expr(db_info->expr), argv[1]);
- __add_return_to_param_mapping(db_info->expr, argv[1]);
- store_return_state(db_info, argv[1], alloc_estate_rl(clone_rl(var_rl)));
+ __add_return_comparison(strip_expr(db_info->expr), ret_str);
+ __add_return_to_param_mapping(db_info->expr, ret_str);
+ store_return_state(db_info, ret_str, alloc_estate_rl(clone_rl(var_rl)));
}
FOR_EACH_PTR(db_info->callbacks, tmp) {
if (tmp->type == type)
tmp->callback(db_info->expr, param, key, value);
@@ -685,16 +720,14 @@
db_info.stree = NULL;
db_info.prev_return_id = -1;
__push_fake_cur_stree();
sql_select_return_states("return_id, return, type, parameter, key, value",
call_expr, db_compare_callback, &db_info);
- set_return_state(db_info.var_expr, &db_info);
+ set_other_side_state(&db_info);
stree = __pop_fake_cur_stree();
- if (!db_info.cull) {
- set_return_state(db_info.var_expr, &db_info);
+ if (!db_info.cull)
merge_fake_stree(&db_info.stree, stree);
- }
free_stree(&stree);
true_states = db_info.stree;
if (!true_states && db_info.has_states) {
__push_fake_cur_stree();
set_path_impossible();
@@ -712,15 +745,14 @@
db_info.prev_return_id = -1;
db_info.cull = 0;
__push_fake_cur_stree();
sql_select_return_states("return_id, return, type, parameter, key, value", call_expr,
db_compare_callback, &db_info);
+ set_other_side_state(&db_info);
stree = __pop_fake_cur_stree();
- if (!db_info.cull) {
- set_return_state(db_info.var_expr, &db_info);
+ if (!db_info.cull)
merge_fake_stree(&db_info.stree, stree);
- }
free_stree(&stree);
false_states = db_info.stree;
if (!false_states && db_info.has_states) {
__push_fake_cur_stree();
set_path_impossible();
@@ -804,47 +836,44 @@
fn = expr->fn->symbol_name->name;
call_backs = search_callback(func_hash, fn);
FOR_EACH_PTR(call_backs, tmp) {
- struct range_list *range_rl = NULL;
+ struct range_list *range_rl;
if (tmp->type != RANGED_CALL)
continue;
- add_range(&range_rl, tmp->range->min, tmp->range->max);
+ range_rl = alloc_rl(tmp->range->min, tmp->range->max);
range_rl = cast_rl(estate_type(db_info->ret_state), range_rl);
- if (possibly_true_rl(range_rl, SPECIAL_EQUAL, estate_rl(db_info->ret_state))) {
- if (!possibly_true_rl(rl_invert(range_rl), SPECIAL_EQUAL, estate_rl(db_info->ret_state)))
+ if (possibly_true_rl(range_rl, SPECIAL_EQUAL, estate_rl(db_info->ret_state)))
(tmp->u.ranged)(fn, expr, db_info->expr, tmp->info);
- else
- db_info->handled = -1;
- }
} END_FOR_EACH_PTR(tmp);
}
static int db_assign_return_states_callback(void *_info, int argc, char **argv, char **azColName)
{
struct db_callback_info *db_info = _info;
struct range_list *ret_range;
int type, param;
- char *key, *value;
+ char *ret_str, *key, *value;
struct return_implies_callback *tmp;
struct stree *stree;
int return_id;
if (argc != 6)
return 0;
return_id = atoi(argv[0]);
+ ret_str = argv[1];
type = atoi(argv[2]);
param = atoi(argv[3]);
key = argv[4];
value = argv[5];
if (db_info->prev_return_id != -1 && type == INTERNAL) {
call_ranged_return_hooks(db_info);
- set_return_state(db_info->expr->left, db_info);
+ set_return_assign_state(db_info);
stree = __pop_fake_cur_stree();
if (!db_info->cull)
merge_fake_stree(&db_info->stree, stree);
free_stree(&stree);
__push_fake_cur_stree();
@@ -867,21 +896,21 @@
if (type == PARAM_LIMIT)
param_limit_implications(db_info->expr, param, key, value);
db_info->handled = 1;
- call_results_to_rl(db_info->expr->right, get_type(strip_expr(db_info->expr->right)), argv[1], &ret_range);
+ call_results_to_rl(db_info->expr->right, get_type(strip_expr(db_info->expr->right)), ret_str, &ret_range);
if (!ret_range)
ret_range = alloc_whole_rl(get_type(strip_expr(db_info->expr->right)));
ret_range = cast_rl(get_type(db_info->expr->right), ret_range);
if (type == INTERNAL) {
set_state(-1, "unnull_path", NULL, &true_state);
- __add_return_comparison(strip_expr(db_info->expr->right), argv[1]);
- __add_comparison_info(db_info->expr->left, strip_expr(db_info->expr->right), argv[1]);
- __add_return_to_param_mapping(db_info->expr, argv[1]);
- store_return_state(db_info, argv[1], alloc_estate_rl(ret_range));
+ __add_return_comparison(strip_expr(db_info->expr->right), ret_str);
+ __add_comparison_info(db_info->expr->left, strip_expr(db_info->expr->right), ret_str);
+ __add_return_to_param_mapping(db_info->expr, ret_str);
+ store_return_state(db_info, ret_str, alloc_estate_rl(ret_range));
}
FOR_EACH_PTR(db_return_states_list, tmp) {
if (tmp->type == type)
tmp->callback(db_info->expr, param, key, value);
@@ -915,11 +944,11 @@
db_info.prev_return_id,
db_info.ret_state ? db_info.ret_state->name : "'<empty>'");
}
if (db_info.handled)
call_ranged_return_hooks(&db_info);
- set_return_state(db_info.expr->left, &db_info);
+ set_return_assign_state(&db_info);
stree = __pop_fake_cur_stree();
if (!db_info.cull)
merge_fake_stree(&db_info.stree, stree);
free_stree(&stree);
@@ -1009,20 +1038,21 @@
static int db_return_states_callback(void *_info, int argc, char **argv, char **azColName)
{
struct db_callback_info *db_info = _info;
struct range_list *ret_range;
int type, param;
- char *key, *value;
+ char *ret_str, *key, *value;
struct return_implies_callback *tmp;
struct stree *stree;
int return_id;
char buf[64];
if (argc != 6)
return 0;
return_id = atoi(argv[0]);
+ ret_str = argv[1];
type = atoi(argv[2]);
param = atoi(argv[3]);
key = argv[4];
value = argv[5];
@@ -1051,17 +1081,17 @@
}
if (type == PARAM_LIMIT)
param_limit_implications(db_info->expr, param, key, value);
- call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), argv[1], &ret_range);
+ call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), ret_str, &ret_range);
ret_range = cast_rl(get_type(db_info->expr), ret_range);
if (type == INTERNAL) {
set_state(-1, "unnull_path", NULL, &true_state);
- __add_return_comparison(strip_expr(db_info->expr), argv[1]);
- __add_return_to_param_mapping(db_info->expr, argv[1]);
+ __add_return_comparison(strip_expr(db_info->expr), ret_str);
+ __add_return_to_param_mapping(db_info->expr, ret_str);
}
FOR_EACH_PTR(db_return_states_list, tmp) {
if (tmp->type == type)