2 * Copyright (C) 2017 Oracle.
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.
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.
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
19 * Say you have assign a function to a function pointer and you assign a
20 * pointer to the data argument then we want to record some information about
21 * the argument. Right now what I mainly want to record is the type of it, I
27 #include "smatch_extra.h"
28 #include "smatch_slist.h"
33 static int assigns_parameters(struct expression
*fn
, struct expression
*arg
)
35 int fn_param
, arg_param
;
38 fn_param
= get_param_num(fn
);
42 arg_param
= get_param_num(arg
);
46 snprintf(buf
, sizeof(buf
), "%d", arg_param
);
47 sql_insert_return_implies(FN_ARG_LINK
, fn_param
, "$", buf
);
51 static void link_function_arg(struct expression
*fn
, int param
, struct expression
*arg
)
57 if (assigns_parameters(fn
, arg
))
61 if (!type
|| type
->type
!= SYM_PTR
)
63 type
= get_real_base_type(type
);
66 // FIXME: param shouldn't always be 0?
67 sql_insert_fn_data_link(fn
, PASSES_TYPE
, param
, "$", type_to_str(type
));
70 char *next_param_name
;
71 struct symbol
*next_param_sym
;
72 struct expression
*next_fn
;
73 static void match_assign_param(struct expression
*expr
)
81 name
= expr_to_var_sym(expr
->left
, &sym
);
87 if (sym
!= next_param_sym
||
88 strcmp(name
, next_param_name
) != 0)
91 link_function_arg(next_fn
, 0, strip_expr(expr
->right
));
94 next_param_sym
= NULL
;
98 static int get_arg_ptr(void *_arg_ptr
, int argc
, char **argv
, char **azColName
)
100 char **arg_ptr
= _arg_ptr
;
105 *arg_ptr
= alloc_string(argv
[0]);
109 static char *get_data_member(char *fn_member
, struct expression
*expr
, struct symbol
**sym
)
111 struct symbol
*tmp_sym
;
113 char *arg_ptr
= NULL
;
115 int len_ptr
, len_str
;
119 run_sql(get_arg_ptr
, &arg_ptr
,
120 "select data from fn_ptr_data_link where fn_ptr = '%s';", fn_member
);
123 end_type
= strchr(arg_ptr
, '>');
127 fn_str
= expr_to_var_sym(expr
, &tmp_sym
);
128 if (!fn_str
|| !tmp_sym
)
130 len_ptr
= strlen(fn_member
);
131 len_str
= strlen(fn_str
);
132 while (len_str
> 0 && len_ptr
> 0) {
133 if (fn_str
[len_str
- 1] != fn_member
[len_ptr
- 1])
135 if (fn_str
[len_str
- 1] == '>')
141 strncpy(buf
, fn_str
, sizeof(buf
));
142 snprintf(buf
+ len_str
, sizeof(buf
) - len_str
, end_type
);
144 return alloc_string(buf
);
147 static void match_assign_function(struct expression
*expr
)
149 struct expression
*right
, *arg
;
155 right
= strip_expr(expr
->right
);
156 if (right
->type
== EXPR_PREOP
&& right
->op
== '&')
157 right
= strip_expr(right
->unop
);
159 type
= get_type(right
);
160 if (type
&& type
->type
== SYM_PTR
)
161 type
= get_real_base_type(type
);
162 if (!type
|| type
->type
!= SYM_FN
)
165 member_name
= get_member_name(expr
->left
);
169 data_member
= get_data_member(member_name
, expr
->left
, &sym
);
170 if (!data_member
|| !sym
) {
171 free_string(data_member
);
175 arg
= get_assigned_expr_name_sym(data_member
, sym
);
177 link_function_arg(right
, 0, arg
);
179 next_param_name
= data_member
;
180 next_param_sym
= sym
;
185 static int is_recursive_call(struct expression
*call
)
187 if (call
->fn
->type
!= EXPR_SYMBOL
)
189 if (call
->fn
->symbol
== cur_func_sym
)
194 static void check_passes_fn_and_data(struct expression
*call
, struct expression
*fn
, char *key
, char *value
)
196 struct expression
*arg
;
200 if (is_recursive_call(call
))
204 if (!type
|| type
->type
!= SYM_FN
)
207 if (!isdigit(value
[0]))
209 data_nr
= atoi(value
);
210 arg
= get_argument_from_call_expr(call
->args
, data_nr
);
213 link_function_arg(fn
, 0, arg
);
216 static void match_end_func(struct symbol
*sym
)
218 next_param_sym
= NULL
;
222 void register_about_fn_ptr_arg(int id
)
226 if (0 && !option_info
)
228 add_hook(match_assign_param
, ASSIGNMENT_HOOK
);
229 add_hook(match_assign_function
, ASSIGNMENT_HOOK
);
230 select_return_implies_hook(FN_ARG_LINK
, &check_passes_fn_and_data
);
231 add_hook(&match_end_func
, END_FUNC_HOOK
);