From 04d560015ac891d5ac30869b9b3bc18863f1bfdd Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 13 Feb 2018 16:59:53 +0300 Subject: [PATCH] user_data: silence some false positives with divides Say we have "capped_user_data / unknown_trusted_value" then the result is unknown. And so we mark it as whole range user data. That's not very useful. Let's instead just mark it as trusted. Signed-off-by: Dan Carpenter --- check_user_data2.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/check_user_data2.c b/check_user_data2.c index 1c4b25a6..332fb2a5 100644 --- a/check_user_data2.c +++ b/check_user_data2.c @@ -678,6 +678,7 @@ static int db_returned_user_rl(struct expression *call, struct range_list **rl) } static int user_data_flag; +static int no_user_data_flag; static struct range_list *var_user_rl(struct expression *expr) { struct smatch_state *state; @@ -694,6 +695,34 @@ static struct range_list *var_user_rl(struct expression *expr) goto found; } + if (expr->type == EXPR_BINOP && expr->op == '/') { + struct range_list *left = NULL; + struct range_list *right = NULL; + struct range_list *abs_right; + + /* + * The specific bug I'm dealing with is: + * + * foo = capped_user / unknown; + * + * Instead of just saying foo is now entirely user_rl we should + * probably say instead that it is not at all user data. + * + */ + + get_user_rl(expr->left, &left); + get_user_rl(expr->right, &right); + get_absolute_rl(expr->right, &abs_right); + + if (left && !right) { + rl = rl_binop(left, '/', abs_right); + if (sval_cmp(rl_max(left), rl_max(rl)) < 0) + no_user_data_flag = 1; + } + + return NULL; + } + if (get_user_macro_rl(expr, &rl)) goto found; @@ -722,8 +751,9 @@ int get_user_rl(struct expression *expr, struct range_list **rl) { user_data_flag = 0; + no_user_data_flag = 0; custom_get_absolute_rl(expr, &var_user_rl, rl); - if (!user_data_flag || !*rl) { + if (!user_data_flag || no_user_data_flag || !*rl) { *rl = NULL; return 0; } -- 2.11.4.GIT