extra: assume indexes are in bounds
authorDan Carpenter <dan.carpenter@oracle.com>
Fri, 20 Dec 2013 09:43:11 +0000 (20 12:43 +0300)
committerDan Carpenter <dan.carpenter@oracle.com>
Fri, 20 Dec 2013 09:43:11 +0000 (20 12:43 +0300)
Sometimes, we know the size of the array but we don't know the value of the
index.  After this patch we assume that the index is valid.  We only
assume this after we have had a chance to warn about the overflow, so it
shouldn't hide any bugs.  If the index is used more than once though, the
second use doesn't generate a warning.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
smatch_extra.c

index 24ff355..c717344 100644 (file)
@@ -1286,6 +1286,44 @@ void __extra_match_condition(struct expression *expr)
        }
 }
 
+static void assume_indexes_are_valid(struct expression *expr)
+{
+       struct expression *array_expr;
+       int array_size;
+       struct expression *offset;
+       struct symbol *offset_type;
+       struct range_list *rl_before;
+       struct range_list *rl_after;
+       struct range_list *filter = NULL;
+       sval_t size;
+
+       expr = strip_expr(expr);
+       if (!is_array(expr))
+               return;
+
+       offset = get_array_offset(expr);
+       offset_type = get_type(offset);
+       if (offset_type && type_signed(offset_type)) {
+               filter = alloc_rl(sval_type_min(offset_type),
+                                 sval_type_val(offset_type, -1));
+       }
+
+       array_expr = strip_parens(expr->unop->left);
+       array_size = get_real_array_size(array_expr);
+       if (array_size > 1) {
+               size = sval_type_val(offset_type, array_size);
+               add_range(&filter, size, sval_type_max(offset_type));
+       }
+
+       if (!filter)
+               return;
+       get_absolute_rl(offset, &rl_before);
+       rl_after = rl_filter(rl_before, filter);
+       if (rl_equiv(rl_before, rl_after))
+               return;
+       set_extra_expr_nomod(offset, alloc_estate_rl(rl_after));
+}
+
 /* returns 1 if it is not possible for expr to be value, otherwise returns 0 */
 int implied_not_equal(struct expression *expr, long long val)
 {
@@ -1545,4 +1583,6 @@ void register_smatch_extra_late(int id)
        add_hook(&match_call_info, FUNCTION_CALL_HOOK);
        add_member_info_callback(my_id, struct_member_callback);
        add_returned_member_callback(my_id, returned_member_callback);
+
+       add_hook(&assume_indexes_are_valid, OP_HOOK);
 }