db: caller info needs to record the -1 parameters
[smatch.git] / check_free.c
blob5bd4775f56022cf33c55b9a47fdc1735bb21f8bc
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(const char *name, struct symbol *sym, struct expression *expr, void *unused)
25 set_state(my_id, name, sym, &ok);
28 static int is_freed(struct expression *expr)
30 struct sm_state *sm;
32 sm = get_sm_state_expr(my_id, expr);
33 if (sm && slist_has_state(sm->possible, &freed))
34 return 1;
35 return 0;
38 static void match_symbol(struct expression *expr)
40 char *name;
42 if (!is_freed(expr))
43 return;
44 name = get_variable_from_expr(expr, NULL);
45 sm_msg("warn: '%s' was already freed.", name);
46 free_string(name);
49 static void match_dereferences(struct expression *expr)
51 char *name;
53 if (expr->type != EXPR_PREOP)
54 return;
55 expr = strip_expr(expr->unop);
57 if (!is_freed(expr))
58 return;
59 name = get_variable_from_expr(expr, NULL);
60 sm_msg("error: dereferencing freed memory '%s'", name);
61 set_state_expr(my_id, expr, &ok);
62 free_string(name);
65 static void match_free(const char *fn, struct expression *expr, void *param)
67 struct expression *arg;
69 arg = get_argument_from_call_expr(expr->args, PTR_INT(param));
70 if (!arg)
71 return;
72 /* option_spammy already prints a warning here */
73 if (!option_spammy && is_freed(arg)) {
74 char *name = get_variable_from_expr(arg, NULL);
76 sm_msg("error: double free of '%s'", name);
77 free_string(name);
79 set_state_expr(my_id, arg, &freed);
82 void check_free(int id)
84 my_id = id;
86 if (option_project == PROJ_KERNEL)
87 add_function_hook("kfree", &match_free, (void *)0);
88 else
89 add_function_hook("free", &match_free, (void *)0);
91 if (option_spammy)
92 add_hook(&match_symbol, SYM_HOOK);
93 else
94 add_hook(&match_dereferences, DEREF_HOOK);
96 set_default_modification_hook(my_id, ok_to_use);