free_strict: print the line number where the pointer was freed
[smatch.git] / check_impossible_compare.c
blob3e175c9e6151d61eb8d86389b300fe86bf2a61dc
1 /*
2 * Copyright 2023 Linaro Ltd.
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
18 #include "smatch.h"
19 #include "smatch_extra.h"
21 static int my_id;
23 static const char *okay_macros[] = {
24 "ULONG_MAX",
27 static const char *kernel_macros[] = {
28 "DP_FFE_PRESET_MAX_LEVEL",
29 "FSMC_THOLD_MASK",
30 "FSMC_TSET_MASK",
31 "FSMC_TWAIT_MASK",
32 "L2CAP_CID_DYN_END",
33 "LOGICVC_DIMENSIONS_MAX",
34 "MAXREFCEXTLEN",
35 "MAXREFCOUNT",
36 "NLM4_OFFSET_MAX",
37 "TIPC_MAX_PORT",
38 "TSL2591_ALS_MAX_VALUE",
39 "UBIFS_COMPR_TYPES_CNT",
40 "XFS_MAX_CRC_AG_BLOCKS",
41 NULL
44 static const char **allowed_macros;
46 static bool is_lt_zero(int op, sval_t known)
48 if (op != '<' && op != SPECIAL_UNSIGNED_LT)
49 return false;
50 if (known.value != 0)
51 return false;
52 return true;
55 static bool check_is_ulong_max_recursive(struct expression *expr)
57 sval_t sval;
59 expr = strip_expr(expr);
61 if (!get_value(expr, &sval))
62 return false;
64 if (expr->type == EXPR_BINOP) {
65 if (check_is_ulong_max_recursive(expr->left))
66 return true;
67 return false;
70 if (sval_cmp(sval, sval_type_max(&ulong_ctype)) == 0)
71 return true;
72 return false;
75 static bool is_u64_vs_ulongmax(struct expression *expr)
77 struct symbol *left, *right;
79 if (expr->op != '>' && expr->op != SPECIAL_UNSIGNED_GT)
80 return false;
81 if (!check_is_ulong_max_recursive(expr->right))
82 return false;
84 left = get_type(expr->left);
85 right = get_type(expr->right);
87 if (left == right)
88 return true;
89 if (type_positive_bits(left) < type_positive_bits(right))
90 return true;
92 if (type_bits(left) != 64)
93 return false;
94 if (right != &ulong_ctype && right != &uint_ctype)
95 return false;
97 return true;
100 static bool is_long_vs_UINTMAX(struct range_list *rl, int op, sval_t known)
102 if (op != '>' && op != SPECIAL_UNSIGNED_GT)
103 return false;
104 if (rl_type(rl) != &long_ctype && rl_type(rl) != &ulong_ctype)
105 return false;
106 if (known.value == UINT_MAX)
107 return true;
108 return false;
111 static bool is_allowed_impossible_limit(struct expression *expr)
113 char *macro;
114 int i;
116 if (!allowed_macros)
117 return false;
119 macro = get_macro_name(expr->pos);
120 if (!macro) {
121 macro = pos_ident(expr->pos);
122 if (!macro)
123 return false;
125 i = -1;
126 while (allowed_macros[++i]) {
127 if (strcmp(macro, allowed_macros[i]) == 0)
128 return true;
130 return false;
133 static void match_condition(struct expression *expr)
135 struct symbol *type;
136 sval_t known, dummy;
137 struct range_list *var_rl, *known_rl, *rl_right, *rl_left;
138 char *name;
139 int op;
141 if (expr->type != EXPR_COMPARE)
142 return;
144 type = get_type(expr);
145 if (!type)
146 return;
148 if (get_macro_name(expr->pos))
149 return;
151 op = expr->op;
152 if (get_value(expr->right, &known)) {
153 /* check that one and only one side is known */
154 if (get_value(expr->left, &dummy))
155 return;
157 var_rl = alloc_whole_rl(get_type(expr->left));
158 } else if (get_value(expr->left, &known)) {
159 op = flip_comparison(op);
160 var_rl = alloc_whole_rl(get_type(expr->right));
161 } else {
162 return;
164 known = sval_cast(type, known);
165 known_rl = alloc_rl(known, known);
166 var_rl = cast_rl(type, var_rl);
168 /* handled by check_unsigned_lt_zero.c */
169 if (is_lt_zero(op, known))
170 return;
172 if (possibly_true_rl(var_rl, op, known_rl))
173 return;
174 if (is_u64_vs_ulongmax(expr))
175 return;
176 if (is_long_vs_UINTMAX(var_rl, op, known))
177 return;
178 if (is_allowed_impossible_limit(expr->right))
179 return;
181 name = expr_to_str(expr);
182 get_absolute_rl(expr->left, &rl_left);
183 get_absolute_rl(expr->right, &rl_right);
184 sm_warning("impossible condition '(%s) => (%s %s %s)'", name,
185 show_rl(rl_left), show_special(expr->op), show_rl(rl_right));
186 free_string(name);
189 void check_impossible_compare(int id)
191 my_id = id;
193 allowed_macros = okay_macros;
194 if (option_project == PROJ_KERNEL)
195 allowed_macros = kernel_macros;
197 add_hook(&match_condition, CONDITION_HOOK);