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 
find_param_eq(struct expression * expr,int size)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 
match_call(struct expression * expr)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 
register_passes_array_size(int id)83 void register_passes_array_size(int id)
84 {
85 	add_hook(&match_call, FUNCTION_CALL_HOOK);
86 }
87 
88