conditions: fix small signedness bug in compares
authorDan Carpenter <dan.carpenter@oracle.com>
Thu, 14 Mar 2013 11:13:19 +0000 (14 14:13 +0300)
committerDan Carpenter <dan.carpenter@oracle.com>
Thu, 14 Mar 2013 11:13:19 +0000 (14 14:13 +0300)
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 <dan.carpenter@oracle.com>
check_signed.c
smatch_conditions.c

index 2500ed1..a621799 100644 (file)
@@ -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;
 }
 
index 616cd5b..6684e08 100644 (file)
@@ -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)