comparison: white space cleanup
[smatch.git] / check_kernel.c
blobe5620259d1fa5722073895f90e4f8a5119afe2c2
1 /*
2 * sparse/check_kernel.c
4 * Copyright (C) 2010 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
11 * This is kernel specific stuff for smatch_extra.
14 #include "scope.h"
15 #include "smatch.h"
16 #include "smatch_extra.h"
18 static int implied_err_cast_return(struct expression *call, void *unused, struct range_list **rl)
20 struct expression *arg;
22 arg = get_argument_from_call_expr(call->args, 0);
23 if (!get_implied_rl(arg, rl))
24 *rl = alloc_rl(ll_to_sval(-4095), ll_to_sval(-1));
25 return 1;
28 static void match_param_valid_ptr(const char *fn, struct expression *call_expr,
29 struct expression *assign_expr, void *_param)
31 int param = PTR_INT(_param);
32 struct expression *arg;
33 struct smatch_state *pre_state;
34 struct smatch_state *end_state;
36 arg = get_argument_from_call_expr(call_expr->args, param);
37 pre_state = get_state_expr(SMATCH_EXTRA, arg);
38 end_state = estate_filter_range(pre_state, ll_to_sval(-4095), ll_to_sval(0));
39 set_extra_expr_nomod(arg, end_state);
42 static void match_param_err_or_null(const char *fn, struct expression *call_expr,
43 struct expression *assign_expr, void *_param)
45 int param = PTR_INT(_param);
46 struct expression *arg;
47 struct range_list *rl;
48 struct smatch_state *pre_state;
49 struct smatch_state *end_state;
51 arg = get_argument_from_call_expr(call_expr->args, param);
52 pre_state = get_state_expr(SMATCH_EXTRA, arg);
53 rl = alloc_rl(ll_to_sval(-4095), ll_to_sval(0));
54 rl = rl_intersection(estate_rl(pre_state), rl);
55 rl = cast_rl(estate_type(pre_state), rl);
56 end_state = alloc_estate_rl(rl);
57 set_extra_expr_nomod(arg, end_state);
60 static void match_not_err(const char *fn, struct expression *call_expr,
61 struct expression *assign_expr, void *unused)
63 struct expression *arg;
64 struct smatch_state *pre_state;
65 struct smatch_state *new_state;
67 arg = get_argument_from_call_expr(call_expr->args, 0);
68 pre_state = get_state_expr(SMATCH_EXTRA, arg);
69 new_state = estate_filter_range(pre_state, sval_type_min(&long_ctype), ll_to_sval(-1));
70 set_extra_expr_nomod(arg, new_state);
73 static void match_err(const char *fn, struct expression *call_expr,
74 struct expression *assign_expr, void *unused)
76 struct expression *arg;
77 struct smatch_state *pre_state;
78 struct smatch_state *new_state;
80 arg = get_argument_from_call_expr(call_expr->args, 0);
81 pre_state = get_state_expr(SMATCH_EXTRA, arg);
82 new_state = estate_filter_range(pre_state, sval_type_min(&long_ctype), ll_to_sval(-4096));
83 new_state = estate_filter_range(new_state, ll_to_sval(0), sval_type_max(&long_ctype));
84 set_extra_expr_nomod(arg, new_state);
87 static void match_container_of_macro(const char *fn, struct expression *expr, void *unused)
89 set_extra_expr_mod(expr->left, alloc_estate_range(valid_ptr_min_sval, valid_ptr_max_sval));
92 static void match_container_of(struct expression *expr)
94 struct expression *right = expr->right;
95 char *macro;
98 * The problem here is that sometimes the container_of() macro is itself
99 * inside a macro and get_macro() only returns the name of the outside
100 * macro.
104 * This actually an expression statement assignment but smatch_flow
105 * pre-mangles it for us so we only get the last chunk:
106 * sk = (typeof(sk))((char *)__mptr - offsetof(...))
109 macro = get_macro_name(right->pos);
110 if (!macro)
111 return;
112 if (right->type != EXPR_CAST)
113 return;
114 right = strip_expr(right);
115 if (right->type != EXPR_BINOP || right->op != '-' ||
116 right->left->type != EXPR_CAST)
117 return;
118 right = strip_expr(right->left);
119 if (right->type != EXPR_SYMBOL)
120 return;
121 if (!right->symbol->ident ||
122 strcmp(right->symbol->ident->name, "__mptr") != 0)
123 return;
124 set_extra_expr_mod(expr->left, alloc_estate_range(valid_ptr_min_sval, valid_ptr_max_sval));
127 static int match_next_bit(struct expression *call, void *unused, struct range_list **rl)
129 struct expression *start_arg;
130 struct expression *size_arg;
131 struct symbol *type;
132 sval_t min, max, tmp;
134 size_arg = get_argument_from_call_expr(call->args, 1);
135 /* btw. there isn't a start_arg for find_first_bit() */
136 start_arg = get_argument_from_call_expr(call->args, 2);
138 type = get_type(call);
139 min = sval_type_val(type, 0);
140 max = sval_type_val(type, sizeof(long long) * 8);
142 if (get_implied_max(size_arg, &tmp) && tmp.uvalue < max.value)
143 max = tmp;
144 if (start_arg && get_implied_min(start_arg, &tmp) && !sval_is_negative(tmp))
145 min = tmp;
146 if (sval_cmp(min, max) > 0)
147 max = min;
148 min = sval_cast(type, min);
149 max = sval_cast(type, max);
150 *rl = alloc_rl(min, max);
151 return 1;
154 static void find_module_init_exit(struct symbol_list *sym_list)
156 struct symbol *sym;
157 struct symbol *fn;
158 struct statement *stmt;
159 char *name;
160 int init;
161 int count;
164 * This is more complicated because Sparse ignores the "alias"
165 * attribute. I search backwards because module_init() is normally at
166 * the end of the file.
168 count = 0;
169 FOR_EACH_PTR_REVERSE(sym_list, sym) {
170 if (sym->type != SYM_NODE)
171 continue;
172 if (!(sym->ctype.modifiers & MOD_STATIC))
173 continue;
174 fn = get_base_type(sym);
175 if (!fn)
176 continue;
177 if (fn->type != SYM_FN)
178 continue;
179 if (!sym->ident || !sym->ident->name)
180 continue;
181 if (!fn->inline_stmt)
182 continue;
183 if (strcmp(sym->ident->name, "__inittest") == 0)
184 init = 1;
185 else if (strcmp(sym->ident->name, "__exittest") == 0)
186 init = 0;
187 else
188 continue;
190 count++;
192 stmt = first_ptr_list((struct ptr_list *)fn->inline_stmt->stmts);
193 if (!stmt || stmt->type != STMT_RETURN)
194 continue;
195 name = expr_to_var(stmt->ret_value);
196 if (!name)
197 continue;
198 if (init)
199 sql_insert_function_ptr(name, "(struct module)->init");
200 else
201 sql_insert_function_ptr(name, "(struct module)->exit");
202 free_string(name);
203 if (count >= 2)
204 return;
205 } END_FOR_EACH_PTR_REVERSE(sym);
208 static void match_end_file(struct symbol_list *sym_list)
210 struct symbol *sym;
212 /* find the last static symbol in the file */
213 FOR_EACH_PTR_REVERSE(sym_list, sym) {
214 if (!(sym->ctype.modifiers & MOD_STATIC))
215 continue;
216 if (!sym->scope)
217 continue;
218 find_module_init_exit(sym->scope->symbols);
219 return;
220 } END_FOR_EACH_PTR_REVERSE(sym);
223 void check_kernel(int id)
225 if (option_project != PROJ_KERNEL)
226 return;
228 add_implied_return_hook("ERR_PTR", &implied_err_cast_return, NULL);
229 add_implied_return_hook("ERR_CAST", &implied_err_cast_return, NULL);
230 add_implied_return_hook("PTR_ERR", &implied_err_cast_return, NULL);
231 return_implies_state("IS_ERR_OR_NULL", 0, 0, &match_param_valid_ptr, (void *)0);
232 return_implies_state("IS_ERR_OR_NULL", 1, 1, &match_param_err_or_null, (void *)0);
233 return_implies_state("IS_ERR", 0, 0, &match_not_err, NULL);
234 return_implies_state("IS_ERR", 1, 1, &match_err, NULL);
235 return_implies_state("tomoyo_memory_ok", 1, 1, &match_param_valid_ptr, (void *)0);
237 add_macro_assign_hook_extra("container_of", &match_container_of_macro, NULL);
238 add_hook(match_container_of, ASSIGNMENT_HOOK);
240 add_implied_return_hook("find_next_bit", &match_next_bit, NULL);
241 add_implied_return_hook("find_next_zero_bit", &match_next_bit, NULL);
242 add_implied_return_hook("find_first_bit", &match_next_bit, NULL);
243 add_implied_return_hook("find_first_zero_bit", &match_next_bit, NULL);
245 add_function_hook("__ftrace_bad_type", &__match_nullify_path_hook, NULL);
247 if (option_info)
248 add_hook(match_end_file, END_FILE_HOOK);