2 * Copyright (C) 2010 Dan Carpenter.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 * Looks for integers that we get from the user which can be attacked
20 * with an integer overflow.
25 #include "smatch_slist.h"
33 static void match_condition(struct expression
*expr
)
35 struct smatch_state
*left_max_true
= NULL
;
36 struct smatch_state
*left_max_false
= NULL
;
37 struct smatch_state
*right_max_true
= NULL
;
38 struct smatch_state
*right_max_false
= NULL
;
40 struct smatch_state
*left_min_true
= NULL
;
41 struct smatch_state
*left_min_false
= NULL
;
42 struct smatch_state
*right_min_true
= NULL
;
43 struct smatch_state
*right_min_false
= NULL
;
45 if (expr
->type
!= EXPR_COMPARE
)
51 case SPECIAL_UNSIGNED_LT
:
52 case SPECIAL_UNSIGNED_LTE
:
53 left_max_true
= &capped
;
54 right_max_false
= &capped
;
55 right_min_true
= &capped
;
56 left_min_false
= &capped
;
60 case SPECIAL_UNSIGNED_GT
:
61 case SPECIAL_UNSIGNED_GTE
:
62 left_max_false
= &capped
;
63 right_max_true
= &capped
;
64 left_min_true
= &capped
;
65 right_min_false
= &capped
;
68 left_max_true
= &capped
;
69 right_max_true
= &capped
;
70 left_min_true
= &capped
;
71 right_min_true
= &capped
;
73 case SPECIAL_NOTEQUAL
:
74 left_max_false
= &capped
;
75 right_max_false
= &capped
;
76 left_min_false
= &capped
;
77 right_min_false
= &capped
;
83 if (get_state_expr(my_max_id
, expr
->left
)) {
84 set_true_false_states_expr(my_max_id
, expr
->left
, left_max_true
, left_max_false
);
85 set_true_false_states_expr(my_min_id
, expr
->left
, left_min_true
, left_min_false
);
87 if (get_state_expr(my_max_id
, expr
->right
)) {
88 set_true_false_states_expr(my_max_id
, expr
->right
, right_max_true
, right_max_false
);
89 set_true_false_states_expr(my_min_id
, expr
->right
, right_min_true
, right_min_false
);
93 static void match_normal_assign(struct expression
*expr
)
95 if (get_state_expr(my_max_id
, expr
->left
)) {
96 set_state_expr(my_max_id
, expr
->left
, &capped
);
97 set_state_expr(my_min_id
, expr
->left
, &capped
);
101 static void match_assign(struct expression
*expr
)
105 name
= get_macro_name(expr
->pos
);
106 if (!name
|| strcmp(name
, "get_user") != 0) {
107 match_normal_assign(expr
);
110 name
= expr_to_var(expr
->right
);
111 if (!name
|| (strcmp(name
, "__val_gu") != 0 && strcmp(name
, "__gu_val")))
113 set_state_expr(my_max_id
, expr
->left
, &user_data
);
114 set_state_expr(my_min_id
, expr
->left
, &user_data
);
119 static void check_expr(struct expression
*expr
)
128 sm
= get_sm_state_expr(my_max_id
, expr
);
129 if (sm
&& slist_has_state(sm
->possible
, &user_data
)) {
130 get_absolute_max(expr
, &max
);
131 if (sval_cmp_val(max
, 20000) > 0)
135 sm
= get_sm_state_expr(my_min_id
, expr
);
136 if (sm
&& slist_has_state(sm
->possible
, &user_data
)) {
137 get_absolute_min(expr
, &sval
);
138 if (sval_is_negative(sval
) && sval_cmp_val(sval
, -20000) < 0)
142 if (!overflow
&& !underflow
)
145 name
= expr_to_var_sym(expr
, NULL
);
146 if (overflow
&& underflow
)
147 sm_warning("check for integer over/underflow '%s'", name
);
149 sm_warning("check for integer underflow '%s'", name
);
151 sm_warning("check for integer overflow '%s'", name
);
154 set_state_expr(my_max_id
, expr
, &capped
);
155 set_state_expr(my_min_id
, expr
, &capped
);
158 static void match_binop(struct expression
*expr
)
166 if (expr
->op
== SPECIAL_RIGHTSHIFT
)
168 if (expr
->op
== SPECIAL_LEFTSHIFT
)
171 check_expr(expr
->left
);
172 check_expr(expr
->right
);
175 void check_get_user_overflow(int id
)
177 if (option_project
!= PROJ_KERNEL
)
180 add_hook(&match_condition
, CONDITION_HOOK
);
181 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
182 add_hook(&match_binop
, BINOP_HOOK
);
185 void check_get_user_overflow2(int id
)