Avoid triggering a division by zero in the overflow check
[smatch.git] / check_balanced.c
blob5db83bc4ef507acdf5e3b080212e032efa2bde39
1 /*
2 * sparse/check_prempt.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
11 * This test checks that prempt is enabled at the end of every function.
14 #include "smatch.h"
15 #include "smatch_slist.h"
17 static int my_id;
19 STATE(left);
20 STATE(right);
21 STATE(start_state);
23 static struct tracker_list *starts_left;
24 static struct tracker_list *starts_right;
26 static struct smatch_state *get_start_state(struct sm_state *sm)
28 int is_left = 0;
29 int is_right = 0;
31 if (in_tracker_list(starts_left, my_id, sm->name, sm->sym))
32 is_left = 1;
33 if (in_tracker_list(starts_right, my_id, sm->name, sm->sym))
34 is_right = 1;
35 if (is_left && is_right)
36 return &undefined;
37 if (is_left)
38 return &left;
39 if (is_right)
40 return &right;
41 return &undefined;
44 static struct smatch_state *unmatched_state(struct sm_state *sm)
46 return &start_state;
49 static void match_left(const char *fn, struct expression *expr, void *data)
51 struct sm_state *sm;
52 char *name = (char *)data;
54 sm = get_sm_state(my_id, name, NULL);
55 if (!sm)
56 add_tracker(&starts_right, my_id, name, NULL);
57 if (sm && slist_has_state(sm->possible, &left))
58 sm_msg("warn: double '%s'", fn);
59 set_state(my_id, (char *)data, NULL, &left);
62 static void match_right(const char *fn, struct expression *expr, void *data)
64 struct sm_state *sm;
65 char *name = (char *)data;
67 sm = get_sm_state(my_id, name, NULL);
68 if (!sm)
69 add_tracker(&starts_left, my_id, name, NULL);
70 if (sm && slist_has_state(sm->possible, &right))
71 sm_msg("warn: double '%s'", fn);
72 set_state(my_id, (char *)data, NULL, &right);
75 static void check_possible(struct sm_state *sm)
77 struct sm_state *tmp;
78 int is_left = 0;
79 int is_right = 0;
80 int undef = 0;
82 FOR_EACH_PTR(sm->possible, tmp) {
83 if (tmp->state == &left)
84 is_left = 1;
85 if (tmp->state == &right)
86 is_right = 1;
87 if (tmp->state == &start_state) {
88 struct smatch_state *s;
90 s = get_start_state(tmp);
91 if (s == &left)
92 is_left = 1;
93 else if (s == &right)
94 is_right = 1;
95 else
96 undef = 1;
98 if (tmp->state == &undefined)
99 undef = 1; // i don't think this is possible any more.
100 } END_FOR_EACH_PTR(tmp);
101 if ((is_left && is_right) || undef)
102 sm_msg("warn: returning with unbalanced %s", sm->name);
105 static void match_return(struct expression *expr)
107 struct state_list *slist;
108 struct sm_state *tmp;
110 slist = get_all_states(my_id);
111 FOR_EACH_PTR(slist, tmp) {
112 if (tmp->state == &merged)
113 check_possible(tmp);
114 } END_FOR_EACH_PTR(tmp);
115 free_slist(&slist);
118 static void clear_lists(void)
120 free_trackers_and_list(&starts_left);
121 free_trackers_and_list(&starts_right);
124 static void match_func_end(struct symbol *sym)
126 if (is_reachable())
127 match_return(NULL);
128 clear_lists();
131 static void get_left_funcs(const char *name, struct token **token)
133 const char *func;
135 while (token_type(*token) == TOKEN_IDENT) {
136 func = show_ident((*token)->ident);
137 add_function_hook(func, &match_left, (char *)name);
138 *token = (*token)->next;
140 if (token_type(*token) == TOKEN_SPECIAL)
141 *token = (*token)->next;
144 static void get_right_funcs(const char *name, struct token **token)
146 const char *func;
148 while (token_type(*token) == TOKEN_IDENT) {
149 func = show_ident((*token)->ident);
150 add_function_hook(func, &match_right, (char *)name);
151 *token = (*token)->next;
153 if (token_type(*token) == TOKEN_SPECIAL)
154 *token = (*token)->next;
157 static void register_funcs_from_file(void)
159 struct token *token;
160 char *name;
162 token = get_tokens_file("kernel.balanced_funcs");
163 if (!token)
164 return;
165 if (token_type(token) != TOKEN_STREAMBEGIN)
166 return;
167 token = token->next;
168 while (token_type(token) != TOKEN_STREAMEND) {
169 if (token_type(token) != TOKEN_IDENT)
170 return;
171 name = alloc_string(show_ident(token->ident));
172 token = token->next;
173 get_left_funcs(name, &token);
174 get_right_funcs(name, &token);
176 clear_token_alloc();
179 void check_balanced(int id)
181 my_id = id;
182 add_unmatched_state_hook(my_id, &unmatched_state);
183 add_hook(&match_return, RETURN_HOOK);
184 add_hook(&match_func_end, END_FUNC_HOOK);
185 register_funcs_from_file();