2 * Copyright (C) 2010 Dan Carpenter.
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 * This is like check_deref_check.c except that it complains about code like:
24 * Of course, Smatch has complained about these for forever but the problem is
25 * the old scripts were too messy and complicated and generated too many false
28 * This check is supposed to be simpler because it only looks for one kind of
29 * null dereference bug instead of every kind. It also gets rid of the false
30 * positives caused by the checks that happen inside macros.
35 #include "smatch_slist.h"
36 #include "smatch_extra.h"
43 static void is_ok(struct sm_state
*sm
, struct expression
*mod_expr
)
45 set_state(my_id
, sm
->name
, sm
->sym
, &ok
);
48 static int get_checked_line_var_sym(char *name
, struct symbol
*sym
)
53 sm
= get_sm_state(my_id
, name
, sym
);
56 if (is_ignored(my_id
, sm
->name
, sm
->sym
))
58 if (implied_not_equal_name_sym(name
, sym
, 0))
61 FOR_EACH_PTR(sm
->possible
, tmp
) {
62 if (tmp
->state
== &merged
)
64 if (tmp
->state
== &ok
)
66 if (tmp
->state
== &null
)
68 } END_FOR_EACH_PTR(tmp
);
73 static int get_checked_line(struct expression
*expr
)
79 name
= expr_to_var_sym(expr
, &sym
);
82 line
= get_checked_line_var_sym(name
, sym
);
88 static void deref_hook(struct expression
*expr
)
92 struct range_list
*rl
;
95 if (__in_fake_assign
|| __in_fake_parameter_assign
)
98 line
= get_checked_line(expr
);
102 get_absolute_rl(expr
, &rl
);
103 if (!rl_has_sval(rl
, sval_type_val(rl_type(rl
), 0)))
106 name
= expr_to_var_sym(expr
, &sym
);
110 sm_error("we previously assumed '%s' could be null (see line %d)",
113 add_ignore(my_id
, name
, sym
);
118 static void match_condition(struct expression
*expr
)
120 struct smatch_state
*true_state
= NULL
;
123 name
= get_macro_name(expr
->pos
);
125 (strcmp(name
, "likely") != 0 && strcmp(name
, "unlikely") != 0))
128 if (!is_pointer(expr
))
131 if (expr
->type
== EXPR_ASSIGNMENT
) {
132 match_condition(expr
->right
);
133 match_condition(expr
->left
);
136 if (implied_not_equal(expr
, 0))
139 if (get_state_expr(my_id
, expr
))
142 set_true_false_states_expr(my_id
, expr
, true_state
, &null
);
145 void check_check_deref(int id
)
149 add_modification_hook(my_id
, &is_ok
);
150 add_hook(&match_condition
, CONDITION_HOOK
);
151 add_dereference_hook(deref_hook
);