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 #include "smatch_extra.h"
29 static struct allocator generic_allocator_table
[] = {
35 static struct allocator kernel_allocator_table
[] = {
44 {"dma_alloc_attrs", 1},
45 {"dma_alloc_coherent", 1},
51 static struct allocator calloc_table
[] = {
54 {"kmalloc_array", 0, 1},
55 {"devm_kcalloc", 1, 2},
58 static int bytes_per_element(struct expression
*expr
)
62 type
= get_type(expr
);
66 if (type
->type
!= SYM_PTR
&& type
->type
!= SYM_ARRAY
)
69 type
= get_base_type(type
);
70 return type_bytes(type
);
73 static void save_constraint_required(struct expression
*pointer
, int op
, struct expression
*constraint
)
77 data
= get_constraint_str(pointer
);
81 limit
= get_constraint_str(constraint
);
83 // FIXME deal with <= also
85 set_state_expr(my_id
, constraint
, alloc_state_expr(pointer
));
89 sql_save_constraint_required(data
, op
, limit
);
96 static int handle_zero_size_arrays(struct expression
*pointer
, struct expression
*size
)
98 struct expression
*left
, *right
;
99 struct symbol
*type
, *array
, *array_type
;
104 if (size
->type
!= EXPR_BINOP
|| size
->op
!= '+')
107 type
= get_type(pointer
);
108 if (!type
|| type
->type
!= SYM_PTR
)
110 type
= get_real_base_type(type
);
111 if (!type
|| !type
->ident
|| type
->type
!= SYM_STRUCT
)
113 if (!last_member_is_resizable(type
))
115 array
= last_ptr_list((struct ptr_list
*)type
->symbol_list
);
116 if (!array
|| !array
->ident
)
118 array_type
= get_real_base_type(array
);
119 if (!array_type
|| array_type
->type
!= SYM_ARRAY
)
121 array_type
= get_real_base_type(array_type
);
123 left
= strip_expr(size
->left
);
124 right
= strip_expr(size
->right
);
126 if (!get_implied_value(left
, &struct_size
))
128 if (struct_size
.value
!= type_bytes(type
))
131 if (right
->type
== EXPR_BINOP
&& right
->op
== '*') {
132 struct expression
*mult_left
, *mult_right
;
135 mult_left
= strip_expr(right
->left
);
136 mult_right
= strip_expr(right
->right
);
138 if (get_implied_value(mult_left
, &sval
) &&
139 sval
.value
== type_bytes(array_type
))
141 else if (get_implied_value(mult_right
, &sval
) &&
142 sval
.value
== type_bytes(array_type
))
148 snprintf(data
, sizeof(data
), "(struct %s)->%s", type
->ident
->name
, array
->ident
->name
);
149 limit
= get_constraint_str(size
);
151 set_state_expr(my_id
, size
, alloc_state_expr(
152 member_expression(deref_expression(pointer
), '*', array
->ident
)));
156 sql_save_constraint_required(data
, '<', limit
);
162 static void match_alloc_helper(struct expression
*pointer
, struct expression
*size
, int recurse
)
164 struct expression
*size_orig
, *tmp
;
168 pointer
= strip_expr(pointer
);
169 size
= strip_expr(size
);
170 if (!size
|| !pointer
)
175 while ((tmp
= get_assigned_expr(size
))) {
176 size
= strip_expr(tmp
);
180 if (size
!= size_orig
) {
181 match_alloc_helper(pointer
, size
, 0);
186 if (handle_zero_size_arrays(pointer
, size
))
189 if (size
->type
== EXPR_BINOP
&& size
->op
== '*') {
190 struct expression
*mult_left
, *mult_right
;
192 mult_left
= strip_expr(size
->left
);
193 mult_right
= strip_expr(size
->right
);
195 if (get_implied_value(mult_left
, &sval
) &&
196 sval
.value
== bytes_per_element(pointer
))
198 else if (get_implied_value(mult_right
, &sval
) &&
199 sval
.value
== bytes_per_element(pointer
))
205 if (size
->type
== EXPR_BINOP
&& size
->op
== '+' &&
206 get_implied_value(size
->right
, &sval
) &&
208 save_constraint_required(pointer
, SPECIAL_LTE
, size
->left
);
210 save_constraint_required(pointer
, '<', size
);
213 static void match_alloc(const char *fn
, struct expression
*expr
, void *_size_arg
)
215 int size_arg
= PTR_INT(_size_arg
);
216 struct expression
*call
, *arg
;
218 call
= strip_expr(expr
->right
);
219 arg
= get_argument_from_call_expr(call
->args
, size_arg
);
221 match_alloc_helper(expr
->left
, arg
, 1);
224 static void match_calloc(const char *fn
, struct expression
*expr
, void *_start_arg
)
226 struct expression
*pointer
, *call
, *size
;
227 struct expression
*count
= NULL
;
228 int start_arg
= PTR_INT(_start_arg
);
231 pointer
= strip_expr(expr
->left
);
232 call
= strip_expr(expr
->right
);
234 size
= get_argument_from_call_expr(call
->args
, start_arg
);
235 if (get_implied_value(size
, &sval
) &&
236 sval
.value
== bytes_per_element(pointer
))
237 count
= get_argument_from_call_expr(call
->args
, start_arg
+ 1);
239 size
= get_argument_from_call_expr(call
->args
, start_arg
+ 1);
240 if (get_implied_value(size
, &sval
) &&
241 sval
.value
== bytes_per_element(pointer
))
242 count
= get_argument_from_call_expr(call
->args
, start_arg
);
248 save_constraint_required(pointer
, '<', count
);
251 static void add_allocation_function(const char *func
, void *call_back
, int param
)
253 add_function_assign_hook(func
, call_back
, INT_PTR(param
));
256 static void match_assign_size(struct expression
*expr
)
258 struct smatch_state
*state
;
261 state
= get_state_expr(my_id
, expr
->right
);
262 if (!state
|| !state
->data
)
265 data
= get_constraint_str(state
->data
);
269 limit
= get_constraint_str(expr
->left
);
273 sql_save_constraint_required(data
, '<', limit
);
280 static void match_assign_has_buf_comparison(struct expression
*expr
)
282 struct expression
*size
;
287 if (expr
->right
->type
== EXPR_CALL
)
289 size
= get_size_variable(expr
->right
, &limit_type
);
292 if (limit_type
!= ELEM_COUNT
)
294 match_alloc_helper(expr
->left
, size
, 1);
297 static void match_assign_data(struct expression
*expr
)
299 struct expression
*right
, *arg
, *tmp
;
307 /* Direct calls are handled else where (for now at least) */
308 tmp
= get_assigned_expr(expr
->right
);
312 right
= strip_expr(tmp
);
313 if (right
->type
!= EXPR_CALL
)
316 if (right
->fn
->type
!= EXPR_SYMBOL
||
317 !right
->fn
->symbol
||
318 !right
->fn
->symbol
->ident
)
321 for (i
= 0; i
< ARRAY_SIZE(generic_allocator_table
); i
++) {
322 if (strcmp(right
->fn
->symbol
->ident
->name
,
323 generic_allocator_table
[i
].func
) == 0) {
324 size_arg
= generic_allocator_table
[i
].param
;
329 if (option_project
!= PROJ_KERNEL
)
332 for (i
= 0; i
< ARRAY_SIZE(kernel_allocator_table
); i
++) {
333 if (strcmp(right
->fn
->symbol
->ident
->name
,
334 kernel_allocator_table
[i
].func
) == 0) {
335 size_arg
= kernel_allocator_table
[i
].param
;
340 for (i
= 0; i
< ARRAY_SIZE(calloc_table
); i
++) {
341 if (strcmp(right
->fn
->symbol
->ident
->name
,
342 calloc_table
[i
].func
) == 0) {
343 size_arg
= calloc_table
[i
].param
;
344 size_arg2
= calloc_table
[i
].param2
;
352 arg
= get_argument_from_call_expr(right
->args
, size_arg
);
353 match_alloc_helper(expr
->left
, arg
, 1);
356 arg
= get_argument_from_call_expr(right
->args
, size_arg2
);
357 match_alloc_helper(expr
->left
, arg
, 1);
360 static void match_assign_ARRAY_SIZE(struct expression
*expr
)
362 struct expression
*array
;
366 macro
= get_macro_name(expr
->right
->pos
);
367 if (!macro
|| strcmp(macro
, "ARRAY_SIZE") != 0)
369 array
= strip_expr(expr
->right
);
370 if (array
->type
!= EXPR_BINOP
|| array
->op
!= '+')
372 array
= strip_expr(array
->left
);
373 if (array
->type
!= EXPR_BINOP
|| array
->op
!= '/')
375 array
= strip_expr(array
->left
);
376 if (array
->type
!= EXPR_SIZEOF
)
378 array
= strip_expr(array
->cast_expression
);
379 if (array
->type
!= EXPR_PREOP
|| array
->op
!= '*')
381 array
= strip_expr(array
->unop
);
383 data
= get_constraint_str(array
);
384 limit
= get_constraint_str(expr
->left
);
388 sql_save_constraint_required(data
, '<', limit
);
395 static void match_assign_buf_comparison(struct expression
*expr
)
397 struct expression
*pointer
;
401 pointer
= get_array_variable(expr
->right
);
405 match_alloc_helper(pointer
, expr
->right
, 1);
408 static int constraint_found(void *_found
, int argc
, char **argv
, char **azColName
)
416 static int has_constraint(struct expression
*expr
, const char *constraint
)
420 if (get_state_expr(my_id
, expr
))
423 run_sql(constraint_found
, &found
,
424 "select data from constraints_required where bound = '%q' limit 1",
425 escape_newlines(constraint
));
430 static void match_assign_constraint(struct expression
*expr
)
435 if (__in_fake_struct_assign
)
440 type
= get_type(expr
->left
);
441 if (!type
|| type
->type
!= SYM_BASETYPE
)
444 left
= get_constraint_str(expr
->left
);
447 right
= get_constraint_str(expr
->right
);
450 if (!has_constraint(expr
->right
, right
))
452 sql_copy_constraint_required(left
, right
);
458 void register_constraints_required(int id
)
462 set_dynamic_states(my_id
);
463 add_hook(&match_assign_size
, ASSIGNMENT_HOOK
);
464 add_hook(&match_assign_data
, ASSIGNMENT_HOOK
);
465 add_hook(&match_assign_has_buf_comparison
, ASSIGNMENT_HOOK
);
467 add_hook(&match_assign_ARRAY_SIZE
, ASSIGNMENT_HOOK
);
468 add_hook(&match_assign_ARRAY_SIZE
, GLOBAL_ASSIGNMENT_HOOK
);
469 add_hook(&match_assign_buf_comparison
, ASSIGNMENT_HOOK
);
470 add_hook(&match_assign_constraint
, ASSIGNMENT_HOOK
);
472 add_allocation_function("malloc", &match_alloc
, 0);
473 add_allocation_function("memdup", &match_alloc
, 1);
474 add_allocation_function("realloc", &match_alloc
, 1);
475 add_allocation_function("realloc", &match_calloc
, 0);
476 if (option_project
== PROJ_KERNEL
) {
477 add_allocation_function("kmalloc", &match_alloc
, 0);
478 add_allocation_function("kzalloc", &match_alloc
, 0);
479 add_allocation_function("vmalloc", &match_alloc
, 0);
480 add_allocation_function("__vmalloc", &match_alloc
, 0);
481 add_allocation_function("vzalloc", &match_alloc
, 0);
482 add_allocation_function("sock_kmalloc", &match_alloc
, 1);
483 add_allocation_function("kmemdup", &match_alloc
, 1);
484 add_allocation_function("memdup_user", &match_alloc
, 1);
485 add_allocation_function("dma_alloc_attrs", &match_alloc
, 1);
486 add_allocation_function("dma_alloc_coherent", &match_alloc
, 1);
487 add_allocation_function("devm_kmalloc", &match_alloc
, 1);
488 add_allocation_function("devm_kzalloc", &match_alloc
, 1);
489 add_allocation_function("kcalloc", &match_calloc
, 0);
490 add_allocation_function("kmalloc_array", &match_calloc
, 0);
491 add_allocation_function("devm_kcalloc", &match_calloc
, 1);
492 add_allocation_function("krealloc", &match_alloc
, 1);