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 (!is_user_data(expr
))
70 if (!get_user_rl(expr
, &rl
))
76 static int common_false_positives(struct expression
*array
, char *name
, sval_t max
)
81 /* Smatch can't figure out glibc's strcmp __strcmp_cg()
82 * so it prints an error every time you compare to a string
83 * literal array with 4 or less chars.
85 if (strcmp(name
, "__s1") == 0 || strcmp(name
, "__s2") == 0)
88 /* Ugh... People are saying that Smatch still barfs on glibc strcmp()
94 /* why is this again??? */
95 if (array
->type
== EXPR_STRING
&&
96 max
.value
== array
->string
->length
)
99 macro
= get_macro_name(array
->pos
);
100 if (macro
&& max
.uvalue
< 4 &&
101 (strcmp(macro
, "strcmp") == 0 ||
102 strcmp(macro
, "strncmp") == 0 ||
103 strcmp(macro
, "streq") == 0 ||
104 strcmp(macro
, "strneq") == 0 ||
105 strcmp(macro
, "strsep") == 0))
110 * passing WORK_CPU_UNBOUND is idiomatic but Smatch doesn't understand
111 * how it's used so it causes a bunch of false positives.
113 if (option_project
== PROJ_KERNEL
&&
114 strcmp(name
, "__per_cpu_offset") == 0)
119 static void array_check(struct expression
*expr
)
121 struct expression
*array_expr
;
122 const char *level
= "error";
124 struct expression
*offset
;
128 expr
= strip_expr(expr
);
132 array_expr
= get_array_base(expr
);
133 array_size
= get_array_size(array_expr
);
134 if (!array_size
|| array_size
== 1)
137 offset
= get_array_offset(expr
);
138 if (!get_the_max(offset
, &max
))
140 if (array_size
> max
.value
)
142 if (getting_address())
145 if (definitely_just_used_as_limiter(array_expr
, offset
))
148 array_expr
= strip_expr(array_expr
);
149 name
= expr_to_str(array_expr
);
150 if (!common_false_positives(array_expr
, name
, max
)) {
151 sm_msg("%s: buffer overflow '%s' %d <= %s",
152 level
, name
, array_size
, sval_to_str(max
));
157 void check_index_overflow(int id
)
159 add_hook(&array_check
, OP_HOOK
);