2 * Copyright (C) 2012 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 * This works together with smatch_clear_buffer.c. This one is only for
20 * tracking the information and smatch_clear_buffer.c changes SMATCH_EXTRA.
22 * This tracks functions like memset() which clear out a chunk of memory.
23 * It fills in a gap that smatch_param_set.c can't handle. It only handles
24 * void pointers because smatch_param_set.c should handle the rest. Oh. And
25 * also it handles arrays because Smatch sucks at handling arrays.
30 #include "smatch_slist.h"
31 #include "smatch_extra.h"
38 static void db_param_cleared(struct expression
*expr
, int param
, char *key
, char *value
)
40 struct expression
*arg
;
44 while (expr
->type
== EXPR_ASSIGNMENT
)
45 expr
= strip_expr(expr
->right
);
46 if (expr
->type
!= EXPR_CALL
)
49 arg
= get_argument_from_call_expr(expr
->args
, param
);
50 name
= get_variable_from_key(arg
, key
, &sym
);
54 if (strcmp(value
, "0") == 0)
55 set_state(my_id
, name
, sym
, &zeroed
);
57 set_state(my_id
, name
, sym
, &cleared
);
62 static void match_memset(const char *fn
, struct expression
*expr
, void *arg
)
64 db_param_cleared(expr
, PTR_INT(arg
), (char *)"$", (char *)"0");
67 static void match_memcpy(const char *fn
, struct expression
*expr
, void *arg
)
69 db_param_cleared(expr
, PTR_INT(arg
), (char *)"$", (char *)"");
72 static void print_return_value_param(int return_id
, char *return_ranges
, struct expression
*expr
)
77 const char *param_name
;
79 stree
= __get_cur_stree();
81 FOR_EACH_MY_SM(my_id
, stree
, sm
) {
82 param
= get_param_num_from_sym(sm
->sym
);
86 param_name
= get_param_name(sm
);
90 if (sm
->state
== &zeroed
) {
91 sql_insert_return_states(return_id
, return_ranges
,
92 PARAM_CLEARED
, param
, param_name
, "0");
95 if (sm
->state
== &cleared
) {
96 sql_insert_return_states(return_id
, return_ranges
,
97 PARAM_CLEARED
, param
, param_name
, "");
99 } END_FOR_EACH_SM(sm
);
102 static void register_clears_param(void)
106 const char *function
;
109 if (option_project
== PROJ_NONE
)
112 snprintf(name
, 256, "%s.clears_argument", option_project_str
);
114 token
= get_tokens_file(name
);
117 if (token_type(token
) != TOKEN_STREAMBEGIN
)
120 while (token_type(token
) != TOKEN_STREAMEND
) {
121 if (token_type(token
) != TOKEN_IDENT
)
123 function
= show_ident(token
->ident
);
125 if (token_type(token
) != TOKEN_NUMBER
)
127 param
= atoi(token
->number
);
128 add_function_hook(function
, &match_memcpy
, INT_PTR(param
));
134 #define USB_DIR_IN 0x80
135 static void match_usb_control_msg(const char *fn
, struct expression
*expr
, void *_size_arg
)
137 struct expression
*inout
;
140 inout
= get_argument_from_call_expr(expr
->args
, 3);
142 if (get_value(inout
, &sval
) && !(sval
.uvalue
& USB_DIR_IN
))
145 db_param_cleared(expr
, 6, (char *)"$", (char *)"");
148 static void match_assign(struct expression
*expr
)
153 * If we have struct foo x, y; and we say that x = y; then it
154 * initializes the struct holes. So we record that here.
156 type
= get_type(expr
->left
);
157 if (!type
|| type
->type
!= SYM_STRUCT
)
159 set_state_expr(my_id
, expr
->left
, &cleared
);
162 static void match_array_assign(struct expression
*expr
)
164 struct expression
*array_expr
;
166 if (!is_array(expr
->left
))
169 array_expr
= get_array_base(expr
->left
);
170 set_state_expr(my_id
, array_expr
, &cleared
);
173 void register_param_cleared(int id
)
177 add_function_hook("memset", &match_memset
, INT_PTR(0));
178 add_function_hook("memzero", &match_memset
, INT_PTR(0));
179 add_function_hook("__memset", &match_memset
, INT_PTR(0));
180 add_function_hook("__memzero", &match_memset
, INT_PTR(0));
182 add_function_hook("memcpy", &match_memcpy
, INT_PTR(0));
183 add_function_hook("memmove", &match_memcpy
, INT_PTR(0));
184 add_function_hook("__memcpy", &match_memcpy
, INT_PTR(0));
185 add_function_hook("__memmove", &match_memcpy
, INT_PTR(0));
186 add_function_hook("strcpy", &match_memcpy
, INT_PTR(0));
187 add_function_hook("strncpy", &match_memcpy
, INT_PTR(0));
188 add_function_hook("sprintf", &match_memcpy
, INT_PTR(0));
189 add_function_hook("snprintf", &match_memcpy
, INT_PTR(0));
191 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
192 add_hook(&match_array_assign
, ASSIGNMENT_HOOK
);
194 register_clears_param();
196 select_return_states_hook(PARAM_CLEARED
, &db_param_cleared
);
197 add_split_return_callback(&print_return_value_param
);
199 if (option_project
== PROJ_KERNEL
) {
200 add_function_hook("usb_control_msg", &match_usb_control_msg
, NULL
);