extra: don't reset impossible states after a condition
[smatch.git] / check_signed_integer_overflow_check.c
blob5eb9b0e16f4d3c37e94ae5cc83aafb12e975a4cd
1 /*
2 * Copyright (C) 2014 Oracle.
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.
24 #include "smatch.h"
25 #include "smatch_slist.h"
27 static int my_id;
29 static void match_condition(struct expression *expr)
31 struct expression *left, *right;
32 struct symbol *type;
33 char *right_name;
34 char *left_name;
36 if (expr->type != EXPR_COMPARE)
37 return;
38 if (expr->op != '<')
39 return;
41 type = get_type(expr);
42 if (!type_signed(type))
43 return;
45 left = strip_expr(expr->left);
46 right = strip_expr(expr->right);
48 if (left->type != EXPR_BINOP) {
49 left = get_assigned_expr(left);
50 left = strip_expr(left);
51 if (!left || left->type != EXPR_BINOP)
52 return;
55 if (left->op != '+' && left->op != '*' && left->op != SPECIAL_LEFTSHIFT)
56 return;
58 if (has_variable(left, right) == 1) {
59 left_name = expr_to_str(left);
60 right_name = expr_to_str(right);
61 sm_msg("warn: signed overflow undefined. '%s %s %s'", left_name, show_special(expr->op), right_name);
62 free_string(left_name);
63 free_string(right_name);
67 static void match_binop(struct expression *expr)
69 sval_t left_val, right_min;
70 char *str;
72 if (expr->op != '-')
73 return;
75 if (!get_value(expr->left, &left_val))
76 return;
78 switch (left_val.uvalue) {
79 case SHRT_MAX:
80 case USHRT_MAX:
81 case INT_MAX:
82 case UINT_MAX:
83 case LLONG_MAX:
84 case ULLONG_MAX:
85 break;
86 default:
87 return;
90 get_absolute_min(expr->right, &right_min);
91 if (!sval_is_negative(right_min))
92 return;
94 str = expr_to_str(expr);
95 sm_msg("warn: potential negative subtraction from max '%s'", str);
96 free_string(str);
99 void check_signed_integer_overflow_check(int id)
101 my_id = id;
103 add_hook(&match_condition, CONDITION_HOOK);
104 add_hook(&match_binop, BINOP_HOOK);