6 #include "smatch_slist.h"
7 #include "smatch_extra.h"
9 ALLOCATOR(fcall_back
, "call backs");
11 static struct hsearch_data func_hash
;
13 #define REGULAR_CALL 0
14 #define CONDITIONAL_CALL 1
18 static struct fcall_back
*alloc_fcall_back(int type
, func_hook
*call_back
,
21 struct fcall_back
*cb
;
23 cb
= __alloc_fcall_back(0);
25 cb
->call_back
= call_back
;
30 static struct call_back_list
*get_call_backs(const char *look_for
)
34 e
.key
= (char *)look_for
;
35 hsearch_r(e
, FIND
, &ep
, &func_hash
);
38 return (struct call_back_list
*)ep
->data
;
41 static void add_cb_hook(const char *look_for
, struct fcall_back
*cb
)
46 e
.key
= alloc_string(look_for
);
47 hsearch_r(e
, FIND
, &ep
, &func_hash
);
49 struct call_back_list
*list
= NULL
;
51 add_ptr_list(&list
, cb
);
56 add_ptr_list((struct call_back_list
**)&ep
->data
, cb
);
59 if (!hsearch_r(e
, ENTER
, &ep
, &func_hash
)) {
60 printf("Error hash table too small in smatch_function_hooks.c\n");
66 void add_function_hook(const char *look_for
, func_hook
*call_back
, void *info
)
68 struct fcall_back
*cb
;
70 cb
= alloc_fcall_back(REGULAR_CALL
, call_back
, info
);
71 add_cb_hook(look_for
, cb
);
74 void add_conditional_hook(const char *look_for
, func_hook
*call_back
,
77 struct fcall_back
*cb
;
79 cb
= alloc_fcall_back(CONDITIONAL_CALL
, call_back
, info
);
80 add_cb_hook(look_for
, cb
);
83 void add_function_assign_hook(const char *look_for
, func_hook
*call_back
,
86 struct fcall_back
*cb
;
88 cb
= alloc_fcall_back(ASSIGN_CALL
, call_back
, info
);
89 add_cb_hook(look_for
, cb
);
92 void return_implies_state(const char *look_for
, long long start
, long long end
,
93 func_hook
*call_back
, void *info
)
95 struct fcall_back
*cb
;
97 cb
= alloc_fcall_back(RANGED_CALL
, call_back
, info
);
98 cb
->range
= alloc_range_perm(start
, end
);
99 add_cb_hook(look_for
, cb
);
102 static void call_call_backs(struct call_back_list
*list
, int type
,
103 const char *fn
, struct expression
*expr
)
105 struct fcall_back
*tmp
;
107 FOR_EACH_PTR(list
, tmp
) {
108 if (tmp
->type
== type
)
109 (tmp
->call_back
)(fn
, expr
, tmp
->info
);
110 } END_FOR_EACH_PTR(tmp
);
113 static void match_function_call(struct expression
*expr
)
115 struct call_back_list
*call_backs
;
117 if (expr
->fn
->type
!= EXPR_SYMBOL
|| !expr
->fn
->symbol
)
119 call_backs
= get_call_backs(expr
->fn
->symbol
->ident
->name
);
122 call_call_backs(call_backs
, REGULAR_CALL
, expr
->fn
->symbol
->ident
->name
,
126 static void assign_condition_funcs(const char *fn
, struct expression
*expr
,
127 struct call_back_list
*call_backs
)
129 struct fcall_back
*tmp
;
134 struct smatch_state
*zero_state
, *non_zero_state
;
136 var_name
= get_variable_from_expr(expr
->left
, &sym
);
137 if (!var_name
|| !sym
)
140 __fake_conditions
= 1;
141 FOR_EACH_PTR(call_backs
, tmp
) {
142 if (tmp
->type
!= CONDITIONAL_CALL
)
146 (tmp
->call_back
)(fn
, expr
->right
, tmp
->info
);
147 } END_FOR_EACH_PTR(tmp
);
149 zero_state
= alloc_extra_state(0);
150 non_zero_state
= add_filter(extra_undefined(), 0);
151 set_true_false_states(var_name
, SMATCH_EXTRA
, sym
, non_zero_state
, zero_state
);
153 __fake_conditions
= 0;
158 merge_slist(&__fake_cond_true
, __fake_cond_false
);
160 FOR_EACH_PTR(__fake_cond_true
, sm
) {
162 } END_FOR_EACH_PTR(sm
);
163 free_slist(&__fake_cond_true
);
164 free_slist(&__fake_cond_false
);
166 free_string(var_name
);
169 static struct call_back_list
*get_same_ranged_call_backs(struct call_back_list
*list
,
170 struct data_range
*drange
)
172 struct call_back_list
*ret
= NULL
;
173 struct fcall_back
*tmp
;
175 FOR_EACH_PTR(list
, tmp
) {
176 if (tmp
->range
->min
== drange
->min
&& tmp
->range
->max
== drange
->max
)
177 add_ptr_list(&ret
, tmp
);
178 } END_FOR_EACH_PTR(tmp
);
182 static void assign_ranged_funcs(const char *fn
, struct expression
*expr
,
183 struct call_back_list
*call_backs
)
185 struct fcall_back
*tmp
;
189 struct smatch_state
*extra_state
;
190 struct state_list
*final_states
= NULL
;
191 struct range_list
*handled_ranges
= NULL
;
192 struct call_back_list
*same_range_call_backs
= NULL
;
194 var_name
= get_variable_from_expr(expr
->left
, &sym
);
195 if (!var_name
|| !sym
)
199 FOR_EACH_PTR(call_backs
, tmp
) {
200 if (tmp
->type
!= RANGED_CALL
)
202 if (in_list_exact(handled_ranges
, tmp
->range
))
204 tack_on(&handled_ranges
, tmp
->range
);
206 same_range_call_backs
= get_same_ranged_call_backs(call_backs
, tmp
->range
);
207 call_call_backs(same_range_call_backs
, RANGED_CALL
, fn
, expr
->right
);
208 __free_ptr_list((struct ptr_list
**)&same_range_call_backs
);
210 extra_state
= alloc_extra_state_range(tmp
->range
->min
, tmp
->range
->max
);
211 set_state(var_name
, SMATCH_EXTRA
, sym
, extra_state
);
213 merge_slist(&final_states
, __fake_cur_slist
);
214 free_slist(&__fake_cur_slist
);
215 } END_FOR_EACH_PTR(tmp
);
218 FOR_EACH_PTR(final_states
, sm
) {
220 } END_FOR_EACH_PTR(sm
);
222 free_slist(&final_states
);
224 free_string(var_name
);
227 void function_comparison(int comparison
, struct expression
*expr
, long long value
, int left
)
229 struct call_back_list
*call_backs
;
230 struct fcall_back
*tmp
;
232 struct data_range
*value_range
;
233 struct state_list
*true_states
= NULL
;
234 struct state_list
*false_states
= NULL
;
237 if (expr
->fn
->type
!= EXPR_SYMBOL
|| !expr
->fn
->symbol
)
239 fn
= expr
->fn
->symbol
->ident
->name
;
240 call_backs
= get_call_backs(expr
->fn
->symbol
->ident
->name
);
243 value_range
= alloc_range(value
, value
);
246 FOR_EACH_PTR(call_backs
, tmp
) {
247 if (tmp
->type
== RANGED_CALL
&&
248 true_comparison_range_lr(comparison
, tmp
->range
, value_range
, left
))
249 (tmp
->call_back
)(fn
, expr
, tmp
->info
);
250 merge_slist(&true_states
, __fake_cur_slist
);
251 free_slist(&__fake_cur_slist
);
252 } END_FOR_EACH_PTR(tmp
);
254 FOR_EACH_PTR(call_backs
, tmp
) {
255 if (tmp
->type
== RANGED_CALL
&&
256 false_comparison_range_lr(comparison
, tmp
->range
, value_range
, left
))
257 (tmp
->call_back
)(fn
, expr
, tmp
->info
);
258 merge_slist(&false_states
, __fake_cur_slist
);
259 free_slist(&__fake_cur_slist
);
260 } END_FOR_EACH_PTR(tmp
);
263 FOR_EACH_PTR(true_states
, sm
) {
264 __set_true_false_sm(sm
, NULL
);
265 } END_FOR_EACH_PTR(sm
);
266 FOR_EACH_PTR(false_states
, sm
) {
267 __set_true_false_sm(NULL
, sm
);
268 } END_FOR_EACH_PTR(sm
);
270 if (true_states
&& !false_states
)
271 smatch_msg("warning: unhandled false condition.");
272 if (!true_states
&& false_states
)
273 smatch_msg("warning: unhandled true condition.");
274 free_slist(&true_states
);
275 free_slist(&false_states
);
278 void __match_initializer_call(struct symbol
*sym
)
280 struct call_back_list
*call_backs
;
281 struct expression
*initializer
= sym
->initializer
;
282 struct expression
*e_assign
, *e_symbol
;
285 if (initializer
->fn
->type
!= EXPR_SYMBOL
286 || !initializer
->fn
->symbol
)
288 fn
= initializer
->fn
->symbol
->ident
->name
;
289 call_backs
= get_call_backs(fn
);
293 e_assign
= alloc_expression(initializer
->pos
, EXPR_ASSIGNMENT
);
294 e_symbol
= alloc_expression(initializer
->pos
, EXPR_SYMBOL
);
295 e_symbol
->symbol
= sym
;
296 e_symbol
->symbol_name
= sym
->ident
;
297 e_assign
->left
= e_symbol
;
298 e_assign
->right
= initializer
;
299 call_call_backs(call_backs
, ASSIGN_CALL
, fn
, e_assign
);
300 assign_condition_funcs(fn
, e_assign
, call_backs
);
301 assign_ranged_funcs(fn
, e_assign
, call_backs
);
304 static void match_assign_call(struct expression
*expr
)
306 struct call_back_list
*call_backs
;
309 if (expr
->right
->fn
->type
!= EXPR_SYMBOL
|| !expr
->right
->fn
->symbol
)
311 fn
= expr
->right
->fn
->symbol
->ident
->name
;
312 call_backs
= get_call_backs(fn
);
315 call_call_backs(call_backs
, ASSIGN_CALL
, fn
, expr
);
316 assign_condition_funcs(fn
, expr
, call_backs
);
317 assign_ranged_funcs(fn
, expr
, call_backs
);
320 static void match_conditional_call(struct expression
*expr
)
322 struct call_back_list
*call_backs
;
323 struct fcall_back
*tmp
;
327 if (expr
->type
!= EXPR_CALL
)
330 if (expr
->fn
->type
!= EXPR_SYMBOL
|| !expr
->fn
->symbol
)
333 fn
= expr
->fn
->symbol
->ident
->name
;
334 call_backs
= get_call_backs(fn
);
337 __fake_conditions
= 1;
338 FOR_EACH_PTR(call_backs
, tmp
) {
339 if (tmp
->type
!= CONDITIONAL_CALL
)
342 (tmp
->call_back
)(fn
, expr
, tmp
->info
);
344 FOR_EACH_PTR(__fake_cond_true
, sm
) {
345 __set_true_false_sm(sm
, NULL
);
346 } END_FOR_EACH_PTR(sm
);
347 free_slist(&__fake_cond_true
);
349 FOR_EACH_PTR(__fake_cond_false
, sm
) {
350 __set_true_false_sm(NULL
, sm
);
351 } END_FOR_EACH_PTR(sm
);
352 free_slist(&__fake_cond_false
);
354 } END_FOR_EACH_PTR(tmp
);
355 __fake_conditions
= 0;
358 void create_function_hash(void)
360 hcreate_r(10000, &func_hash
); // Apparently 1000 is too few...
363 void register_function_hooks(int id
)
365 add_hook(&match_function_call
, FUNCTION_CALL_HOOK
);
366 add_hook(&match_assign_call
, CALL_ASSIGNMENT_HOOK
);
367 add_hook(&match_conditional_call
, CONDITION_HOOK
);