2 * Copyright (C) 2009 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
19 * This script is for finding functions like hcd_buffer_free() which free
20 * their arguments. After running it, add those functions to check_memory.c
24 #include "smatch_slist.h"
30 static struct symbol
*this_func
;
31 static struct tracker_list
*freed_args
= NULL
;
33 static void match_function_def(struct symbol
*sym
)
38 static int is_arg(char *name
, struct symbol
*sym
)
43 FOR_EACH_PTR(this_func
->ctype
.base_type
->arguments
, arg
) {
44 arg_name
= (arg
->ident
?arg
->ident
->name
:"-");
45 if (sym
== arg
&& !strcmp(name
, arg_name
))
47 } END_FOR_EACH_PTR(arg
);
51 static void match_kfree(const char *fn
, struct expression
*expr
, void *info
)
53 struct expression
*tmp
;
57 tmp
= get_argument_from_call_expr(expr
->args
, 0);
58 tmp
= strip_expr(tmp
);
59 name
= expr_to_var_sym(tmp
, &sym
);
60 if (is_arg(name
, sym
)) {
61 set_state(my_id
, name
, sym
, &freed
);
66 static int return_count
= 0;
67 static void match_return(struct expression
*ret_value
)
71 struct tracker
*tracker
;
77 stree
= __get_cur_stree();
78 FOR_EACH_MY_SM(my_id
, stree
, tmp
) {
79 if (tmp
->state
== &freed
)
80 add_tracker(&freed_args
, my_id
, tmp
->name
,
82 } END_FOR_EACH_SM(tmp
);
84 FOR_EACH_PTR(freed_args
, tracker
) {
85 tmp
= get_sm_state(my_id
, tracker
->name
, tracker
->sym
);
86 if (tmp
&& tmp
->state
!= &freed
)
87 del_tracker(&freed_args
, my_id
, tracker
->name
,
89 } END_FOR_EACH_PTR(tracker
);
93 static void print_arg(struct symbol
*sym
)
98 FOR_EACH_PTR(this_func
->ctype
.base_type
->arguments
, arg
) {
100 sm_info("free_arg %s %d", get_function(), i
);
104 } END_FOR_EACH_PTR(arg
);
107 static void match_end_func(struct symbol
*sym
)
115 static void match_after_func(struct symbol
*sym
)
117 struct tracker
*tracker
;
122 FOR_EACH_PTR(freed_args
, tracker
) {
123 print_arg(tracker
->sym
);
124 } END_FOR_EACH_PTR(tracker
);
126 free_trackers_and_list(&freed_args
);
130 void check_frees_argument(int id
)
136 add_hook(&match_function_def
, FUNC_DEF_HOOK
);
137 if (option_project
== PROJ_KERNEL
)
138 add_function_hook("kfree", &match_kfree
, NULL
);
140 add_function_hook("free", &match_kfree
, NULL
);
141 add_hook(&match_return
, RETURN_HOOK
);
142 add_hook(&match_end_func
, END_FUNC_HOOK
);
143 add_hook(&match_after_func
, AFTER_FUNC_HOOK
);