1 /* 2 * Copyright (C) 2010 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 "smatch.h" 19 20 static int my_id; 21 static struct symbol *func_sym; 22 23 STATE(argument); 24 STATE(ok); 25 26 static void set_ok(struct sm_state *sm, struct expression *mod_expr) 27 { 28 if (sm->state != &ok) 29 set_state(my_id, sm->name, sm->sym, &ok); 30 } 31 32 static void match_function_def(struct symbol *sym) 33 { 34 struct symbol *arg; 35 36 func_sym = sym; 37 FOR_EACH_PTR(func_sym->ctype.base_type->arguments, arg) { 38 if (!arg->ident) { 39 continue; 40 } 41 set_state(my_id, arg->ident->name, arg, &argument); 42 } END_FOR_EACH_PTR(arg); 43 } 44 45 static int get_arg_num(struct expression *expr) 46 { 47 struct smatch_state *state; 48 struct symbol *arg; 49 struct symbol *this_arg; 50 int i; 51 52 expr = strip_expr(expr); 53 if (expr->type != EXPR_SYMBOL) 54 return -1; 55 this_arg = expr->symbol; 56 57 state = get_state_expr(my_id, expr); 58 if (!state || state != &argument) 59 return -1; 60 61 i = 0; 62 FOR_EACH_PTR(func_sym->ctype.base_type->arguments, arg) { 63 if (arg == this_arg) 64 return i; 65 i++; 66 } END_FOR_EACH_PTR(arg); 67 68 return -1; 69 } 70 71 static void match_is_err(const char *fn, struct expression *expr, void *unused) 72 { 73 struct expression *arg; 74 int arg_num; 75 76 arg = get_argument_from_call_expr(expr->args, 0); 77 arg_num = get_arg_num(arg); 78 if (arg_num < 0) 79 return; 80 sm_msg("info: expects ERR_PTR %d", arg_num); 81 } 82 83 void check_expects_err_ptr(int id) 84 { 85 if (option_project != PROJ_KERNEL) 86 return; 87 if (!option_info) 88 return; 89 90 my_id = id; 91 add_hook(&match_function_def, FUNC_DEF_HOOK); 92 add_modification_hook(my_id, &set_ok); 93 add_function_hook("IS_ERR", &match_is_err, NULL); 94 } 95