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"
23 static int bytes_per_element(struct expression
*expr
)
27 type
= get_type(expr
);
31 if (type
->type
!= SYM_PTR
&& type
->type
!= SYM_ARRAY
)
34 type
= get_base_type(type
);
35 return type_bytes(type
);
38 static void save_constraint_required(struct expression
*pointer
, int op
, struct expression
*constraint
)
42 data
= get_constraint_str(pointer
);
46 limit
= get_constraint_str(constraint
);
48 // FIXME deal with <= also
50 set_state_expr(my_id
, constraint
, alloc_state_expr(pointer
));
54 sql_save_constraint_required(data
, op
, limit
);
61 static void match_alloc(const char *fn
, struct expression
*expr
, void *_size_arg
)
63 int size_arg
= PTR_INT(_size_arg
);
64 struct expression
*pointer
, *call
, *arg
;
67 pointer
= strip_expr(expr
->left
);
68 call
= strip_expr(expr
->right
);
69 arg
= get_argument_from_call_expr(call
->args
, size_arg
);
70 arg
= strip_expr(arg
);
72 if (arg
->type
== EXPR_BINOP
&& arg
->op
== '*') {
73 struct expression
*left
, *right
;
75 left
= strip_expr(arg
->left
);
76 right
= strip_expr(arg
->right
);
78 if (get_implied_value(left
, &sval
) &&
79 sval
.value
== bytes_per_element(pointer
))
81 else if (get_implied_value(right
, &sval
) &&
82 sval
.value
== bytes_per_element(pointer
))
88 if (arg
->type
== EXPR_BINOP
&& arg
->op
== '+' &&
89 get_implied_value(expr
->right
, &sval
) &&
91 save_constraint_required(pointer
, SPECIAL_LTE
, arg
->left
);
93 save_constraint_required(pointer
, '<', arg
);
96 static void match_calloc(const char *fn
, struct expression
*expr
, void *_start_arg
)
98 struct expression
*pointer
, *call
, *size
;
99 struct expression
*count
= NULL
;
100 int start_arg
= PTR_INT(_start_arg
);
103 pointer
= strip_expr(expr
->left
);
104 call
= strip_expr(expr
->right
);
106 size
= get_argument_from_call_expr(call
->args
, start_arg
);
107 if (get_implied_value(size
, &sval
) &&
108 sval
.value
== bytes_per_element(pointer
))
109 count
= get_argument_from_call_expr(call
->args
, start_arg
+ 1);
111 size
= get_argument_from_call_expr(call
->args
, start_arg
+ 1);
112 if (get_implied_value(size
, &sval
) &&
113 sval
.value
== bytes_per_element(pointer
))
114 count
= get_argument_from_call_expr(call
->args
, start_arg
);
120 save_constraint_required(pointer
, '<', count
);
123 static void add_allocation_function(const char *func
, void *call_back
, int param
)
125 add_function_assign_hook(func
, call_back
, INT_PTR(param
));
128 static void match_assign_state(struct expression
*expr
)
130 struct smatch_state
*state
;
133 state
= get_state_expr(my_id
, expr
->right
);
134 if (!state
|| !state
->data
)
137 data
= get_constraint_str(state
->data
);
141 limit
= get_constraint_str(expr
->left
);
145 sql_save_constraint_required(data
, '<', limit
);
152 static void match_assign_ARRAY_SIZE(struct expression
*expr
)
154 struct expression
*array
;
158 macro
= get_macro_name(expr
->right
->pos
);
159 if (!macro
|| strcmp(macro
, "ARRAY_SIZE") != 0)
161 array
= strip_expr(expr
->right
);
162 if (array
->type
!= EXPR_BINOP
|| array
->op
!= '+')
164 array
= strip_expr(array
->left
);
165 if (array
->type
!= EXPR_BINOP
|| array
->op
!= '/')
167 array
= strip_expr(array
->left
);
168 if (array
->type
!= EXPR_SIZEOF
)
170 array
= strip_expr(array
->cast_expression
);
171 if (array
->type
!= EXPR_PREOP
|| array
->op
!= '*')
173 array
= strip_expr(array
->unop
);
175 data
= get_constraint_str(array
);
176 limit
= get_constraint_str(expr
->left
);
180 sql_save_constraint_required(data
, '<', limit
);
187 void register_constraints_required(int id
)
191 add_hook(&match_assign_state
, ASSIGNMENT_HOOK
);
193 add_hook(&match_assign_ARRAY_SIZE
, ASSIGNMENT_HOOK
);
194 add_hook(&match_assign_ARRAY_SIZE
, GLOBAL_ASSIGNMENT_HOOK
);
196 add_allocation_function("malloc", &match_alloc
, 0);
197 add_allocation_function("memdup", &match_alloc
, 1);
198 add_allocation_function("realloc", &match_alloc
, 1);
199 add_allocation_function("realloc", &match_calloc
, 0);
200 if (option_project
== PROJ_KERNEL
) {
201 add_allocation_function("kmalloc", &match_alloc
, 0);
202 add_allocation_function("kzalloc", &match_alloc
, 0);
203 add_allocation_function("vmalloc", &match_alloc
, 0);
204 add_allocation_function("__vmalloc", &match_alloc
, 0);
205 add_allocation_function("sock_kmalloc", &match_alloc
, 1);
206 add_allocation_function("kmemdup", &match_alloc
, 1);
207 add_allocation_function("kmemdup_user", &match_alloc
, 1);
208 add_allocation_function("dma_alloc_attrs", &match_alloc
, 1);
209 add_allocation_function("pci_alloc_consistent", &match_alloc
, 1);
210 add_allocation_function("pci_alloc_coherent", &match_alloc
, 1);
211 add_allocation_function("devm_kmalloc", &match_alloc
, 1);
212 add_allocation_function("devm_kzalloc", &match_alloc
, 1);
213 add_allocation_function("kcalloc", &match_calloc
, 0);
214 add_allocation_function("devm_kcalloc", &match_calloc
, 1);
215 add_allocation_function("krealloc", &match_alloc
, 1);