Small clean up. Allocating filter.
[smatch.git] / check_err_ptr_deref.c
blob36f69ea08aad158bee6c7dc91067c3109f22f081
1 /*
2 * sparse/check_err_ptr_deref.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "smatch.h"
11 #include "smatch_slist.h"
13 static int my_id;
15 STATE(err_ptr);
16 STATE(checked);
18 static void check_is_err_ptr(struct sm_state *sm)
20 if (slist_has_state(sm->possible, &err_ptr)) {
21 smatch_msg("error: '%s' dereferencing possible ERR_PTR()",
22 sm->name);
23 set_state(sm->name, my_id, sm->sym, &checked);
27 static void match_returns_err_ptr(const char *fn, struct expression *expr,
28 void *info)
30 char *left_name = NULL;
31 struct symbol *left_sym;
33 left_name = get_variable_from_expr(expr->left, &left_sym);
34 if (!left_name || !left_sym)
35 goto free;
36 set_state(left_name, my_id, left_sym, &err_ptr);
37 free:
38 free_string(left_name);
41 static void match_is_err(const char *fn, struct expression *expr,
42 void *data)
44 char *name;
45 struct symbol *sym;
47 expr = get_argument_from_call_expr(expr->args, 0);
48 if (expr->type == EXPR_ASSIGNMENT)
49 expr = expr->left;
50 name = get_variable_from_expr(expr, &sym);
51 if (!name || !sym)
52 goto free;
53 set_cond_states(name, my_id, sym, &err_ptr, &checked);
54 free:
55 free_string(name);
58 static void match_dereferences(struct expression *expr)
60 char *deref = NULL;
61 struct symbol *sym = NULL;
62 struct sm_state *sm;
64 deref = get_variable_from_expr(expr->deref->unop, &sym);
65 if (!deref || !sym)
66 goto free;
68 sm = get_sm_state(deref, my_id, sym);
69 if (sm)
70 check_is_err_ptr(sm);
71 free:
72 free_string(deref);
75 static void register_err_ptr_funcs(void)
77 struct token *token;
78 const char *func;
80 token = get_tokens_file("kernel.returns_err_ptr");
81 if (!token)
82 return;
83 if (token_type(token) != TOKEN_STREAMBEGIN)
84 return;
85 token = token->next;
86 while (token_type(token) != TOKEN_STREAMEND) {
87 if (token_type(token) != TOKEN_IDENT)
88 return;
89 func = show_ident(token->ident);
90 add_function_assign_hook(func, &match_returns_err_ptr, NULL);
91 token = token->next;
93 clear_token_alloc();
96 void check_err_ptr_deref(int id)
98 my_id = id;
99 add_conditional_hook("IS_ERR", &match_is_err, NULL);
100 register_err_ptr_funcs();
101 add_hook(&match_dereferences, DEREF_HOOK);