From 8a14f53700f8a1d74eb2debd8bcd8ebd20fed12d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 Mar 2013 14:13:19 +0300 Subject: [PATCH] conditions: fix small signedness bug in compares If I recall correctly, we always get signed comparisons here and manually change them to SPECIAL_UNSIGNED_ as needed. In comparisons the type is promoted to whichever side has more positive bits. So a comparison between and int and a unsigned char is signed. In the original code it would have been treated as unsigned. I've updated check_signed.c to match. Signed-off-by: Dan Carpenter --- check_signed.c | 16 ++++++++++------ smatch_conditions.c | 33 ++++++++++++++++----------------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/check_signed.c b/check_signed.c index 2500ed1c..a621799c 100644 --- a/check_signed.c +++ b/check_signed.c @@ -87,8 +87,6 @@ static int cap_gt_zero_and_lt(struct expression *expr) if (!get_value(expr->right, &known) || known.value != 0) return 0; - if (expr->op != SPECIAL_UNSIGNED_GT && expr->op != SPECIAL_UNSIGNED_GTE) - return 0; i = 0; FOR_EACH_PTR_REVERSE(big_expression_stack, tmp) { @@ -137,8 +135,6 @@ static int cap_lt_zero_or_gt(struct expression *expr) if (!get_value(expr->right, &known) || known.value != 0) return 0; - if (expr->op != SPECIAL_UNSIGNED_LT && expr->op != SPECIAL_UNSIGNED_LTE) - return 0; i = 0; FOR_EACH_PTR_REVERSE(big_expression_stack, tmp) { @@ -176,10 +172,18 @@ free: static int cap_both_sides(struct expression *expr) { - if (expr->op == SPECIAL_UNSIGNED_LT || expr->op == SPECIAL_UNSIGNED_LTE) + switch (expr->op) { + case '<': + case SPECIAL_UNSIGNED_LT: + case SPECIAL_LTE: + case SPECIAL_UNSIGNED_LTE: return cap_lt_zero_or_gt(expr); - if (expr->op == SPECIAL_UNSIGNED_GT || expr->op == SPECIAL_UNSIGNED_GTE) + case '>': + case SPECIAL_UNSIGNED_GT: + case SPECIAL_GTE: + case SPECIAL_UNSIGNED_GTE: return cap_gt_zero_and_lt(expr); + } return 0; } diff --git a/smatch_conditions.c b/smatch_conditions.c index 616cd5b5..6684e087 100644 --- a/smatch_conditions.c +++ b/smatch_conditions.c @@ -310,29 +310,28 @@ static void handle_select(struct expression *expr) } END_FOR_EACH_PTR(sm); } -static void hackup_unsigned_compares(struct expression *expr) +static int make_op_unsigned(int op) { - if (expr->type != EXPR_COMPARE) - return; - - switch (expr->op) { + switch (op) { case '<': - if (expr_unsigned(expr->left) || expr_unsigned(expr->right)) - expr->op = SPECIAL_UNSIGNED_LT; - break; + return SPECIAL_UNSIGNED_LT; case SPECIAL_LTE: - if (expr_unsigned(expr->left) || expr_unsigned(expr->right)) - expr->op = SPECIAL_UNSIGNED_LTE; - break; + return SPECIAL_UNSIGNED_LTE; case '>': - if (expr_unsigned(expr->left) || expr_unsigned(expr->right)) - expr->op = SPECIAL_UNSIGNED_GT; - break; + return SPECIAL_UNSIGNED_GT; case SPECIAL_GTE: - if (expr_unsigned(expr->left) || expr_unsigned(expr->right)) - expr->op = SPECIAL_UNSIGNED_GTE; - break; + return SPECIAL_UNSIGNED_GTE; } + return op; +} + +static void hackup_unsigned_compares(struct expression *expr) +{ + if (expr->type != EXPR_COMPARE) + return; + + if (type_unsigned(get_type(expr))) + expr->op = make_op_unsigned(expr->op); } static void split_conditions(struct expression *expr) -- 2.11.4.GIT