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
21 #include "smatch_slist.h"
22 #include "smatch_extra.h"
24 static int definitely_just_used_as_limiter(struct expression
*array
, struct expression
*offset
)
27 struct expression
*tmp
;
31 if (!get_implied_value(offset
, &sval
))
33 if (get_array_size(array
) != sval
.value
)
36 FOR_EACH_PTR_REVERSE(big_expression_stack
, tmp
) {
41 if (tmp
->type
== EXPR_PREOP
&& tmp
->op
== '(')
43 if (tmp
->op
== '.' && !dot_ops
++)
45 if (step
== 1 && tmp
->op
== '&') {
49 if (step
== 2 && tmp
->type
== EXPR_COMPARE
)
51 if (step
== 2 && tmp
->type
== EXPR_ASSIGNMENT
)
54 } END_FOR_EACH_PTR_REVERSE(tmp
);
58 static int get_the_max(struct expression
*expr
, sval_t
*sval
)
60 struct range_list
*rl
;
62 if (get_hard_max(expr
, sval
))
66 if (get_fuzzy_max(expr
, sval
))
68 if (!get_user_rl(expr
, &rl
))
74 static int common_false_positives(struct expression
*array
, char *name
, sval_t max
)
79 /* Smatch can't figure out glibc's strcmp __strcmp_cg()
80 * so it prints an error every time you compare to a string
81 * literal array with 4 or less chars.
83 if (strcmp(name
, "__s1") == 0 || strcmp(name
, "__s2") == 0)
86 /* Ugh... People are saying that Smatch still barfs on glibc strcmp()
92 /* why is this again??? */
93 if (array
->type
== EXPR_STRING
&&
94 max
.value
== array
->string
->length
)
97 macro
= get_macro_name(array
->pos
);
98 if (macro
&& max
.uvalue
< 4 &&
99 (strcmp(macro
, "strcmp") == 0 ||
100 strcmp(macro
, "strncmp") == 0 ||
101 strcmp(macro
, "streq") == 0 ||
102 strcmp(macro
, "strneq") == 0 ||
103 strcmp(macro
, "strsep") == 0))
108 * passing WORK_CPU_UNBOUND is idiomatic but Smatch doesn't understand
109 * how it's used so it causes a bunch of false positives.
111 if (option_project
== PROJ_KERNEL
&&
112 strcmp(name
, "__per_cpu_offset") == 0)
117 static void array_check(struct expression
*expr
)
119 struct expression
*array_expr
;
121 struct expression
*offset
;
125 expr
= strip_expr(expr
);
129 if (is_impossible_path())
131 array_expr
= get_array_base(expr
);
132 array_size
= get_array_size(array_expr
);
133 if (!array_size
|| array_size
== 1)
136 offset
= get_array_offset(expr
);
137 if (!get_the_max(offset
, &max
))
139 if (array_size
> max
.value
)
142 if (definitely_just_used_as_limiter(array_expr
, offset
))
145 array_expr
= strip_expr(array_expr
);
146 name
= expr_to_str(array_expr
);
147 if (common_false_positives(array_expr
, name
, max
))
150 sm_msg("error: buffer overflow '%s' %d <= %s", name
, array_size
, sval_to_str(max
));
156 void check_index_overflow(int id
)
158 add_hook(&array_check
, OP_HOOK
);