1 /* 2 * Copyright (C) 2017 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 21 static int find_param_eq(struct expression *expr, int size) 22 { 23 struct expression *arg; 24 sval_t val; 25 int i; 26 27 i = -1; 28 FOR_EACH_PTR(expr->args, arg) { 29 i++; 30 if (!get_implied_value(arg, &val)) 31 continue; 32 if (val.value == size) 33 return i; 34 } END_FOR_EACH_PTR(arg); 35 36 return -1; 37 } 38 39 static void match_call(struct expression *expr) 40 { 41 struct expression *arg; 42 struct symbol *type, *arg_type; 43 int size, bytes; 44 int i, nr; 45 char buf[16]; 46 char elem_count[8]; 47 char byte_count[8]; 48 49 snprintf(elem_count, sizeof(elem_count), "%d", ELEM_COUNT); 50 snprintf(byte_count, sizeof(byte_count), "%d", BYTE_COUNT); 51 52 i = -1; 53 FOR_EACH_PTR(expr->args, arg) { 54 i++; 55 type = get_type(arg); 56 if (!type || (type->type != SYM_PTR && type->type != SYM_ARRAY)) 57 continue; 58 arg_type = get_arg_type(expr->fn, i); 59 if (arg_type != type) 60 continue; 61 62 size = get_array_size(arg); 63 if (size > 0) { 64 nr = find_param_eq(expr, size); 65 if (nr >= 0) { 66 snprintf(buf, sizeof(buf), "==$%d", nr); 67 sql_insert_caller_info(expr, ELEM_COUNT, i, buf, elem_count); 68 continue; 69 } 70 } 71 bytes = get_array_size_bytes(arg); 72 if (bytes > 0) { 73 nr = find_param_eq(expr, bytes); 74 if (nr >= 0) { 75 snprintf(buf, sizeof(buf), "==$%d", nr); 76 sql_insert_caller_info(expr, BYTE_COUNT, i, buf, byte_count); 77 continue; 78 } 79 } 80 } END_FOR_EACH_PTR(arg); 81 } 82 83 void register_passes_array_size(int id) 84 { 85 add_hook(&match_call, FUNCTION_CALL_HOOK); 86 } 87 88