2 * Copyright (C) 2013 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 #include "smatch_slist.h"
20 #include "smatch_extra.h"
27 static int type_sym_array(struct expression
*expr
)
31 /* remove casting the array to a pointer */
32 expr
= strip_expr(expr
);
33 type
= get_type(expr
);
34 if (type
&& type
->type
== SYM_ARRAY
)
39 static void set_members_uninitialized(struct expression
*expr
)
41 struct symbol
*type
, *sym
, *tmp
;
45 type
= get_type(expr
);
49 if (type
->type
!= SYM_PTR
)
51 type
= get_real_base_type(type
);
53 name
= expr_to_var_sym(expr
, &sym
);
57 FOR_EACH_PTR(type
->symbol_list
, tmp
) {
60 snprintf(buf
, sizeof(buf
), "%s->%s", name
, tmp
->ident
->name
);
61 set_state(my_id
, buf
, sym
, &uninitialized
);
62 } END_FOR_EACH_PTR(tmp
);
68 static void initialize_struct_members(struct symbol
*type
, struct expression
*expr
, struct expression
*to
)
71 struct expression
*member
;
72 struct expression
*assign
;
75 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '&') {
76 expr
= strip_expr(expr
->unop
);
80 FOR_EACH_PTR(type
->symbol_list
, tmp
) {
83 member
= member_expression(expr
, op
, tmp
->ident
);
84 if (type_sym_array(member
))
88 * FIXME: the problem here is that sometimes we have:
89 * memset(&my_struct, 0xff, sizeof(my_struct));
90 * and my_struct->foo is a 1 bit bitfield. There is a check
91 * which complains that "255 doesn't fit in ->foo".
93 * For now I just have this ugly hack. But really it's not
94 * handling the memset(..., 0xff, ...) correctly at all so one
95 * more hack barely makes a difference.
98 if (to
&& type_positive_bits(get_type(member
)) >= type_positive_bits(get_type(to
)))
99 assign
= assign_expression(member
, to
);
101 assign
= assign_expression(member
, member
);
103 __pass_to_client(assign
, ASSIGNMENT_HOOK
);
104 } END_FOR_EACH_PTR(tmp
);
107 static void initialize_base_type(struct symbol
*type
, struct expression
*expr
,
108 struct expression
*to
)
110 struct expression
*assign
;
112 if (type
== &void_ctype
)
114 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '&')
115 expr
= strip_expr(expr
->unop
);
117 expr
= deref_expression(expr
);
120 /* FIXME: see the FIXME in initialize_struct_members() */
121 if (type_positive_bits(get_type(expr
)) < type_positive_bits(get_type(to
)))
123 assign
= assign_expression(expr
, to
);
124 __pass_to_client(assign
, ASSIGNMENT_HOOK
);
127 static void set_initialized(struct expression
*expr
, struct expression
*to
)
131 expr
= strip_expr(expr
);
133 type
= get_type(expr
);
134 if (!type
|| type
->type
!= SYM_PTR
)
136 type
= get_real_base_type(type
);
139 if (type
->type
== SYM_BASETYPE
)
140 initialize_base_type(type
, expr
, to
);
141 if (type
->type
== SYM_STRUCT
) {
142 if (expr
->type
!= EXPR_PREOP
|| expr
->op
!= '&')
143 expr
= deref_expression(expr
);
144 initialize_struct_members(type
, expr
, to
);
148 int is_uninitialized(struct expression
*expr
)
152 sm
= get_sm_state_expr(my_id
, expr
);
155 return slist_has_state(sm
->possible
, &uninitialized
);
158 int has_uninitialized_members(struct expression
*expr
)
166 sym
= get_type(expr
);
170 if (sym
->type
== SYM_PTR
)
171 sym
= get_real_base_type(sym
);
173 name
= expr_to_var(expr
);
177 FOR_EACH_PTR(sym
->symbol_list
, tmp
) {
180 snprintf(buf
, sizeof(buf
), "%s->%s", name
, tmp
->ident
->name
);
181 sm
= get_sm_state(my_id
, buf
, sym
);
184 if (slist_has_state(sm
->possible
, &uninitialized
))
186 } END_FOR_EACH_PTR(tmp
);
192 static void match_assign(struct expression
*expr
)
196 type
= get_type(expr
->left
);
197 if (!type
|| type
->type
!= SYM_STRUCT
)
199 initialize_struct_members(type
, expr
->left
, NULL
);
202 static void match_alloc(const char *fn
, struct expression
*expr
, void *_size_arg
)
204 set_members_uninitialized(expr
->left
);
207 static void db_param_cleared(struct expression
*expr
, int param
, char *key
, char *value
)
209 struct expression
*arg
;
211 while (expr
->type
== EXPR_ASSIGNMENT
)
212 expr
= strip_expr(expr
->right
);
213 if (expr
->type
!= EXPR_CALL
)
216 arg
= get_argument_from_call_expr(expr
->args
, param
);
220 if (strcmp(value
, "0") == 0)
221 set_initialized(arg
, zero_expr());
223 set_initialized(arg
, NULL
);
226 static void match_memcpy(const char *fn
, struct expression
*expr
, void *_arg
)
228 struct expression
*buf
;
229 int arg
= PTR_INT(_arg
);
231 buf
= get_argument_from_call_expr(expr
->args
, arg
);
233 set_initialized(buf
, NULL
);
236 static void reset_initialized(struct sm_state
*sm
, struct expression
*mod_expr
)
238 set_state(my_id
, sm
->name
, sm
->sym
, &initialized
);
241 #define USB_DIR_IN 0x80
242 static void match_usb_control_msg(const char *fn
, struct expression
*expr
, void *_size_arg
)
244 struct expression
*inout
;
245 struct expression
*buf
;
248 inout
= get_argument_from_call_expr(expr
->args
, 3);
249 buf
= get_argument_from_call_expr(expr
->args
, 6);
251 if (get_value(inout
, &sval
) && !(sval
.uvalue
& USB_DIR_IN
))
254 set_initialized(buf
, NULL
);
257 void register_clear_buffer(int id
)
260 if (option_project
== PROJ_KERNEL
) {
261 add_function_assign_hook("kmalloc", &match_alloc
, NULL
);
262 add_function_hook("usb_control_msg", &match_usb_control_msg
, NULL
);
264 add_modification_hook(my_id
, &reset_initialized
);
265 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
267 select_return_states_hook(PARAM_CLEARED
, &db_param_cleared
);