1 /* 2 * Copyright (C) 2009 Dan Carpenter. 3 * 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. 8 * 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. 13 * 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 16 */ 17 18 #include <fcntl.h> 19 #include <unistd.h> 20 #include "parse.h" 21 #include "smatch.h" 22 #include "smatch_slist.h" 23 24 static int my_id; 25 26 /* 27 * Print a list of functions that return newly allocated memory. 28 */ 29 30 static struct tracker_list *allocated; 31 32 static const char *allocation_funcs[] = { 33 "kmalloc", 34 "kzalloc", 35 "kcalloc", 36 "__alloc_skb", 37 NULL, 38 }; 39 40 static void match_allocation(const char *fn, struct expression *expr, 41 void *info) 42 { 43 char *left_name; 44 struct symbol *left_sym; 45 46 left_name = expr_to_var_sym(expr->left, &left_sym); 47 if (!left_name || !left_sym) 48 goto free; 49 if (left_sym->ctype.modifiers & 50 (MOD_NONLOCAL | MOD_STATIC | MOD_ADDRESSABLE)) 51 goto free; 52 add_tracker(&allocated, my_id, left_name, left_sym); 53 free: 54 free_string(left_name); 55 } 56 57 static int returns_new_stuff = 0; 58 static int returns_old_stuff = 0; 59 static void match_return(struct expression *ret_value) 60 { 61 char *name; 62 struct symbol *sym; 63 sval_t tmp; 64 65 if (__inline_fn) 66 return; 67 if (get_value(ret_value, &tmp) && tmp.value == 0) 68 return; 69 returns_new_stuff = 1; 70 name = expr_to_var_sym(ret_value, &sym); 71 if (!name || !sym) { 72 returns_old_stuff = 1; 73 goto free; 74 } 75 if (!in_tracker_list(allocated, my_id, name, sym)) 76 returns_old_stuff = 1; 77 free: 78 free_string(name); 79 } 80 81 static void match_end_func(struct symbol *sym) 82 { 83 if (__inline_fn) 84 return; 85 if (returns_new_stuff && !returns_old_stuff) 86 sm_info("allocation func"); 87 free_trackers_and_list(&allocated); 88 returns_new_stuff = 0; 89 returns_old_stuff = 0; 90 } 91 92 void check_allocation_funcs(int id) 93 { 94 int i; 95 96 if (!option_info || option_project != PROJ_KERNEL) 97 return; 98 99 my_id = id; 100 add_hook(&match_return, RETURN_HOOK); 101 add_hook(&match_end_func, AFTER_FUNC_HOOK); 102 for (i = 0; allocation_funcs[i]; i++) { 103 add_function_assign_hook(allocation_funcs[i], 104 &match_allocation, NULL); 105 } 106 }