2 * sparse/check_deference.c
4 * Copyright (C) 2006 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
13 #include "smatch_slist.h"
22 static struct symbol
*this_func
;
24 static void match_function_def(struct symbol
*sym
)
29 static void print_args(struct expression
*expr
, int size
)
40 name
= get_variable_from_expr(expr
, &sym
);
45 FOR_EACH_PTR(this_func
->ctype
.base_type
->arguments
, arg
) {
46 arg_name
= (arg
->ident
?arg
->ident
->name
:"-");
47 if (sym
== arg
&& !strcmp(name
, arg_name
)) {
48 sm_msg("param %d array index. size %d", i
, size
);
52 } END_FOR_EACH_PTR(arg
);
57 static char *alloc_num(long long num
)
59 static char buff
[256];
61 if (num
== whole_range
.min
) {
62 snprintf(buff
, 255, "min");
63 } else if (num
== whole_range
.max
) {
64 snprintf(buff
, 255, "max");
66 snprintf(buff
, 255, "(%lld)", num
);
68 snprintf(buff
, 255, "%lld", num
);
71 return alloc_sname(buff
);
74 static struct smatch_state
*alloc_my_state(int val
)
76 struct smatch_state
*state
;
78 state
= malloc(sizeof(*state
));
79 state
->name
= alloc_num(val
);
80 state
->data
= malloc(sizeof(int));
81 *(int *)state
->data
= val
;
85 static void match_declaration(struct symbol
*sym
)
87 struct symbol
*base_type
;
94 name
= sym
->ident
->name
;
95 base_type
= get_base_type(sym
);
97 if (base_type
->type
== SYM_ARRAY
&& base_type
->bit_size
> 0) {
98 set_state(my_id
, name
, NULL
, alloc_my_state(base_type
->bit_size
));
100 if (sym
->initializer
&&
101 sym
->initializer
->type
== EXPR_STRING
&&
102 sym
->initializer
->string
) {
103 size
= sym
->initializer
->string
->length
* 8;
104 set_state(my_id
, name
, NULL
, alloc_my_state(size
));
109 static int get_array_size(struct expression
*expr
)
113 struct smatch_state
*state
;
116 if (expr
->type
!= EXPR_SYMBOL
)
118 tmp
= get_base_type(expr
->symbol
);
119 if (tmp
->type
== SYM_ARRAY
) {
120 ret
= get_expression_value(tmp
->array_size
);
124 name
= get_variable_from_expr(expr
, NULL
);
127 state
= get_state(my_id
, name
, NULL
);
128 if (!state
|| !state
->data
)
130 if (tmp
->type
== SYM_PTR
)
131 tmp
= get_base_type(tmp
);
132 ret
= *(int *)state
->data
/ 8 / tmp
->ctype
.alignment
;
138 extern int check_assigned_expr_id
;
139 static void print_assigned_expr(struct expression
*expr
)
142 struct state_list
*slist
;
143 struct sm_state
*tmp
;
146 name
= get_variable_from_expr(expr
, NULL
);
147 slist
= get_possible_states_expr(check_assigned_expr_id
, expr
);
148 FOR_EACH_PTR(slist
, tmp
) {
149 if (tmp
->state
== &undefined
|| tmp
->state
== &merged
)
151 smatch_msg("debug: unknown initializer %s = %s", name
, show_state(tmp
->state
));
152 } END_FOR_EACH_PTR(tmp
);
157 static void array_check(struct expression
*expr
)
159 struct expression
*dest
;
161 struct expression
*offset
;
165 expr
= strip_expr(expr
);
169 dest
= get_array_name(expr
);
170 array_size
= get_array_size(dest
);
172 name
= get_variable_from_expr(dest
, NULL
);
175 // smatch_msg("debug: array '%s' unknown size", name);
176 print_assigned_expr(dest
);
180 offset
= get_array_offset(expr
);
181 if (!get_implied_max(offset
, &max
)) {
182 name
= get_variable_from_expr(dest
, NULL
);
183 // smatch_msg("debug: offset '%s' unknown", name);
184 print_args(offset
, array_size
);
185 } else if (array_size
<= max
) {
186 name
= get_variable_from_expr(dest
, NULL
);
188 blast. smatch can't figure out glibc's strcmp __strcmp_cg()
189 so it prints an error every time you compare to a string
190 literal array with 4 or less chars. */
191 if (strcmp(name
, "__s1") && strcmp(name
, "__s2"))
192 sm_msg("error: buffer overflow '%s' %d <= %lld", name
, array_size
, max
);
197 static void match_string_assignment(struct expression
*expr
)
199 struct expression
*left
;
200 struct expression
*right
;
203 left
= strip_expr(expr
->left
);
204 right
= strip_expr(expr
->right
);
205 name
= get_variable_from_expr(left
, NULL
);
208 if (right
->type
!= EXPR_STRING
|| !right
->string
)
210 set_state(my_id
, name
, NULL
,
211 alloc_my_state(right
->string
->length
* 8));
216 static void match_malloc(const char *fn
, struct expression
*expr
, void *unused
)
219 struct expression
*right
;
220 struct expression
*arg
;
223 name
= get_variable_from_expr(expr
->left
, NULL
);
227 right
= strip_expr(expr
->right
);
228 arg
= get_argument_from_call_expr(right
->args
, 0);
229 if (!get_implied_value(arg
, &bytes
))
231 set_state(my_id
, name
, NULL
, alloc_my_state(bytes
* 8));
236 static void match_strcpy(const char *fn
, struct expression
*expr
,
239 struct expression
*dest
;
240 struct expression
*data
;
241 char *dest_name
= NULL
;
242 char *data_name
= NULL
;
243 struct smatch_state
*dest_state
;
244 struct smatch_state
*data_state
;
248 dest
= get_argument_from_call_expr(expr
->args
, 0);
249 dest_name
= get_variable_from_expr(dest
, NULL
);
251 data
= get_argument_from_call_expr(expr
->args
, 1);
252 data_name
= get_variable_from_expr(data
, NULL
);
254 dest_state
= get_state(my_id
, dest_name
, NULL
);
255 if (!dest_state
|| !dest_state
->data
)
258 data_state
= get_state(my_id
, data_name
, NULL
);
259 if (!data_state
|| !data_state
->data
)
261 dest_size
= *(int *)dest_state
->data
/ 8;
262 data_size
= *(int *)data_state
->data
/ 8;
263 if (dest_size
< data_size
)
264 sm_msg("error: %s (%d) too large for %s (%d)", data_name
,
265 data_size
, dest_name
, dest_size
);
267 free_string(dest_name
);
268 free_string(data_name
);
271 static void match_limitted(const char *fn
, struct expression
*expr
,
274 struct expression
*dest
;
275 struct expression
*data
;
276 char *dest_name
= NULL
;
277 struct smatch_state
*state
;
281 dest
= get_argument_from_call_expr(expr
->args
, 0);
282 dest_name
= get_variable_from_expr(dest
, NULL
);
284 data
= get_argument_from_call_expr(expr
->args
, PTR_INT(limit_arg
));
285 if (!get_value(data
, &needed
))
287 state
= get_state(my_id
, dest_name
, NULL
);
288 if (!state
|| !state
->data
)
290 has
= *(int *)state
->data
/ 8;
292 sm_msg("error: %s too small for %lld bytes.", dest_name
,
295 free_string(dest_name
);
298 static void match_array_func(const char *fn
, struct expression
*expr
, void *info
)
300 struct bound
*bound_info
= (struct bound
*)info
;
301 struct expression
*arg
;
304 arg
= get_argument_from_call_expr(expr
->args
, bound_info
->param
);
305 if (!get_implied_value(arg
, &offset
))
307 if (offset
>= bound_info
->size
)
308 sm_msg("buffer overflow calling %s. param %d. %lld >= %d", fn
, bound_info
->param
, offset
, bound_info
->size
);
311 static void register_array_funcs(void)
315 struct bound
*bound_info
;
317 token
= get_tokens_file("kernel.array_bounds");
320 if (token_type(token
) != TOKEN_STREAMBEGIN
)
323 while (token_type(token
) != TOKEN_STREAMEND
) {
324 bound_info
= malloc(sizeof(*bound_info
));
325 if (token_type(token
) != TOKEN_IDENT
)
327 func
= show_ident(token
->ident
);
329 if (token_type(token
) != TOKEN_NUMBER
)
331 bound_info
->param
= atoi(token
->number
);
333 if (token_type(token
) != TOKEN_NUMBER
)
335 bound_info
->size
= atoi(token
->number
);
336 add_function_hook(func
, &match_array_func
, bound_info
);
342 void check_overflow(int id
)
345 add_hook(&match_function_def
, FUNC_DEF_HOOK
);
346 add_hook(&match_declaration
, DECLARATION_HOOK
);
347 add_hook(&array_check
, OP_HOOK
);
348 add_hook(&match_string_assignment
, ASSIGNMENT_HOOK
);
349 add_function_assign_hook("malloc", &match_malloc
, NULL
);
350 add_function_hook("strcpy", &match_strcpy
, NULL
);
351 add_function_hook("strncpy", &match_limitted
, (void *)2);
352 if (option_project
== PROJ_KERNEL
) {
353 add_function_assign_hook("kmalloc", &match_malloc
, NULL
);
354 add_function_assign_hook("kzalloc", &match_malloc
, NULL
);
355 add_function_assign_hook("vmalloc", &match_malloc
, NULL
);
356 add_function_hook("copy_to_user", &match_limitted
, (void *)2);
357 add_function_hook("copy_from_user", &match_limitted
, (void *)2);
359 register_array_funcs();