Print this page
11506 smatch resync
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_param_filter.c
+++ new/usr/src/tools/smatch/src/smatch_param_filter.c
1 1 /*
2 2 * Copyright (C) 2012 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 * This is for functions like:
20 20 *
21 21 * void foo(int *x)
22 22 * {
23 23 * if (*x == 42)
24 24 * *x = 0;
25 25 * }
26 26 *
27 27 * The final value of *x depends on the input to the function but with *x == 42
28 28 * filtered out.
29 29 *
30 30 */
31 31
32 32 #include "smatch.h"
33 33 #include "smatch_extra.h"
34 34 #include "smatch_slist.h"
35 35
36 36 static int my_id;
37 37
38 38 static struct stree *start_states;
39 39 static struct stree_stack *saved_stack;
40 40 static void save_start_states(struct statement *stmt)
41 41 {
42 42 start_states = get_all_states_stree(SMATCH_EXTRA);
43 43 }
44 44
45 45 static void free_start_states(void)
46 46 {
47 47 free_stree(&start_states);
48 48 }
49 49
50 50 static void match_save_states(struct expression *expr)
51 51 {
52 52 push_stree(&saved_stack, start_states);
53 53 start_states = NULL;
54 54 }
55 55
56 56 static void match_restore_states(struct expression *expr)
57 57 {
58 58 free_stree(&start_states);
59 59 start_states = pop_stree(&saved_stack);
60 60 }
61 61
62 62 static struct smatch_state *unmatched_state(struct sm_state *sm)
63 63 {
64 64 struct smatch_state *state;
65 65
66 66 if (parent_is_gone_var_sym(sm->name, sm->sym))
67 67 return alloc_estate_empty();
68 68
69 69 state = get_state(SMATCH_EXTRA, sm->name, sm->sym);
70 70 if (state)
71 71 return state;
72 72 return alloc_estate_whole(estate_type(sm->state));
73 73 }
74 74
75 75 static void pre_merge_hook(struct sm_state *sm)
76 76 {
77 77 struct smatch_state *extra, *mine;
78 78 struct range_list *rl;
79 79
80 80 if (estate_rl(sm->state))
81 81 return;
82 82
83 83 extra = get_state(SMATCH_EXTRA, sm->name, sm->sym);
84 84 if (!extra)
85 85 return;
86 86 mine = get_state(my_id, sm->name, sm->sym);
87 87
88 88 rl = rl_intersection(estate_rl(extra), estate_rl(mine));
89 89 if (rl_equiv(rl, estate_rl(mine)))
90 90 return;
91 91 set_state(my_id, sm->name, sm->sym, alloc_estate_rl(clone_rl(rl)));
92 92 }
93 93
94 94 static void extra_mod_hook(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
95 95 {
96 96 int param;
97 97
98 98 if (__in_fake_assign)
99 99 return;
100 100
101 101 param = get_param_num_from_sym(sym);
102 102 if (param < 0)
103 103 return;
104 104
105 105 /* on stack parameters are handled in smatch_param_limit.c */
106 106 if (sym->ident && strcmp(sym->ident->name, name) == 0)
107 107 return;
108 108
109 109 set_state(my_id, name, sym, alloc_estate_empty());
110 110 }
111 111
112 112 /*
113 113 * This relies on the fact that these states are stored so that
114 114 * foo->bar is before foo->bar->baz.
115 115 */
116 116 static int parent_set(struct string_list *list, const char *name)
117 117 {
118 118 char *tmp;
119 119 int len;
120 120 int ret;
121 121
122 122 FOR_EACH_PTR(list, tmp) {
123 123 len = strlen(tmp);
124 124 ret = strncmp(tmp, name, len);
125 125 if (ret < 0)
126 126 continue;
127 127 if (ret > 0)
128 128 return 0;
129 129 if (name[len] == '-')
130 130 return 1;
131 131 } END_FOR_EACH_PTR(tmp);
132 132
133 133 return 0;
134 134 }
135 135
136 136 static void print_one_mod_param(int return_id, char *return_ranges,
137 137 int param, struct sm_state *sm, struct string_list **totally_filtered)
138 138 {
139 139 const char *param_name;
140 140
↓ open down ↓ |
140 lines elided |
↑ open up ↑ |
141 141 param_name = get_param_name(sm);
142 142 if (!param_name)
143 143 return;
144 144 if (is_whole_rl(estate_rl(sm->state)))
145 145 return;
146 146 if (!estate_rl(sm->state)) {
147 147 insert_string(totally_filtered, (char *)sm->name);
148 148 return;
149 149 }
150 150
151 + if (is_ignored_kernel_data(param_name)) {
152 + insert_string(totally_filtered, (char *)sm->name);
153 + return;
154 + }
155 +
151 156 sql_insert_return_states(return_id, return_ranges, PARAM_FILTER, param,
152 157 param_name, show_rl(estate_rl(sm->state)));
153 158 }
154 159
155 160 static void print_return_value_param(int return_id, char *return_ranges, struct expression *expr)
156 161 {
157 162 struct sm_state *tmp;
158 163 struct sm_state *sm;
159 164 struct string_list *totally_filtered = NULL;
160 165 int param;
161 166
162 167 FOR_EACH_MY_SM(SMATCH_EXTRA, __get_cur_stree(), tmp) {
163 168 param = get_param_num_from_sym(tmp->sym);
164 169 if (param < 0)
165 170 continue;
166 171
167 172 /* on stack parameters are handled in smatch_param_limit.c */
168 173 if (tmp->sym->ident && strcmp(tmp->sym->ident->name, tmp->name) == 0)
169 174 continue;
170 175
171 176 if (parent_set(totally_filtered, tmp->name))
172 177 continue;
173 178
174 179 sm = get_sm_state(my_id, tmp->name, tmp->sym);
175 180 if (sm)
176 181 print_one_mod_param(return_id, return_ranges, param, sm, &totally_filtered);
177 182 } END_FOR_EACH_SM(tmp);
178 183
179 184 free_ptr_list((struct ptr_list **)&totally_filtered);
180 185 }
181 186
182 187 int param_has_filter_data(struct sm_state *sm)
183 188 {
184 189 struct smatch_state *state;
185 190
186 191 state = get_state(my_id, sm->name, sm->sym);
187 192 if (!state) {
188 193 if (get_assigned_expr_name_sym(sm->name, sm->sym))
189 194 return 0;
190 195 return 1;
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
191 196 }
192 197 if (estate_rl(state))
193 198 return 1;
194 199 return 0;
195 200 }
196 201
197 202 void register_param_filter(int id)
198 203 {
199 204 my_id = id;
200 205
206 + set_dynamic_states(my_id);
201 207 add_hook(&save_start_states, AFTER_DEF_HOOK);
202 208 add_hook(&free_start_states, AFTER_FUNC_HOOK);
203 209
204 210 add_extra_mod_hook(&extra_mod_hook);
205 211 add_unmatched_state_hook(my_id, &unmatched_state);
206 212 add_pre_merge_hook(my_id, &pre_merge_hook);
207 213 add_merge_hook(my_id, &merge_estates);
208 214
209 215 add_hook(&match_save_states, INLINE_FN_START);
210 216 add_hook(&match_restore_states, INLINE_FN_END);
211 217
212 218 add_split_return_callback(&print_return_value_param);
213 219 }
214 220
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX