math: check for overflows when calculating the max
authorDan Carpenter <dan.carpenter@oracle.com>
Fri, 23 Nov 2012 06:39:32 +0000 (23 09:39 +0300)
committerDan Carpenter <dan.carpenter@oracle.com>
Fri, 23 Nov 2012 06:39:32 +0000 (23 09:39 +0300)
If it overflows then return the max for the type.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
smatch.h
smatch_math.c
smatch_sval.c

index 744918b..be68265 100644 (file)
--- a/smatch.h
+++ b/smatch.h
@@ -542,6 +542,7 @@ int sval_fits(struct symbol *type, sval_t sval);
 sval_t sval_cast(struct symbol *type, sval_t sval);
 sval_t sval_preop(sval_t sval, int op);
 sval_t sval_binop(sval_t left, int op, sval_t right);
+int sval_binop_overflows(sval_t left, int op, sval_t right);
 const char *sval_to_str(sval_t sval);
 const char *sval_to_numstr(sval_t sval);
 sval_t ll_to_sval(long long val);
index a0a6244..c022db8 100644 (file)
@@ -226,6 +226,7 @@ static sval_t handle_mod(struct expression *expr, int *undefined, int implied)
 
 static sval_t handle_binop(struct expression *expr, int *undefined, int implied)
 {
+       struct symbol *type;
        sval_t left, right;
        sval_t ret = {.type = &int_ctype, .value = 123456};
        int local_undef = 0;
@@ -276,6 +277,19 @@ static sval_t handle_binop(struct expression *expr, int *undefined, int implied)
        if (*undefined)
                return bogus;
 
+       type = get_type(expr);
+       left = sval_cast(type, left);
+       right = sval_cast(type, right);
+
+       switch (implied) {
+       case IMPLIED_MAX:
+       case FUZZY_MAX:
+       case HARD_MAX:
+       case ABSOLUTE_MAX:
+               if (sval_binop_overflows(left, expr->op, right))
+                       return sval_type_max(get_type(expr));
+       }
+
        switch (expr->op) {
        case '/':
                return handle_divide(expr, undefined, implied);
index 9500645..f3c2a19 100644 (file)
@@ -423,6 +423,23 @@ sval_t sval_binop(sval_t left, int op, sval_t right)
        return ret;
 }
 
+int sval_binop_overflows(sval_t left, int op, sval_t right)
+{
+       sval_t max = sval_type_max(left.type);
+
+       switch (op) {
+       case '+':
+               if (sval_cmp(left, sval_binop(max, '-', right)) > 0)
+                       return 1;
+               return 0;
+       case '*':
+               if (sval_cmp(left, sval_binop(max, '/', right)) > 0)
+                       return 1;
+               return 0;
+       }
+       return 0;
+}
+
 const char *sval_to_str(sval_t sval)
 {
        char buf[30];