2 * Copyright (C) 2012 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 * The point here is to store that a buffer has x bytes even if we don't know
25 #include "smatch_extra.h"
26 #include "smatch_slist.h"
32 * We need this for code which does:
37 * We want to record that the size of "foo" is "size" even after the merge.
40 static struct smatch_state
*unmatched_state(struct sm_state
*sm
)
42 struct expression
*size_expr
;
47 size_expr
= sm
->state
->data
;
48 if (!get_implied_value(size_expr
, &sval
) || sval
.value
!= 0)
53 static struct smatch_state
*merge_links(struct smatch_state
*s1
, struct smatch_state
*s2
)
55 struct expression
*expr1
, *expr2
;
60 if (expr1
&& expr2
&& expr_equiv(expr1
, expr2
))
65 static void match_link_modify(struct sm_state
*sm
, struct expression
*mod_expr
)
67 struct expression
*expr
;
70 expr
= sm
->state
->data
;
72 set_state_expr(size_id
, expr
, &undefined
);
73 set_state(link_id
, sm
->name
, sm
->sym
, &undefined
);
77 FOR_EACH_PTR(sm
->possible
, tmp
) {
78 expr
= tmp
->state
->data
;
80 set_state_expr(size_id
, expr
, &undefined
);
81 } END_FOR_EACH_PTR(tmp
);
82 set_state(link_id
, sm
->name
, sm
->sym
, &undefined
);
85 static struct smatch_state
*alloc_expr_state(struct expression
*expr
)
87 struct smatch_state
*state
;
90 state
= __alloc_smatch_state(0);
91 expr
= strip_expr(expr
);
92 name
= expr_to_str(expr
);
93 state
->name
= alloc_sname(name
);
99 static int bytes_per_element(struct expression
*expr
)
103 type
= get_type(expr
);
107 if (type
->type
!= SYM_PTR
&& type
->type
!= SYM_ARRAY
)
110 type
= get_base_type(type
);
111 return type_bytes(type
);
114 static void db_save_type_links(struct expression
*array
, struct expression
*size
)
116 const char *array_name
;
118 array_name
= get_data_info_name(array
);
121 sql_insert_data_info(size
, ARRAY_LEN
, array_name
);
124 static void match_alloc_helper(struct expression
*pointer
, struct expression
*size
)
126 struct expression
*tmp
;
131 pointer
= strip_expr(pointer
);
132 size
= strip_expr(size
);
133 if (!size
|| !pointer
)
136 while ((tmp
= get_assigned_expr(size
))) {
137 size
= strip_expr(tmp
);
142 if (size
->type
== EXPR_BINOP
&& size
->op
== '*') {
143 struct expression
*mult_left
, *mult_right
;
145 mult_left
= strip_expr(size
->left
);
146 mult_right
= strip_expr(size
->right
);
148 if (get_implied_value(mult_left
, &sval
) &&
149 sval
.value
== bytes_per_element(pointer
))
151 else if (get_implied_value(mult_right
, &sval
) &&
152 sval
.value
== bytes_per_element(pointer
))
158 /* Only save links to variables, not fixed sizes */
159 if (get_value(size
, &sval
))
162 db_save_type_links(pointer
, size
);
163 sm
= set_state_expr(size_id
, pointer
, alloc_expr_state(size
));
166 set_state_expr(link_id
, size
, alloc_expr_state(pointer
));
169 static void match_alloc(const char *fn
, struct expression
*expr
, void *_size_arg
)
171 int size_arg
= PTR_INT(_size_arg
);
172 struct expression
*pointer
, *call
, *arg
;
174 pointer
= strip_expr(expr
->left
);
175 call
= strip_expr(expr
->right
);
176 arg
= get_argument_from_call_expr(call
->args
, size_arg
);
177 match_alloc_helper(pointer
, arg
);
180 static void match_calloc(const char *fn
, struct expression
*expr
, void *_start_arg
)
182 int start_arg
= PTR_INT(_start_arg
);
183 struct expression
*pointer
, *call
, *arg
;
184 struct sm_state
*tmp
;
187 pointer
= strip_expr(expr
->left
);
188 call
= strip_expr(expr
->right
);
189 arg
= get_argument_from_call_expr(call
->args
, start_arg
);
190 if (get_implied_value(arg
, &sval
) &&
191 sval
.value
== bytes_per_element(pointer
))
192 arg
= get_argument_from_call_expr(call
->args
, start_arg
+ 1);
194 db_save_type_links(pointer
, arg
);
195 tmp
= set_state_expr(size_id
, pointer
, alloc_expr_state(arg
));
198 set_state_expr(link_id
, arg
, alloc_expr_state(pointer
));
201 struct expression
*get_size_variable(struct expression
*buf
)
203 struct smatch_state
*state
;
205 state
= get_state_expr(size_id
, buf
);
211 struct expression
*get_array_variable(struct expression
*size
)
213 struct smatch_state
*state
;
215 state
= get_state_expr(link_id
, size
);
221 static void array_check(struct expression
*expr
)
223 struct expression
*array
;
224 struct expression
*size
;
225 struct expression
*offset
;
226 char *array_str
, *offset_str
;
228 expr
= strip_expr(expr
);
232 array
= get_array_base(expr
);
233 size
= get_size_variable(array
);
236 offset
= get_array_offset(expr
);
237 if (!possible_comparison(size
, SPECIAL_EQUAL
, offset
))
240 array_str
= expr_to_str(array
);
241 offset_str
= expr_to_str(offset
);
242 sm_msg("warn: potentially one past the end of array '%s[%s]'", array_str
, offset_str
);
243 free_string(array_str
);
244 free_string(offset_str
);
252 static int db_limitter_callback(void *_info
, int argc
, char **argv
, char **azColName
)
254 struct db_info
*info
= _info
;
257 * If possible the limitters are tied to the struct they limit. If we
258 * aren't sure which struct they limit then we use them as limitters for
261 if (!info
->name
|| argv
[0][0] == '\0' || strcmp(info
->name
, argv
[0]) == 0)
266 static char *vsl_to_data_info_name(const char *name
, struct var_sym_list
*vsl
)
273 if (ptr_list_size((struct ptr_list
*)vsl
) != 1)
275 vs
= first_ptr_list((struct ptr_list
*)vsl
);
277 type
= get_real_base_type(vs
->sym
);
278 if (!type
|| type
->type
!= SYM_PTR
)
280 type
= get_real_base_type(type
);
281 if (!type
|| type
->type
!= SYM_STRUCT
)
287 while ((name
= strstr(p
, "->")))
290 snprintf(buf
, sizeof(buf
),"(struct %s)->%s", type
->ident
->name
, p
);
291 return alloc_sname(buf
);
294 if (!(vs
->sym
->ctype
.modifiers
& MOD_TOPLEVEL
))
296 if (vs
->sym
->ctype
.modifiers
& MOD_STATIC
)
297 snprintf(buf
, sizeof(buf
),"static %s", name
);
299 snprintf(buf
, sizeof(buf
),"global %s", name
);
300 return alloc_sname(buf
);
303 int db_var_is_array_limit(struct expression
*array
, const char *name
, struct var_sym_list
*vsl
)
306 char *array_name
= get_data_info_name(array
);
307 struct db_info db_info
= {.name
= array_name
,};
309 size_name
= vsl_to_data_info_name(name
, vsl
);
313 run_sql(db_limitter_callback
, &db_info
,
314 "select value from data_info where type = %d and data = '%s';",
315 ARRAY_LEN
, size_name
);
320 static int known_access_ok_comparison(struct expression
*expr
)
322 struct expression
*array
;
323 struct expression
*size
;
324 struct expression
*offset
;
327 array
= get_array_base(expr
);
328 size
= get_size_variable(array
);
331 offset
= get_array_offset(expr
);
332 comparison
= get_comparison(size
, offset
);
333 if (comparison
== '>' || comparison
== SPECIAL_UNSIGNED_GT
)
339 static int known_access_ok_numbers(struct expression
*expr
)
341 struct expression
*array
;
342 struct expression
*offset
;
346 array
= get_array_base(expr
);
347 offset
= get_array_offset(expr
);
349 size
= get_array_size(array
);
353 get_absolute_max(offset
, &max
);
354 if (max
.uvalue
< size
)
359 static void array_check_data_info(struct expression
*expr
)
361 struct expression
*array
;
362 struct expression
*offset
;
363 struct state_list
*slist
;
365 struct compare_data
*comp
;
367 const char *equal_name
= NULL
;
369 expr
= strip_expr(expr
);
373 if (known_access_ok_numbers(expr
))
375 if (known_access_ok_comparison(expr
))
378 array
= get_array_base(expr
);
379 offset
= get_array_offset(expr
);
380 offset_name
= expr_to_var(offset
);
383 slist
= get_all_possible_equal_comparisons(offset
);
387 FOR_EACH_PTR(slist
, sm
) {
388 comp
= sm
->state
->data
;
389 if (strcmp(comp
->left_var
, offset_name
) == 0) {
390 if (db_var_is_array_limit(array
, comp
->right_var
, comp
->right_vsl
)) {
391 equal_name
= comp
->right_var
;
394 } else if (strcmp(comp
->right_var
, offset_name
) == 0) {
395 if (db_var_is_array_limit(array
, comp
->left_var
, comp
->left_vsl
)) {
396 equal_name
= comp
->left_var
;
400 } END_FOR_EACH_PTR(sm
);
403 char *array_name
= expr_to_str(array
);
405 sm_msg("warn: potential off by one '%s[]' limit '%s'", array_name
, equal_name
);
406 free_string(array_name
);
411 free_string(offset_name
);
414 static void add_allocation_function(const char *func
, void *call_back
, int param
)
416 add_function_assign_hook(func
, call_back
, INT_PTR(param
));
419 static char *buf_size_param_comparison(struct expression
*array
, struct expression_list
*args
)
421 struct expression
*arg
;
422 struct expression
*size
;
426 size
= get_size_variable(array
);
431 FOR_EACH_PTR(args
, arg
) {
435 if (!expr_equiv(arg
, size
))
437 snprintf(buf
, sizeof(buf
), "==$%d", i
);
439 } END_FOR_EACH_PTR(arg
);
444 static void match_call(struct expression
*call
)
446 struct expression
*arg
;
451 FOR_EACH_PTR(call
->args
, arg
) {
453 if (!is_pointer(arg
))
455 compare
= buf_size_param_comparison(arg
, call
->args
);
458 sql_insert_caller_info(call
, ARRAY_LEN
, param
, "$", compare
);
459 } END_FOR_EACH_PTR(arg
);
462 static int get_param(int param
, char **name
, struct symbol
**sym
)
468 FOR_EACH_PTR(cur_func_sym
->ctype
.base_type
->arguments
, arg
) {
470 * this is a temporary hack to work around a bug (I think in sparse?)
471 * 2.6.37-rc1:fs/reiserfs/journal.o
472 * If there is a function definition without parameter name found
473 * after a function implementation then it causes a crash.
477 if (arg
->ident
->name
< (char *)100)
480 *name
= arg
->ident
->name
;
485 } END_FOR_EACH_PTR(arg
);
490 static void set_param_compare(const char *array_name
, struct symbol
*array_sym
, char *key
, char *value
)
492 struct expression
*array_expr
;
493 struct expression
*size_expr
;
494 struct symbol
*size_sym
;
497 struct sm_state
*tmp
;
499 if (strncmp(value
, "==$", 3) != 0)
501 param
= strtol(value
+ 3, NULL
, 10);
502 if (!get_param(param
, &size_name
, &size_sym
))
504 array_expr
= symbol_expression(array_sym
);
505 size_expr
= symbol_expression(size_sym
);
507 tmp
= set_state_expr(size_id
, array_expr
, alloc_expr_state(size_expr
));
510 set_state_expr(link_id
, size_expr
, alloc_expr_state(array_expr
));
513 static void set_arraysize_arg(const char *array_name
, struct symbol
*array_sym
, char *key
, char *value
)
515 struct expression
*array_expr
;
516 struct expression
*size_expr
;
517 struct symbol
*size_sym
;
520 struct sm_state
*tmp
;
522 param
= strtol(key
, NULL
, 10);
523 if (!get_param(param
, &size_name
, &size_sym
))
525 array_expr
= symbol_expression(array_sym
);
526 size_expr
= symbol_expression(size_sym
);
528 tmp
= set_state_expr(size_id
, array_expr
, alloc_expr_state(size_expr
));
531 set_state_expr(link_id
, size_expr
, alloc_expr_state(array_expr
));
534 static void munge_start_states(struct statement
*stmt
)
536 struct state_list
*slist
= NULL
;
538 struct sm_state
*poss
;
540 FOR_EACH_MY_SM(size_id
, __get_cur_stree(), sm
) {
541 if (sm
->state
!= &merged
)
544 * screw it. let's just assume that if one caller passes the
545 * size then they all do.
547 FOR_EACH_PTR(sm
->possible
, poss
) {
548 if (poss
->state
!= &merged
&&
549 poss
->state
!= &undefined
) {
550 add_ptr_list(&slist
, poss
);
553 } END_FOR_EACH_PTR(poss
);
554 } END_FOR_EACH_SM(sm
);
556 FOR_EACH_PTR(slist
, sm
) {
557 set_state(size_id
, sm
->name
, sm
->sym
, sm
->state
);
558 } END_FOR_EACH_PTR(sm
);
563 void register_buf_comparison(int id
)
567 add_unmatched_state_hook(size_id
, &unmatched_state
);
569 add_allocation_function("malloc", &match_alloc
, 0);
570 add_allocation_function("memdup", &match_alloc
, 1);
571 add_allocation_function("realloc", &match_alloc
, 1);
572 if (option_project
== PROJ_KERNEL
) {
573 add_allocation_function("kmalloc", &match_alloc
, 0);
574 add_allocation_function("kzalloc", &match_alloc
, 0);
575 add_allocation_function("vmalloc", &match_alloc
, 0);
576 add_allocation_function("__vmalloc", &match_alloc
, 0);
577 add_allocation_function("sock_kmalloc", &match_alloc
, 1);
578 add_allocation_function("kmemdup", &match_alloc
, 1);
579 add_allocation_function("kmemdup_user", &match_alloc
, 1);
580 add_allocation_function("dma_alloc_attrs", &match_alloc
, 1);
581 add_allocation_function("pci_alloc_consistent", &match_alloc
, 1);
582 add_allocation_function("pci_alloc_coherent", &match_alloc
, 1);
583 add_allocation_function("devm_kmalloc", &match_alloc
, 1);
584 add_allocation_function("devm_kzalloc", &match_alloc
, 1);
585 add_allocation_function("kcalloc", &match_calloc
, 0);
586 add_allocation_function("devm_kcalloc", &match_calloc
, 1);
587 add_allocation_function("kmalloc_array", &match_calloc
, 0);
588 add_allocation_function("krealloc", &match_alloc
, 1);
591 add_hook(&array_check
, OP_HOOK
);
592 add_hook(&array_check_data_info
, OP_HOOK
);
594 add_hook(&match_call
, FUNCTION_CALL_HOOK
);
595 select_caller_info_hook(set_param_compare
, ARRAY_LEN
);
596 select_caller_info_hook(set_arraysize_arg
, ARRAYSIZE_ARG
);
597 add_hook(&munge_start_states
, AFTER_DEF_HOOK
);
600 void register_buf_comparison_links(int id
)
603 add_merge_hook(link_id
, &merge_links
);
604 add_modification_hook(link_id
, &match_link_modify
);