debug: add __smatch_timer_start/stop()
[smatch.git] / check_signed.c
blob947b84fed4dc67096cb27b55257c2db07e76c69f
1 /*
2 * Copyright (C) 2009 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 * Check for things which are signed but probably should be unsigned.
21 * Hm... It seems like at this point in the processing, sparse makes all
22 * bitfields unsigned. Which is logical but not what GCC does.
26 #include "smatch.h"
27 #include "smatch_extra.h"
29 static int my_id;
31 #define VAR_ON_RIGHT 0
32 #define VAR_ON_LEFT 1
34 static void match_assign(struct expression *expr)
36 struct symbol *sym;
37 sval_t sval;
38 sval_t max;
39 sval_t min;
40 char *left_name, *right_name;
42 if (__in_fake_assign || __in_fake_var_assign)
43 return;
44 if (expr->op == SPECIAL_AND_ASSIGN || expr->op == SPECIAL_OR_ASSIGN)
45 return;
47 sym = get_type(expr->left);
48 if (!sym || sym->type != SYM_BASETYPE) {
49 //sm_msg("could not get type");
50 return;
52 if (type_bits(sym) < 0 || type_bits(sym) >= 32) /* max_val limits this */
53 return;
54 if (!get_implied_value(expr->right, &sval))
55 return;
56 max = sval_type_max(sym);
57 if (sym != &bool_ctype && sym != &uchar_ctype &&
58 sval_cmp(max, sval) < 0 &&
59 !(sval.value < 256 && max.value == 127)) {
60 left_name = expr_to_str(expr->left);
61 right_name = expr_to_str(expr->right);
62 sm_warning("'%s' %s can't fit into %s '%s'",
63 right_name, sval_to_numstr(sval), sval_to_numstr(max), left_name);
64 free_string(left_name);
66 min = sval_type_min(sym);
67 if (sval_cmp_t(&llong_ctype, min, sval) > 0) {
68 if (min.value == 0 && sval.value == -1) /* assigning -1 to unsigned variables is idiomatic */
69 return;
70 if (expr->right->type == EXPR_PREOP && expr->right->op == '~')
71 return;
72 if (expr->op == SPECIAL_SUB_ASSIGN || expr->op == SPECIAL_ADD_ASSIGN)
73 return;
74 if (sval_positive_bits(sval) == 7)
75 return;
76 left_name = expr_to_str(expr->left);
77 if (min.value == 0) {
78 sm_warning("assigning %s to unsigned variable '%s'",
79 sval_to_str(sval), left_name);
80 } else {
81 sm_warning("value %s can't fit into %s '%s'",
82 sval_to_str(sval), sval_to_str(min), left_name);
84 free_string(left_name);
88 static int cap_gt_zero_and_lt(struct expression *expr)
91 struct expression *var = expr->left;
92 struct expression *tmp;
93 char *name1 = NULL;
94 char *name2 = NULL;
95 sval_t known;
96 int ret = 0;
97 int i;
99 if (!get_value(expr->right, &known) || known.value != 0)
100 return 0;
102 i = 0;
103 FOR_EACH_PTR_REVERSE(big_expression_stack, tmp) {
104 if (!i++)
105 continue;
106 if (tmp->op == SPECIAL_LOGICAL_AND) {
107 struct expression *right = strip_expr(tmp->right);
109 if (right->op != '<' &&
110 right->op != SPECIAL_UNSIGNED_LT &&
111 right->op != SPECIAL_LTE &&
112 right->op != SPECIAL_UNSIGNED_LTE)
113 return 0;
115 name1 = expr_to_str(var);
116 if (!name1)
117 goto free;
119 name2 = expr_to_str(right->left);
120 if (!name2)
121 goto free;
122 if (!strcmp(name1, name2))
123 ret = 1;
124 goto free;
127 return 0;
128 } END_FOR_EACH_PTR_REVERSE(tmp);
130 free:
131 free_string(name1);
132 free_string(name2);
133 return ret;
136 static int cap_lt_zero_or_gt(struct expression *expr)
139 struct expression *var = expr->left;
140 struct expression *tmp;
141 char *name1 = NULL;
142 char *name2 = NULL;
143 sval_t known;
144 int ret = 0;
145 int i;
147 if (!get_value(expr->right, &known) || known.value != 0)
148 return 0;
150 i = 0;
151 FOR_EACH_PTR_REVERSE(big_expression_stack, tmp) {
152 if (!i++)
153 continue;
154 if (tmp->op == SPECIAL_LOGICAL_OR) {
155 struct expression *right = strip_expr(tmp->right);
157 if (right->op != '>' &&
158 right->op != SPECIAL_UNSIGNED_GT &&
159 right->op != SPECIAL_GTE &&
160 right->op != SPECIAL_UNSIGNED_GTE)
161 return 0;
163 name1 = expr_to_str(var);
164 if (!name1)
165 goto free;
167 name2 = expr_to_str(right->left);
168 if (!name2)
169 goto free;
170 if (!strcmp(name1, name2))
171 ret = 1;
172 goto free;
175 return 0;
176 } END_FOR_EACH_PTR_REVERSE(tmp);
178 free:
179 free_string(name1);
180 free_string(name2);
181 return ret;
184 static int cap_both_sides(struct expression *expr)
186 switch (expr->op) {
187 case '<':
188 case SPECIAL_UNSIGNED_LT:
189 case SPECIAL_LTE:
190 case SPECIAL_UNSIGNED_LTE:
191 return cap_lt_zero_or_gt(expr);
192 case '>':
193 case SPECIAL_UNSIGNED_GT:
194 case SPECIAL_GTE:
195 case SPECIAL_UNSIGNED_GTE:
196 return cap_gt_zero_and_lt(expr);
198 return 0;
201 static int compare_against_macro(struct expression *expr)
203 sval_t known;
205 if (expr->op != SPECIAL_UNSIGNED_LT)
206 return 0;
208 if (!get_value(expr->right, &known) || known.value != 0)
209 return 0;
210 return !!get_macro_name(expr->right->pos);
213 static int print_unsigned_never_less_than_zero(struct expression *expr)
215 sval_t known;
216 char *name;
218 if (expr->op != SPECIAL_UNSIGNED_LT)
219 return 0;
221 if (!get_value(expr->right, &known) || known.value != 0)
222 return 0;
224 name = expr_to_str(expr->left);
225 sm_warning("unsigned '%s' is never less than zero.", name);
226 free_string(name);
227 return 1;
230 static bool is_u64_vs_ulongmax(struct expression *expr)
232 struct symbol *left, *right;
233 sval_t sval;
235 if (expr->op != '>' && expr->op != SPECIAL_UNSIGNED_GT)
236 return false;
237 if (!get_value(expr->right, &sval) ||
238 !sval_is_max(sval))
239 return false;
241 left = get_type(expr->left);
242 right = get_type(expr->right);
244 if (left == right)
245 return true;
246 if (type_positive_bits(left) < type_positive_bits(right))
247 return true;
249 if (type_bits(left) != 64)
250 return false;
251 if (right != &ulong_ctype && right != &uint_ctype)
252 return false;
254 return true;
257 static void match_condition(struct expression *expr)
259 struct symbol *type;
260 sval_t known;
261 sval_t min, max;
262 struct range_list *rl_left_orig, *rl_right_orig;
263 struct range_list *rl_left, *rl_right;
265 if (expr->type != EXPR_COMPARE)
266 return;
268 type = get_type(expr);
269 if (!type)
270 return;
272 /* screw it. I am writing this to mark yoda code as buggy.
273 * Valid comparisons between an unsigned and zero are:
274 * 1) inside a macro.
275 * 2) foo < LOWER_BOUND where LOWER_BOUND is a macro.
276 * 3) foo < 0 || foo > X in exactly this format. No Yoda.
277 * 4) foo >= 0 && foo < X
279 if (get_macro_name(expr->pos))
280 return;
281 if (compare_against_macro(expr))
282 return;
283 if (cap_both_sides(expr))
284 return;
286 /* This is a special case for the common error */
287 if (print_unsigned_never_less_than_zero(expr))
288 return;
290 /* check that one and only one side is known */
291 if (get_value(expr->left, &known)) {
292 if (get_value(expr->right, &known))
293 return;
294 rl_left_orig = alloc_rl(known, known);
295 rl_left = cast_rl(type, rl_left_orig);
297 min = sval_type_min(get_type(expr->right));
298 max = sval_type_max(get_type(expr->right));
299 rl_right_orig = alloc_rl(min, max);
300 rl_right = cast_rl(type, rl_right_orig);
301 } else if (get_value(expr->right, &known)) {
302 rl_right_orig = alloc_rl(known, known);
303 rl_right = cast_rl(type, rl_right_orig);
305 min = sval_type_min(get_type(expr->left));
306 max = sval_type_max(get_type(expr->left));
307 rl_left_orig = alloc_rl(min, max);
308 rl_left = cast_rl(type, rl_left_orig);
309 } else {
310 return;
313 if (!possibly_true_rl(rl_left, expr->op, rl_right) &&
314 !is_u64_vs_ulongmax(expr)) {
315 char *name = expr_to_str(expr);
317 sm_warning("impossible condition '(%s) => (%s %s %s)'", name,
318 show_rl(rl_left), show_special(expr->op),
319 show_rl(rl_right));
320 free_string(name);
323 if (!possibly_false_rl(rl_left, expr->op, rl_right)) {
324 char *name = expr_to_str(expr);
326 sm_warning("always true condition '(%s) => (%s %s %s)'", name,
327 show_rl(rl_left_orig), show_special(expr->op),
328 show_rl(rl_right_orig));
329 free_string(name);
333 void check_signed(int id)
335 my_id = id;
337 add_hook(&match_assign, ASSIGNMENT_HOOK);
338 add_hook(&match_condition, CONDITION_HOOK);