1 /* 2 * Copyright (C) 2012 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 #include "smatch.h" 19 #include "smatch_extra.h" 20 #include "smatch_slist.h" 21 22 #define NOBUF -2 23 24 static int my_id; 25 26 static struct expression *get_returned_expr(struct expression *expr) 27 { 28 struct statement *stmt; 29 30 stmt = last_ptr_list((struct ptr_list *)big_statement_stack); 31 if (!stmt || stmt->type != STMT_EXPRESSION || !stmt->expression) 32 return NULL; 33 if (stmt->expression->type != EXPR_ASSIGNMENT) 34 return NULL; 35 if (stmt->expression->right != expr) 36 return NULL; 37 return stmt->expression->left; 38 } 39 40 static struct expression *remove_dereference(struct expression *expr) 41 { 42 if (!expr || expr->type != EXPR_PREOP || expr->op != '*') 43 return expr; 44 expr = expr->unop; 45 if (!expr || expr->type != EXPR_PREOP || expr->op != '*') 46 return expr; 47 return expr->unop; 48 } 49 50 static int get_buf_number(struct expression *call, struct expression *size_arg) 51 { 52 struct expression *arg; 53 int idx = -1; 54 55 size_arg = strip_expr(size_arg->cast_expression); 56 size_arg = remove_dereference(size_arg); 57 58 arg = get_returned_expr(call); 59 if (arg && expr_equiv(arg, size_arg)) 60 return idx; 61 62 FOR_EACH_PTR(call->args, arg) { 63 idx++; 64 if (expr_equiv(arg, size_arg)) 65 return idx; 66 } END_FOR_EACH_PTR(arg); 67 68 return NOBUF; 69 } 70 71 static void match_call(struct expression *call) 72 { 73 struct expression *arg; 74 char *name; 75 int buf_nr; 76 int i = -1; 77 78 if (call->fn->type != EXPR_SYMBOL) 79 return; 80 81 name = expr_to_var(call->fn); 82 FOR_EACH_PTR(call->args, arg) { 83 i++; 84 if (arg->type != EXPR_SIZEOF) 85 continue; 86 buf_nr = get_buf_number(call, arg); 87 if (buf_nr == NOBUF) 88 sm_msg("info: sizeof_param '%s' %d", name, i); 89 else 90 sm_msg("info: sizeof_param '%s' %d %d", name, i, buf_nr); 91 } END_FOR_EACH_PTR(arg); 92 free_string(name); 93 } 94 95 void check_passes_sizeof(int id) 96 { 97 if (!option_info) 98 return; 99 100 my_id = id; 101 add_hook(&match_call, FUNCTION_CALL_HOOK); 102 } 103