2 * sparse/check_err_ptr_deref.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
11 #include "smatch_slist.h"
12 #include "smatch_extra.h"
19 static void check_is_err_ptr(struct sm_state
*sm
)
21 if (slist_has_state(sm
->possible
, &err_ptr
)) {
22 smatch_msg("error: '%s' dereferencing possible ERR_PTR()",
24 set_state(sm
->name
, my_id
, sm
->sym
, &checked
);
28 static void match_returns_err_ptr(const char *fn
, struct expression
*expr
,
31 char *left_name
= NULL
;
32 struct symbol
*left_sym
;
34 left_name
= get_variable_from_expr(expr
->left
, &left_sym
);
35 if (!left_name
|| !left_sym
)
37 set_state(left_name
, my_id
, left_sym
, &err_ptr
);
39 free_string(left_name
);
42 static void match_is_err(const char *fn
, struct expression
*expr
,
48 expr
= get_argument_from_call_expr(expr
->args
, 0);
49 if (expr
->type
== EXPR_ASSIGNMENT
)
51 name
= get_variable_from_expr(expr
, &sym
);
54 set_true_false_states(name
, my_id
, sym
, &err_ptr
, &checked
);
59 static void match_dereferences(struct expression
*expr
)
62 struct symbol
*sym
= NULL
;
65 deref
= get_variable_from_expr(expr
->deref
->unop
, &sym
);
69 sm
= get_sm_state(deref
, my_id
, sym
);
76 static void register_err_ptr_funcs(void)
81 token
= get_tokens_file("kernel.returns_err_ptr");
84 if (token_type(token
) != TOKEN_STREAMBEGIN
)
87 while (token_type(token
) != TOKEN_STREAMEND
) {
88 if (token_type(token
) != TOKEN_IDENT
)
90 func
= show_ident(token
->ident
);
91 add_function_assign_hook(func
, &match_returns_err_ptr
, NULL
);
97 static void match_err_ptr(const char *fn
, struct expression
*expr
, void *info
)
99 struct expression
*arg
;
103 struct sm_state
*tmp
;
106 long long min
= whole_range
.max
;
107 long long max
= whole_range
.min
;
109 arg
= get_argument_from_call_expr(expr
->args
, 0);
110 name
= get_variable_from_expr(arg
, &sym
);
113 sm
= get_sm_state(name
, SMATCH_EXTRA
, sym
);
116 FOR_EACH_PTR(sm
->possible
, tmp
) {
117 tmp_min
= get_dinfo_min((struct data_info
*)tmp
->state
->data
);
118 if (tmp_min
!= whole_range
.min
&& tmp_min
< min
)
120 tmp_max
= get_dinfo_max((struct data_info
*)tmp
->state
->data
);
121 if (tmp_max
!= whole_range
.max
&& tmp_max
> max
)
123 } END_FOR_EACH_PTR(tmp
);
125 smatch_msg("error: %lld too low for ERR_PTR", min
);
127 smatch_msg("error: passing non neg %lld to ERR_PTR", max
);
132 void check_err_ptr_deref(int id
)
135 add_conditional_hook("IS_ERR", &match_is_err
, NULL
);
136 register_err_ptr_funcs();
137 add_hook(&match_dereferences
, DEREF_HOOK
);
138 add_function_hook("ERR_PTR", &match_err_ptr
, NULL
);