flow: introduce definite_inside_loop()
[smatch.git] / check_free.c
blob5823aef76df2caf424252804cc7bc8be61a2629b
1 /*
2 * sparse/check_free.c
4 * Copyright (C) 2010 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
11 * check_memory() is getting too big and messy.
15 #include "smatch.h"
16 #include "smatch_slist.h"
18 static int my_id;
20 STATE(freed);
21 STATE(ok);
23 static void ok_to_use(struct sm_state *sm, struct expression *mod_expr)
25 if (sm->state != &ok)
26 set_state(my_id, sm->name, sm->sym, &ok);
29 static int is_freed(struct expression *expr)
31 struct sm_state *sm;
33 sm = get_sm_state_expr(my_id, expr);
34 if (sm && slist_has_state(sm->possible, &freed))
35 return 1;
36 return 0;
39 static void match_symbol(struct expression *expr)
41 char *name;
43 if (!is_freed(expr))
44 return;
45 name = expr_to_var(expr);
46 sm_msg("warn: '%s' was already freed.", name);
47 free_string(name);
50 static void match_dereferences(struct expression *expr)
52 char *name;
54 if (expr->type != EXPR_PREOP)
55 return;
56 expr = strip_expr(expr->unop);
58 if (!is_freed(expr))
59 return;
60 name = expr_to_var_sym(expr, NULL);
61 sm_msg("error: dereferencing freed memory '%s'", name);
62 set_state_expr(my_id, expr, &ok);
63 free_string(name);
66 static void match_free(const char *fn, struct expression *expr, void *param)
68 struct expression *arg;
70 arg = get_argument_from_call_expr(expr->args, PTR_INT(param));
71 if (!arg)
72 return;
73 /* option_spammy already prints a warning here */
74 if (!option_spammy && is_freed(arg)) {
75 char *name = expr_to_var_sym(arg, NULL);
77 sm_msg("error: double free of '%s'", name);
78 free_string(name);
80 set_state_expr(my_id, arg, &freed);
83 static void set_param_freed(struct expression *arg, char *unused)
85 set_state_expr(my_id, arg, &freed);
88 void check_free(int id)
90 my_id = id;
92 if (option_project == PROJ_KERNEL) {
93 add_function_hook("kfree", &match_free, INT_PTR(0));
94 add_function_hook("kmem_cache_free", &match_free, INT_PTR(1));
95 } else {
96 add_function_hook("free", &match_free, INT_PTR(0));
99 if (option_spammy)
100 add_hook(&match_symbol, SYM_HOOK);
101 else
102 add_hook(&match_dereferences, DEREF_HOOK);
104 add_modification_hook(my_id, &ok_to_use);
105 select_call_implies_hook(PARAM_FREED, &set_param_freed);