1 /* 2 * Copyright (C) 2014 Oracle. 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 /* 19 * This file is sort of like check_dereferences_param.c. In theory the one 20 * difference should be that the param is NULL it should still be counted as a 21 * free. But for now I don't handle that case. 22 */ 23 24 #include "smatch.h" 25 #include "smatch_extra.h" 26 #include "smatch_slist.h" 27 28 static int my_id; 29 30 STATE(freed); 31 STATE(ignore); 32 33 static void set_ignore(struct sm_state *sm, struct expression *mod_expr) 34 { 35 set_state(my_id, sm->name, sm->sym, &ignore); 36 } 37 38 static void freed_variable(struct expression *expr) 39 { 40 struct sm_state *sm; 41 42 expr = strip_expr(expr); 43 if (get_param_num(expr) < 0) 44 return; 45 46 sm = get_sm_state_expr(my_id, expr); 47 if (sm && slist_has_state(sm->possible, &ignore)) 48 return; 49 set_state_expr(my_id, expr, &freed); 50 } 51 52 static void match_free(const char *fn, struct expression *expr, void *param) 53 { 54 struct expression *arg; 55 56 arg = get_argument_from_call_expr(expr->args, PTR_INT(param)); 57 if (!arg) 58 return; 59 freed_variable(arg); 60 } 61 62 static void set_param_freed(struct expression *call, struct expression *arg, char *key, char *unused) 63 { 64 /* XXX FIXME: return_implies has been updated with more information */ 65 if (strcmp(key, "$") != 0) 66 return; 67 freed_variable(arg); 68 } 69 70 static void process_states(void) 71 { 72 struct sm_state *sm; 73 int param; 74 const char *param_name; 75 76 FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) { 77 if (sm->state != &freed) 78 continue; 79 param = get_param_num_from_sym(sm->sym); 80 if (param < 0) 81 continue; 82 param_name = get_param_name(sm); 83 if (!param_name) 84 continue; 85 sql_insert_return_implies(PARAM_FREED, param, param_name, "1"); 86 } END_FOR_EACH_SM(sm); 87 88 } 89 90 void check_frees_param(int id) 91 { 92 my_id = id; 93 94 if (option_project == PROJ_KERNEL) { 95 /* The kernel uses check_frees_param_strict.c */ 96 return; 97 } 98 99 add_function_hook("free", &match_free, INT_PTR(0)); 100 101 select_return_implies_hook(PARAM_FREED, &set_param_freed); 102 add_modification_hook(my_id, &set_ignore); 103 104 all_return_states_hook(&process_states); 105 } 106