2 * smatch/check_access_ok_math.c
4 * Copyright (C) 2010 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
13 extern int check_assigned_expr_id
;
15 static struct expression
*get_assigned_expr(struct expression
*expr
)
17 struct smatch_state
*state
;
19 state
= get_state_expr(check_assigned_expr_id
, expr
);
22 return (struct expression
*)state
->data
;
25 static int can_overflow(struct expression
*expr
)
30 expr
= strip_expr(expr
);
32 if (expr
->type
== EXPR_BINOP
) {
33 uncapped
+= can_overflow(expr
->left
);
34 uncapped
+= can_overflow(expr
->right
);
37 (expr
->op
== '+' || expr
->op
== '*' || expr
->op
== SPECIAL_LEFTSHIFT
))
43 if (get_implied_max(expr
, &max
))
45 if (get_absolute_max(expr
, &max
) && max
<= 4096)
50 static void match_size(struct expression
*size_expr
)
54 size_expr
= strip_expr(size_expr
);
57 if (size_expr
->type
!= EXPR_BINOP
) {
58 size_expr
= get_assigned_expr(size_expr
);
59 if (!size_expr
|| size_expr
->type
!= EXPR_BINOP
)
62 if (!can_overflow(size_expr
))
65 name
= get_variable_from_expr_complex(size_expr
, NULL
);
66 sm_msg("warn: math in access_ok() is dangerous '%s'", name
);
71 static void match_access_ok(const char *fn
, struct expression
*expr
, void *data
)
73 struct expression
*size_expr
;
75 size_expr
= get_argument_from_call_expr(expr
->args
, 1);
76 match_size(size_expr
);
79 static void split_asm_constraints(struct expression_list
*expr_list
)
81 struct expression
*expr
;
86 FOR_EACH_PTR(expr_list
, expr
) {
89 case 0: /* identifier */
90 case 1: /* constraint */
93 case 2: /* expression */
100 } END_FOR_EACH_PTR(expr
);
103 static void match_asm_stmt(struct statement
*stmt
)
107 name
= get_macro_name(&stmt
->pos
);
108 if (!name
|| strcmp(name
, "access_ok") != 0)
110 split_asm_constraints(stmt
->asm_inputs
);
113 void check_access_ok_math(int id
)
116 if (option_project
!= PROJ_KERNEL
)
118 add_function_hook("__access_ok", &match_access_ok
, NULL
);
119 add_hook(&match_asm_stmt
, ASM_HOOK
);