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;
43 	int size, bytes;
44 	int i, nr;
45 	char buf[16];
46 
47 
48 	i = -1;
49 	FOR_EACH_PTR(expr->args, arg) {
50 		i++;
51 		type = get_type(arg);
52 		if (!type || (type->type != SYM_PTR && type->type != SYM_ARRAY))
53 			continue;
54 		size = get_array_size(arg);
55 		if (size > 0) {
56 			nr = find_param_eq(expr, size);
57 			if (nr >= 0) {
58 				snprintf(buf, sizeof(buf), "%d", nr);
59 				sql_insert_caller_info(expr, ARRAYSIZE_ARG, i, buf, "");
60 				continue;
61 			}
62 		}
63 		bytes = get_array_size_bytes(arg);
64 		if (bytes > 0) {
65 			nr = find_param_eq(expr, bytes);
66 			if (nr >= 0) {
67 				snprintf(buf, sizeof(buf), "%d", nr);
68 				sql_insert_caller_info(expr, SIZEOF_ARG, i, buf, "");
69 				continue;
70 			}
71 		}
72 	} END_FOR_EACH_PTR(arg);
73 }
74 
75 void register_passes_array_size(int id)
76 {
77 	add_hook(&match_call, FUNCTION_CALL_HOOK);
78 }
79 
80