1 /*
2  * Copyright (C) 2010 Dan Carpenter.
3  *
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.
8  *
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.
13  *
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
16  */
17 
18 /*
19  * This file is only for very generic stuff, that is reusable
20  * between projects.  If you need something special create a
21  * check_your_project.c.
22  *
23  */
24 
25 #include "smatch.h"
26 #include "smatch_extra.h"
27 #include "smatch_function_hashtable.h"
28 
29 static DEFINE_HASHTABLE_INSERT(insert_func, char, int);
30 static DEFINE_HASHTABLE_SEARCH(search_func, char, int);
31 static struct hashtable *skipped_funcs;
32 static struct hashtable *silenced_funcs;
33 static struct hashtable *no_inline_funcs;
34 
is_skipped_function(void)35 int is_skipped_function(void)
36 {
37 	char *func;
38 
39 	func = get_function();
40 	if (!func)
41 		return 0;
42 	if (search_func(skipped_funcs, func))
43 		return 1;
44 	return 0;
45 }
46 
47 /*
48  * A silenced function will still be processed and potentially appear in info
49  * output, but not regular checks.
50  */
is_silenced_function(void)51 int is_silenced_function(void)
52 {
53 	char *func;
54 
55 	if (is_skipped_function())
56 		return 1;
57 
58 	func = get_function();
59 	if (!func)
60 		return 0;
61 	if (search_func(silenced_funcs, func))
62 		return 1;
63 	return 0;
64 }
65 
is_no_inline_function(const char * function)66 int is_no_inline_function(const char *function)
67 {
68 	if (search_func(no_inline_funcs, (char *)function))
69 		return 1;
70 	return 0;
71 }
72 
register_no_return_funcs(void)73 static void register_no_return_funcs(void)
74 {
75 	struct token *token;
76 	const char *func;
77 	char name[256];
78 
79 	snprintf(name, 256, "%s.no_return_funcs", option_project_str);
80 
81 	token = get_tokens_file(name);
82 	if (!token)
83 		return;
84 	if (token_type(token) != TOKEN_STREAMBEGIN)
85 		return;
86 	token = token->next;
87 	while (token_type(token) != TOKEN_STREAMEND) {
88 		if (token_type(token) != TOKEN_IDENT)
89 			return;
90 		func = show_ident(token->ident);
91 		add_function_hook(func, &__match_nullify_path_hook, NULL);
92 		token = token->next;
93 	}
94 	clear_token_alloc();
95 }
96 
register_ignored_macros(void)97 static void register_ignored_macros(void)
98 {
99 	struct token *token;
100 	char *macro;
101 	char name[256];
102 
103 	if (option_project == PROJ_NONE)
104 		strcpy(name, "ignored_macros");
105 	else
106 		snprintf(name, 256, "%s.ignored_macros", option_project_str);
107 
108 	token = get_tokens_file(name);
109 	if (!token)
110 		return;
111 	if (token_type(token) != TOKEN_STREAMBEGIN)
112 		return;
113 	token = token->next;
114 	while (token_type(token) != TOKEN_STREAMEND) {
115 		if (token_type(token) != TOKEN_IDENT)
116 			return;
117 		macro = alloc_string(show_ident(token->ident));
118 		add_ptr_list(&__ignored_macros, macro);
119 		token = token->next;
120 	}
121 	clear_token_alloc();
122 }
123 
register_skipped_functions(void)124 static void register_skipped_functions(void)
125 {
126 	struct token *token;
127 	char *func;
128 	char name[256];
129 
130 	skipped_funcs = create_function_hashtable(500);
131 
132 	if (option_project == PROJ_NONE)
133 		return;
134 
135 	snprintf(name, 256, "%s.skipped_functions", option_project_str);
136 
137 	token = get_tokens_file(name);
138 	if (!token)
139 		return;
140 	if (token_type(token) != TOKEN_STREAMBEGIN)
141 		return;
142 	token = token->next;
143 	while (token_type(token) != TOKEN_STREAMEND) {
144 		if (token_type(token) != TOKEN_IDENT)
145 			return;
146 		func = alloc_string(show_ident(token->ident));
147 		insert_func(skipped_funcs, func, INT_PTR(1));
148 		token = token->next;
149 	}
150 	clear_token_alloc();
151 }
152 
register_silenced_functions(void)153 static void register_silenced_functions(void)
154 {
155 	struct token *token;
156 	char *func;
157 	char name[256];
158 
159 	silenced_funcs = create_function_hashtable(500);
160 
161 	if (option_project == PROJ_NONE)
162 		return;
163 
164 	snprintf(name, 256, "%s.silenced_functions", option_project_str);
165 
166 	token = get_tokens_file(name);
167 	if (!token)
168 		return;
169 	if (token_type(token) != TOKEN_STREAMBEGIN)
170 		return;
171 	token = token->next;
172 	while (token_type(token) != TOKEN_STREAMEND) {
173 		if (token_type(token) != TOKEN_IDENT)
174 			return;
175 		func = alloc_string(show_ident(token->ident));
176 		insert_func(silenced_funcs, func, INT_PTR(1));
177 		token = token->next;
178 	}
179 	clear_token_alloc();
180 }
181 
register_no_inline_functions(void)182 static void register_no_inline_functions(void)
183 {
184 	struct token *token;
185 	char *func;
186 	char name[256];
187 
188 	no_inline_funcs = create_function_hashtable(500);
189 
190 	if (option_project == PROJ_NONE)
191 		return;
192 
193 	snprintf(name, 256, "%s.no_inline_functions", option_project_str);
194 
195 	token = get_tokens_file(name);
196 	if (!token)
197 		return;
198 	if (token_type(token) != TOKEN_STREAMBEGIN)
199 		return;
200 	token = token->next;
201 	while (token_type(token) != TOKEN_STREAMEND) {
202 		if (token_type(token) != TOKEN_IDENT)
203 			return;
204 		func = alloc_string(show_ident(token->ident));
205 		insert_func(no_inline_funcs, func, INT_PTR(1));
206 		token = token->next;
207 	}
208 	clear_token_alloc();
209 }
210 
register_project(int id)211 void register_project(int id)
212 {
213 	register_no_return_funcs();
214 	register_ignored_macros();
215 	register_skipped_functions();
216 	register_silenced_functions();
217 	register_no_inline_functions();
218 }
219