Print this page
11506 smatch resync
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_about_fn_ptr_arg.c
+++ new/usr/src/tools/smatch/src/smatch_about_fn_ptr_arg.c
1 1 /*
2 2 * Copyright (C) 2017 Oracle.
3 3 *
4 4 * This program is free software; you can redistribute it and/or
5 5 * modify it under the terms of the GNU General Public License
6 6 * as published by the Free Software Foundation; either version 2
7 7 * of the License, or (at your option) any later version.
8 8 *
9 9 * This program is distributed in the hope that it will be useful,
10 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 * GNU General Public License for more details.
13 13 *
14 14 * You should have received a copy of the GNU General Public License
15 15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
16 16 */
17 17
18 18 /*
19 19 * Say you have assign a function to a function pointer and you assign a
20 20 * pointer to the data argument then we want to record some information about
21 21 * the argument. Right now what I mainly want to record is the type of it, I
22 22 * guess.
23 23 *
24 24 */
25 25
26 26 #include "smatch.h"
27 27 #include "smatch_extra.h"
28 28 #include "smatch_slist.h"
29 29 #include <ctype.h>
30 30
31 31 static int my_id;
32 32
33 33 static int assigns_parameters(struct expression *fn, struct expression *arg)
34 34 {
35 35 int fn_param, arg_param;
36 36 char buf[32];
37 37
38 38 fn_param = get_param_num(fn);
39 39 if (fn_param < 0)
40 40 return 0;
41 41
42 42 arg_param = get_param_num(arg);
43 43 if (arg_param < 0)
44 44 return 0;
45 45
46 46 snprintf(buf, sizeof(buf), "%d", arg_param);
47 47 sql_insert_return_implies(FN_ARG_LINK, fn_param, "$", buf);
48 48 return 1;
49 49 }
50 50
51 51 static void link_function_arg(struct expression *fn, int param, struct expression *arg)
52 52 {
53 53 struct symbol *type;
54 54
55 55 if (!fn || !arg)
56 56 return;
57 57 if (assigns_parameters(fn, arg))
58 58 return;
59 59
60 60 type = get_type(arg);
61 61 if (!type || type->type != SYM_PTR)
62 62 return;
63 63 type = get_real_base_type(type);
64 64 if (!type)
65 65 return;
66 66 // FIXME: param shouldn't always be 0?
67 67 sql_insert_fn_data_link(fn, PASSES_TYPE, param, "$", type_to_str(type));
68 68 }
69 69
70 70 char *next_param_name;
71 71 struct symbol *next_param_sym;
72 72 struct expression *next_fn;
73 73 static void match_assign_param(struct expression *expr)
74 74 {
75 75 struct symbol *sym;
76 76 char *name;
77 77
78 78 if (!next_param_name)
79 79 return;
80 80
81 81 name = expr_to_var_sym(expr->left, &sym);
82 82 if (!name || !sym) {
83 83 free_string(name);
84 84 return;
85 85 }
86 86
87 87 if (sym != next_param_sym ||
88 88 strcmp(name, next_param_name) != 0)
89 89 return;
90 90
91 91 link_function_arg(next_fn, 0, strip_expr(expr->right));
92 92
93 93 next_param_name = 0;
94 94 next_param_sym = NULL;
95 95 next_fn = NULL;
96 96 }
97 97
98 98 static int get_arg_ptr(void *_arg_ptr, int argc, char **argv, char **azColName)
99 99 {
100 100 char **arg_ptr = _arg_ptr;
101 101
102 102 *arg_ptr = NULL;
103 103 if (argc != 1)
104 104 return 0;
105 105 *arg_ptr = alloc_string(argv[0]);
106 106 return 0;
107 107 }
108 108
109 109 static char *get_data_member(char *fn_member, struct expression *expr, struct symbol **sym)
110 110 {
111 111 struct symbol *tmp_sym;
112 112 char *fn_str;
113 113 char *arg_ptr = NULL;
114 114 char *end_type;
115 115 int len_ptr, len_str;
116 116 char buf[128];
117 117
118 118 *sym = NULL;
119 119 run_sql(get_arg_ptr, &arg_ptr,
120 120 "select data from fn_ptr_data_link where fn_ptr = '%s';", fn_member);
121 121 if (!arg_ptr)
122 122 return NULL;
123 123 end_type = strchr(arg_ptr, '>');
124 124 if (!end_type)
125 125 return NULL;
126 126 end_type++;
127 127 fn_str = expr_to_var_sym(expr, &tmp_sym);
128 128 if (!fn_str || !tmp_sym)
129 129 return NULL;
130 130 len_ptr = strlen(fn_member);
131 131 len_str = strlen(fn_str);
↓ open down ↓ |
131 lines elided |
↑ open up ↑ |
132 132 while (len_str > 0 && len_ptr > 0) {
133 133 if (fn_str[len_str - 1] != fn_member[len_ptr - 1])
134 134 break;
135 135 if (fn_str[len_str - 1] == '>')
136 136 break;
137 137 len_str--;
138 138 len_ptr--;
139 139 }
140 140
141 141 strncpy(buf, fn_str, sizeof(buf));
142 - snprintf(buf + len_str, sizeof(buf) - len_str, end_type);
142 + snprintf(buf + len_str, sizeof(buf) - len_str, "%s", end_type);
143 143 *sym = tmp_sym;
144 144 return alloc_string(buf);
145 145 }
146 146
147 147 static void match_assign_function(struct expression *expr)
148 148 {
149 149 struct expression *right, *arg;
150 150 struct symbol *sym;
151 151 char *data_member;
152 152 struct symbol *type;
153 153 char *member_name;
154 154
155 155 right = strip_expr(expr->right);
156 156 if (right->type == EXPR_PREOP && right->op == '&')
157 157 right = strip_expr(right->unop);
158 158
159 159 type = get_type(right);
160 160 if (type && type->type == SYM_PTR)
161 161 type = get_real_base_type(type);
162 162 if (!type || type->type != SYM_FN)
163 163 return;
164 164
165 165 member_name = get_member_name(expr->left);
166 166 if (!member_name)
167 167 return;
168 168
169 169 data_member = get_data_member(member_name, expr->left, &sym);
170 170 if (!data_member || !sym) {
171 171 free_string(data_member);
172 172 data_member = NULL;
173 173 }
174 174
175 175 arg = get_assigned_expr_name_sym(data_member, sym);
176 176 if (arg) {
177 177 link_function_arg(right, 0, arg);
178 178 } else {
179 179 next_param_name = data_member;
180 180 next_param_sym = sym;
181 181 next_fn = right;
182 182 }
183 183 }
184 184
185 185 static int is_recursive_call(struct expression *call)
186 186 {
187 187 if (call->fn->type != EXPR_SYMBOL)
188 188 return 0;
189 189 if (call->fn->symbol == cur_func_sym)
190 190 return 1;
191 191 return 0;
192 192 }
193 193
194 194 static void check_passes_fn_and_data(struct expression *call, struct expression *fn, char *key, char *value)
195 195 {
196 196 struct expression *arg;
197 197 struct symbol *type;
198 198 int data_nr;
199 199
200 200 if (is_recursive_call(call))
201 201 return;
202 202
203 203 type = get_type(fn);
204 204 if (!type || type->type != SYM_FN)
205 205 return;
206 206
207 207 if (!isdigit(value[0]))
208 208 return;
209 209 data_nr = atoi(value);
210 210 arg = get_argument_from_call_expr(call->args, data_nr);
211 211 if (!arg)
212 212 return;
213 213 link_function_arg(fn, 0, arg);
214 214 }
215 215
216 216 static void match_end_func(struct symbol *sym)
217 217 {
218 218 next_param_sym = NULL;
219 219 next_fn = NULL;
220 220 }
221 221
222 222 void register_about_fn_ptr_arg(int id)
223 223 {
224 224 my_id = id;
225 225
226 226 if (0 && !option_info)
227 227 return;
228 228 add_hook(match_assign_param, ASSIGNMENT_HOOK);
229 229 add_hook(match_assign_function, ASSIGNMENT_HOOK);
230 230 select_return_implies_hook(FN_ARG_LINK, &check_passes_fn_and_data);
231 231 add_hook(&match_end_func, END_FUNC_HOOK);
232 232 }
↓ open down ↓ |
80 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX