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 {"pci_alloc_consistent", 1},
46 {"pci_alloc_coherent", 1},
52 static struct allocator calloc_table
[] = {
55 {"kmalloc_array", 0, 1},
56 {"devm_kcalloc", 1, 2},
59 static int bytes_per_element(struct expression
*expr
)
63 type
= get_type(expr
);
67 if (type
->type
!= SYM_PTR
&& type
->type
!= SYM_ARRAY
)
70 type
= get_base_type(type
);
71 return type_bytes(type
);
74 static void save_constraint_required(struct expression
*pointer
, int op
, struct expression
*constraint
)
78 data
= get_constraint_str(pointer
);
82 limit
= get_constraint_str(constraint
);
84 // FIXME deal with <= also
86 set_state_expr(my_id
, constraint
, alloc_state_expr(pointer
));
90 sql_save_constraint_required(data
, op
, limit
);
97 static int handle_zero_size_arrays(struct expression
*pointer
, struct expression
*size
)
99 struct expression
*left
, *right
;
100 struct symbol
*type
, *array
, *array_type
;
105 if (size
->type
!= EXPR_BINOP
|| size
->op
!= '+')
108 type
= get_type(pointer
);
109 if (!type
|| type
->type
!= SYM_PTR
)
111 type
= get_real_base_type(type
);
112 if (!type
|| !type
->ident
|| type
->type
!= SYM_STRUCT
)
114 if (!last_member_is_resizable(type
))
116 array
= last_ptr_list((struct ptr_list
*)type
->symbol_list
);
117 if (!array
|| !array
->ident
)
119 array_type
= get_real_base_type(array
);
120 if (!array_type
|| array_type
->type
!= SYM_ARRAY
)
122 array_type
= get_real_base_type(array_type
);
124 left
= strip_expr(size
->left
);
125 right
= strip_expr(size
->right
);
127 if (!get_implied_value(left
, &struct_size
))
129 if (struct_size
.value
!= type_bytes(type
))
132 if (right
->type
== EXPR_BINOP
&& right
->op
== '*') {
133 struct expression
*mult_left
, *mult_right
;
136 mult_left
= strip_expr(right
->left
);
137 mult_right
= strip_expr(right
->right
);
139 if (get_implied_value(mult_left
, &sval
) &&
140 sval
.value
== type_bytes(array_type
))
142 else if (get_implied_value(mult_right
, &sval
) &&
143 sval
.value
== type_bytes(array_type
))
149 snprintf(data
, sizeof(data
), "(struct %s)->%s", type
->ident
->name
, array
->ident
->name
);
150 limit
= get_constraint_str(size
);
152 set_state_expr(my_id
, size
, alloc_state_expr(
153 member_expression(deref_expression(pointer
), '*', array
->ident
)));
157 sql_save_constraint_required(data
, '<', limit
);
163 static void match_alloc_helper(struct expression
*pointer
, struct expression
*size
, int recurse
)
165 struct expression
*size_orig
, *tmp
;
169 pointer
= strip_expr(pointer
);
170 size
= strip_expr(size
);
171 if (!size
|| !pointer
)
176 while ((tmp
= get_assigned_expr(size
))) {
177 size
= strip_expr(tmp
);
181 if (size
!= size_orig
) {
182 match_alloc_helper(pointer
, size
, 0);
187 if (handle_zero_size_arrays(pointer
, size
))
190 if (size
->type
== EXPR_BINOP
&& size
->op
== '*') {
191 struct expression
*mult_left
, *mult_right
;
193 mult_left
= strip_expr(size
->left
);
194 mult_right
= strip_expr(size
->right
);
196 if (get_implied_value(mult_left
, &sval
) &&
197 sval
.value
== bytes_per_element(pointer
))
199 else if (get_implied_value(mult_right
, &sval
) &&
200 sval
.value
== bytes_per_element(pointer
))
206 if (size
->type
== EXPR_BINOP
&& size
->op
== '+' &&
207 get_implied_value(size
->right
, &sval
) &&
209 save_constraint_required(pointer
, SPECIAL_LTE
, size
->left
);
211 save_constraint_required(pointer
, '<', size
);
214 static void match_alloc(const char *fn
, struct expression
*expr
, void *_size_arg
)
216 int size_arg
= PTR_INT(_size_arg
);
217 struct expression
*call
, *arg
;
219 call
= strip_expr(expr
->right
);
220 arg
= get_argument_from_call_expr(call
->args
, size_arg
);
222 match_alloc_helper(expr
->left
, arg
, 1);
225 static void match_calloc(const char *fn
, struct expression
*expr
, void *_start_arg
)
227 struct expression
*pointer
, *call
, *size
;
228 struct expression
*count
= NULL
;
229 int start_arg
= PTR_INT(_start_arg
);
232 pointer
= strip_expr(expr
->left
);
233 call
= strip_expr(expr
->right
);
235 size
= get_argument_from_call_expr(call
->args
, start_arg
);
236 if (get_implied_value(size
, &sval
) &&
237 sval
.value
== bytes_per_element(pointer
))
238 count
= get_argument_from_call_expr(call
->args
, start_arg
+ 1);
240 size
= get_argument_from_call_expr(call
->args
, start_arg
+ 1);
241 if (get_implied_value(size
, &sval
) &&
242 sval
.value
== bytes_per_element(pointer
))
243 count
= get_argument_from_call_expr(call
->args
, start_arg
);
249 save_constraint_required(pointer
, '<', count
);
252 static void add_allocation_function(const char *func
, void *call_back
, int param
)
254 add_function_assign_hook(func
, call_back
, INT_PTR(param
));
257 static void match_assign_size(struct expression
*expr
)
259 struct smatch_state
*state
;
262 state
= get_state_expr(my_id
, expr
->right
);
263 if (!state
|| !state
->data
)
266 data
= get_constraint_str(state
->data
);
270 limit
= get_constraint_str(expr
->left
);
274 sql_save_constraint_required(data
, '<', limit
);
281 static void match_assign_has_buf_comparison(struct expression
*expr
)
283 struct expression
*size
;
288 if (expr
->right
->type
== EXPR_CALL
)
290 size
= get_size_variable(expr
->right
, &limit_type
);
293 if (limit_type
!= ELEM_COUNT
)
295 match_alloc_helper(expr
->left
, size
, 1);
298 static void match_assign_data(struct expression
*expr
)
300 struct expression
*right
, *arg
, *tmp
;
308 /* Direct calls are handled else where (for now at least) */
309 tmp
= get_assigned_expr(expr
->right
);
313 right
= strip_expr(tmp
);
314 if (right
->type
!= EXPR_CALL
)
317 if (right
->fn
->type
!= EXPR_SYMBOL
||
318 !right
->fn
->symbol
||
319 !right
->fn
->symbol
->ident
)
322 for (i
= 0; i
< ARRAY_SIZE(generic_allocator_table
); i
++) {
323 if (strcmp(right
->fn
->symbol
->ident
->name
,
324 generic_allocator_table
[i
].func
) == 0) {
325 size_arg
= generic_allocator_table
[i
].param
;
330 if (option_project
!= PROJ_KERNEL
)
333 for (i
= 0; i
< ARRAY_SIZE(kernel_allocator_table
); i
++) {
334 if (strcmp(right
->fn
->symbol
->ident
->name
,
335 kernel_allocator_table
[i
].func
) == 0) {
336 size_arg
= kernel_allocator_table
[i
].param
;
341 for (i
= 0; i
< ARRAY_SIZE(calloc_table
); i
++) {
342 if (strcmp(right
->fn
->symbol
->ident
->name
,
343 calloc_table
[i
].func
) == 0) {
344 size_arg
= calloc_table
[i
].param
;
345 size_arg2
= calloc_table
[i
].param2
;
353 arg
= get_argument_from_call_expr(right
->args
, size_arg
);
354 match_alloc_helper(expr
->left
, arg
, 1);
357 arg
= get_argument_from_call_expr(right
->args
, size_arg2
);
358 match_alloc_helper(expr
->left
, arg
, 1);
361 static void match_assign_ARRAY_SIZE(struct expression
*expr
)
363 struct expression
*array
;
367 macro
= get_macro_name(expr
->right
->pos
);
368 if (!macro
|| strcmp(macro
, "ARRAY_SIZE") != 0)
370 array
= strip_expr(expr
->right
);
371 if (array
->type
!= EXPR_BINOP
|| array
->op
!= '+')
373 array
= strip_expr(array
->left
);
374 if (array
->type
!= EXPR_BINOP
|| array
->op
!= '/')
376 array
= strip_expr(array
->left
);
377 if (array
->type
!= EXPR_SIZEOF
)
379 array
= strip_expr(array
->cast_expression
);
380 if (array
->type
!= EXPR_PREOP
|| array
->op
!= '*')
382 array
= strip_expr(array
->unop
);
384 data
= get_constraint_str(array
);
385 limit
= get_constraint_str(expr
->left
);
389 sql_save_constraint_required(data
, '<', limit
);
396 static void match_assign_buf_comparison(struct expression
*expr
)
398 struct expression
*pointer
;
402 pointer
= get_array_variable(expr
->right
);
406 match_alloc_helper(pointer
, expr
->right
, 1);
409 static int constraint_found(void *_found
, int argc
, char **argv
, char **azColName
)
417 static int has_constraint(struct expression
*expr
, const char *constraint
)
421 if (get_state_expr(my_id
, expr
))
424 run_sql(constraint_found
, &found
,
425 "select data from constraints_required where bound = '%q' limit 1",
426 escape_newlines(constraint
));
431 static void match_assign_constraint(struct expression
*expr
)
436 if (__in_fake_struct_assign
)
441 type
= get_type(expr
->left
);
442 if (!type
|| type
->type
!= SYM_BASETYPE
)
445 left
= get_constraint_str(expr
->left
);
448 right
= get_constraint_str(expr
->right
);
451 if (!has_constraint(expr
->right
, right
))
453 sql_copy_constraint_required(left
, right
);
459 void register_constraints_required(int id
)
463 set_dynamic_states(my_id
);
464 add_hook(&match_assign_size
, ASSIGNMENT_HOOK
);
465 add_hook(&match_assign_data
, ASSIGNMENT_HOOK
);
466 add_hook(&match_assign_has_buf_comparison
, ASSIGNMENT_HOOK
);
468 add_hook(&match_assign_ARRAY_SIZE
, ASSIGNMENT_HOOK
);
469 add_hook(&match_assign_ARRAY_SIZE
, GLOBAL_ASSIGNMENT_HOOK
);
470 add_hook(&match_assign_buf_comparison
, ASSIGNMENT_HOOK
);
471 add_hook(&match_assign_constraint
, ASSIGNMENT_HOOK
);
473 add_allocation_function("malloc", &match_alloc
, 0);
474 add_allocation_function("memdup", &match_alloc
, 1);
475 add_allocation_function("realloc", &match_alloc
, 1);
476 add_allocation_function("realloc", &match_calloc
, 0);
477 if (option_project
== PROJ_KERNEL
) {
478 add_allocation_function("kmalloc", &match_alloc
, 0);
479 add_allocation_function("kzalloc", &match_alloc
, 0);
480 add_allocation_function("vmalloc", &match_alloc
, 0);
481 add_allocation_function("__vmalloc", &match_alloc
, 0);
482 add_allocation_function("vzalloc", &match_alloc
, 0);
483 add_allocation_function("sock_kmalloc", &match_alloc
, 1);
484 add_allocation_function("kmemdup", &match_alloc
, 1);
485 add_allocation_function("kmemdup_user", &match_alloc
, 1);
486 add_allocation_function("dma_alloc_attrs", &match_alloc
, 1);
487 add_allocation_function("pci_alloc_consistent", &match_alloc
, 1);
488 add_allocation_function("pci_alloc_coherent", &match_alloc
, 1);
489 add_allocation_function("devm_kmalloc", &match_alloc
, 1);
490 add_allocation_function("devm_kzalloc", &match_alloc
, 1);
491 add_allocation_function("kcalloc", &match_calloc
, 0);
492 add_allocation_function("kmalloc_array", &match_calloc
, 0);
493 add_allocation_function("devm_kcalloc", &match_calloc
, 1);
494 add_allocation_function("krealloc", &match_alloc
, 1);