2 * sparse/check_frees_argument.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
11 * This script is for finding functions like hcd_buffer_free() which free
12 * their arguments. After running it, add those functions to check_memory.c
16 #include "smatch_slist.h"
22 static struct symbol
*this_func
;
23 static struct tracker_list
*freed_args
= NULL
;
25 static void match_function_def(struct symbol
*sym
)
30 static int is_arg(char *name
, struct symbol
*sym
)
35 FOR_EACH_PTR(this_func
->ctype
.base_type
->arguments
, arg
) {
36 arg_name
= (arg
->ident
?arg
->ident
->name
:"-");
37 if (sym
== arg
&& !strcmp(name
, arg_name
))
39 } END_FOR_EACH_PTR(arg
);
43 static int parent_is_arg(struct symbol
*sym
)
47 FOR_EACH_PTR(this_func
->ctype
.base_type
->arguments
, arg
) {
50 } END_FOR_EACH_PTR(arg
);
54 static void match_put(const char *fn
, struct expression
*expr
, void *info
)
56 struct expression
*tmp
;
60 tmp
= get_argument_from_call_expr(expr
->args
, 0);
61 tmp
= strip_expr(tmp
);
62 name
= get_variable_from_expr(tmp
, &sym
);
64 if (parent_is_arg(sym
) && sym
->ident
)
65 set_state(sym
->ident
->name
, my_id
, sym
, &freed
);
68 static void match_kfree(const char *fn
, struct expression
*expr
, void *info
)
70 struct expression
*tmp
;
74 tmp
= get_argument_from_call_expr(expr
->args
, 0);
75 tmp
= strip_expr(tmp
);
76 name
= get_variable_from_expr(tmp
, &sym
);
77 if (is_arg(name
, sym
)) {
78 set_state(name
, my_id
, sym
, &freed
);
83 static int return_count
= 0;
84 static void match_return(struct statement
*stmt
)
86 struct state_list
*slist
;
88 struct tracker
*tracker
;
91 slist
= get_all_states(my_id
);
92 FOR_EACH_PTR(slist
, tmp
) {
93 if (tmp
->state
== &freed
)
94 add_tracker(&freed_args
, tmp
->name
, my_id
,
96 } END_FOR_EACH_PTR(tmp
);
99 FOR_EACH_PTR(freed_args
, tracker
) {
100 tmp
= get_sm_state(tracker
->name
, my_id
, tracker
->sym
);
101 if (tmp
&& tmp
->state
!= &freed
)
102 del_tracker(&freed_args
, tracker
->name
, my_id
,
104 } END_FOR_EACH_PTR(tracker
);
109 static void print_arg(struct symbol
*sym
)
114 FOR_EACH_PTR(this_func
->ctype
.base_type
->arguments
, arg
) {
116 printf("info: free_arg %s %d\n", get_function(), i
);
120 } END_FOR_EACH_PTR(arg
);
123 static void match_end_func(struct symbol
*sym
)
125 struct tracker
*tracker
;
130 FOR_EACH_PTR(freed_args
, tracker
) {
131 print_arg(tracker
->sym
);
132 } END_FOR_EACH_PTR(tracker
);
134 free_trackers_and_list(&freed_args
);
138 void check_frees_argument(int id
)
141 add_hook(&match_function_def
, FUNC_DEF_HOOK
);
142 add_function_hook("kfree", &match_kfree
, NULL
);
143 add_function_hook("kobject_put", &match_put
, NULL
);
144 add_function_hook("kref_put", &match_put
, NULL
);
145 add_hook(&match_return
, RETURN_HOOK
);
146 add_hook(&match_end_func
, END_FUNC_HOOK
);