extra: get_implied_range_list() should return 0 if it returns unknown
[smatch.git] / check_access_ok_math.c
blob77f3c0818b82f5c752234b3ff084436df9213a38
1 /*
2 * smatch/check_access_ok_math.c
4 * Copyright (C) 2010 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "smatch.h"
12 static int my_id;
14 static int can_overflow(struct expression *expr)
16 long long max;
17 int uncapped = 0;
19 expr = strip_expr(expr);
21 if (expr->type == EXPR_BINOP) {
22 uncapped += can_overflow(expr->left);
23 uncapped += can_overflow(expr->right);
25 if (uncapped &&
26 (expr->op == '+' || expr->op == '*' || expr->op == SPECIAL_LEFTSHIFT))
27 return 1;
29 return 0;
32 if (get_implied_max(expr, &max))
33 return 0;
34 if (get_absolute_max(expr, &max) && max <= 4096)
35 return 0;
36 return 1;
39 static void match_size(struct expression *size_expr)
41 char *name;
43 size_expr = strip_expr(size_expr);
44 if (!size_expr)
45 return;
46 if (size_expr->type != EXPR_BINOP) {
47 size_expr = get_assigned_expr(size_expr);
48 if (!size_expr || size_expr->type != EXPR_BINOP)
49 return;
51 if (!can_overflow(size_expr))
52 return;
54 name = get_variable_from_expr_complex(size_expr, NULL);
55 sm_msg("warn: math in access_ok() is dangerous '%s'", name);
57 free_string(name);
60 static void match_access_ok(const char *fn, struct expression *expr, void *data)
62 struct expression *size_expr;
64 size_expr = get_argument_from_call_expr(expr->args, 1);
65 match_size(size_expr);
68 static void split_asm_constraints(struct expression_list *expr_list)
70 struct expression *expr;
71 int state = 0;
72 int i;
74 i = 0;
75 FOR_EACH_PTR(expr_list, expr) {
77 switch (state) {
78 case 0: /* identifier */
79 case 1: /* constraint */
80 state++;
81 continue;
82 case 2: /* expression */
83 state = 0;
84 if (i == 1)
85 match_size(expr);
86 i++;
87 continue;
89 } END_FOR_EACH_PTR(expr);
92 static void match_asm_stmt(struct statement *stmt)
94 char *name;
96 name = get_macro_name(stmt->pos);
97 if (!name || strcmp(name, "access_ok") != 0)
98 return;
99 split_asm_constraints(stmt->asm_inputs);
102 void check_access_ok_math(int id)
104 my_id = id;
105 if (option_project != PROJ_KERNEL)
106 return;
107 add_function_hook("__access_ok", &match_access_ok, NULL);
108 add_hook(&match_asm_stmt, ASM_HOOK);