db: remove untrusted table
[smatch.git] / smatch_db.c
blob924e671c0e4bc23b15f61220690e4df08e109edb
1 /*
2 * smatch/smatch_db.c
4 * Copyright (C) 2010 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include <string.h>
11 #include <errno.h>
12 #include <sqlite3.h>
13 #include "smatch.h"
14 #include "smatch_slist.h"
15 #include "smatch_extra.h"
17 static sqlite3 *db;
19 struct def_callback {
20 int hook_type;
21 void (*callback)(const char *name, struct symbol *sym, char *key, char *value);
23 ALLOCATOR(def_callback, "definition db hook callbacks");
24 DECLARE_PTR_LIST(callback_list, struct def_callback);
25 static struct callback_list *callbacks;
27 struct member_info_callback {
28 int owner;
29 void (*callback)(char *fn, int param, char *printed_name, struct smatch_state *state);
31 ALLOCATOR(member_info_callback, "caller_info callbacks");
32 DECLARE_PTR_LIST(member_info_cb_list, struct member_info_callback);
33 static struct member_info_cb_list *member_callbacks;
35 void sql_exec(int (*callback)(void*, int, char**, char**), const char *sql)
37 char *err = NULL;
38 int rc;
40 if (option_no_db || !db)
41 return;
43 rc = sqlite3_exec(db, sql, callback, 0, &err);
44 if (rc != SQLITE_OK) {
45 fprintf(stderr, "SQL error #2: %s\n", err);
46 exit(1);
50 void add_definition_db_callback(void (*callback)(const char *name, struct symbol *sym, char *key, char *value), int type)
52 struct def_callback *def_callback = __alloc_def_callback(0);
54 def_callback->hook_type = type;
55 def_callback->callback = callback;
56 add_ptr_list(&callbacks, def_callback);
59 void add_member_info_callback(int owner, void (*callback)(char *fn, int param, char *printed_name, struct smatch_state *state))
61 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
63 member_callback->owner = owner;
64 member_callback->callback = callback;
65 add_ptr_list(&member_callbacks, member_callback);
68 static void match_call_hack(struct expression *expr)
70 char *name;
73 * we just want to record something in the database so that if we have
74 * two calls like: frob(4); frob(some_unkown); then on the recieving
75 * side we know that sometimes frob is called with unknown parameters.
78 name = get_fnptr_name(expr->fn);
79 if (!name)
80 return;
81 if (ptr_list_empty(expr->args))
82 return;
83 sm_msg("info: passes param_value '%s' -1 '$$' min-max", name);
84 free_string(name);
87 static void print_struct_members(char *fn, struct expression *expr, int param, struct state_list *slist,
88 void (*callback)(char *fn, int param, char *printed_name, struct smatch_state *state))
90 struct sm_state *sm;
91 char *name;
92 struct symbol *sym;
93 int len;
94 char printed_name[256];
96 name = get_variable_from_expr(expr, &sym);
97 if (!name || !sym)
98 goto free;
100 len = strlen(name);
101 FOR_EACH_PTR(slist, sm) {
102 if (sm->sym != sym)
103 continue;
104 if (strncmp(name, sm->name, len) || sm->name[len] == '\0')
105 continue;
106 snprintf(printed_name, sizeof(printed_name), "$$%s", sm->name + len);
107 callback(fn, param, printed_name, sm->state);
108 } END_FOR_EACH_PTR(sm);
109 free:
110 free_string(name);
113 static void match_call_info(struct expression *expr)
115 struct member_info_callback *cb;
116 struct expression *arg;
117 struct state_list *slist;
118 char *name;
119 int i;
121 name = get_fnptr_name(expr->fn);
122 if (!name)
123 return;
125 FOR_EACH_PTR(member_callbacks, cb) {
126 slist = get_all_states(cb->owner);
127 i = 0;
128 FOR_EACH_PTR(expr->args, arg) {
129 print_struct_members(name, arg, i, slist, cb->callback);
130 i++;
131 } END_FOR_EACH_PTR(arg);
132 } END_FOR_EACH_PTR(cb);
134 free_string(name);
135 free_slist(&slist);
138 static unsigned long call_count;
139 static int db_count_callback(void *unused, int argc, char **argv, char **azColName)
141 call_count += strtoul(argv[0], NULL, 10);
142 return 0;
145 static int get_param(int param, char **name, struct symbol **sym)
147 struct symbol *arg;
148 int i;
150 i = 0;
151 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
153 * this is a temporary hack to work around a bug (I think in sparse?)
154 * 2.6.37-rc1:fs/reiserfs/journal.o
155 * If there is a function definition without parameter name found
156 * after a function implementation then it causes a crash.
157 * int foo() {}
158 * int bar(char *);
160 if (arg->ident->name < (char *)100)
161 continue;
162 if (i == param && arg->ident->name) {
163 *name = arg->ident->name;
164 *sym = arg;
165 return TRUE;
167 i++;
168 } END_FOR_EACH_PTR(arg);
170 return FALSE;
173 static struct state_list *final_states;
174 static int prev_func_id = -1;
175 static int db_callback(void *unused, int argc, char **argv, char **azColName)
177 int func_id;
178 long type;
179 long param;
180 char *name;
181 struct symbol *sym;
182 struct def_callback *def_callback;
184 if (argc != 5)
185 return 0;
187 func_id = atoi(argv[0]);
188 errno = 0;
189 type = strtol(argv[1], NULL, 10);
190 param = strtol(argv[2], NULL, 10);
191 if (errno)
192 return 0;
194 if (prev_func_id == -1)
195 prev_func_id = func_id;
196 if (func_id != prev_func_id) {
197 merge_slist(&final_states, __pop_fake_cur_slist());
198 __push_fake_cur_slist();
199 prev_func_id = func_id;
202 if (param == -1 || !get_param(param, &name, &sym))
203 return 0;
205 FOR_EACH_PTR(callbacks, def_callback) {
206 if (def_callback->hook_type == type)
207 def_callback->callback(name, sym, argv[3], argv[4]);
208 } END_FOR_EACH_PTR(def_callback);
210 return 0;
213 static void get_direct_callers(struct symbol *sym)
215 char sql_filter[1024];
217 if (sym->ctype.modifiers & MOD_STATIC) {
218 snprintf(sql_filter, 1024,
219 "file = '%s' and function = '%s' order by function_id;",
220 get_filename(), sym->ident->name);
221 } else {
222 snprintf(sql_filter, 1024,
223 "function = '%s' order by function_id;",
224 sym->ident->name);
227 run_sql(db_count_callback, "select count(*) from caller_info where %s",
228 sql_filter);
229 if (call_count == 0 || call_count > 100)
230 return;
232 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
233 " where %s", sql_filter);
236 static char *ptr_name;
237 static int get_ptr_name(void *unused, int argc, char **argv, char **azColName)
239 if (!ptr_name)
240 ptr_name = alloc_string(argv[0]);
241 return 0;
244 static void get_function_pointer_callers(struct symbol *sym)
246 ptr_name = NULL;
247 run_sql(get_ptr_name, "select ptr from function_ptr where function = '%s'",
248 sym->ident->name);
249 if (!ptr_name)
250 return;
252 run_sql(db_count_callback, "select count(*) from caller_info where function = '%s'",
253 ptr_name);
254 if (call_count == 0 || call_count > 100)
255 return;
257 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
258 " where function = '%s' order by function_id", ptr_name);
261 static void match_data_from_db(struct symbol *sym)
263 struct sm_state *sm;
265 if (!sym || !sym->ident || !sym->ident->name)
266 return;
268 __push_fake_cur_slist();
269 prev_func_id = -1;
271 call_count = 0;
272 get_direct_callers(sym);
273 get_function_pointer_callers(sym);
275 merge_slist(&final_states, __pop_fake_cur_slist());
277 if (call_count > 100) {
278 free_slist(&final_states);
279 return;
281 FOR_EACH_PTR(final_states, sm) {
282 __set_sm(sm);
283 } END_FOR_EACH_PTR(sm);
285 free_slist(&final_states);
288 static void match_function_assign(struct expression *expr)
290 struct expression *right = expr->right;
291 struct symbol *sym;
292 char *fn_name;
293 char *ptr_name;
295 if (right->type == EXPR_PREOP && right->op == '&')
296 right = right->unop;
297 if (right->type != EXPR_SYMBOL)
298 return;
299 sym = get_type(right);
300 if (!sym || sym->type != SYM_FN)
301 return;
303 fn_name = get_variable_from_expr(right, NULL);
304 ptr_name = get_fnptr_name(expr->left);
305 if (!fn_name || !ptr_name)
306 goto free;
308 sm_msg("info: sets_fn_ptr '%s' '%s'", ptr_name, fn_name);
310 free:
311 free_string(fn_name);
312 free_string(ptr_name);
315 static void global_variable(struct symbol *sym)
317 struct symbol *struct_type;
318 struct symbol *base_type;
319 struct expression *expr;
321 if (!sym->ident)
322 return;
323 if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
324 return;
325 struct_type = get_base_type(sym);
326 if (!struct_type || struct_type->type != SYM_STRUCT ||
327 !struct_type->ident)
328 return;
330 FOR_EACH_PTR(sym->initializer->expr_list, expr) {
331 if (expr->type != EXPR_IDENTIFIER)
332 continue;
333 if (!expr->expr_ident)
334 continue;
335 if (!expr->ident_expression || !expr->ident_expression->symbol_name)
336 continue;
337 base_type = get_type(expr->ident_expression);
338 if (!base_type || base_type->type != SYM_FN)
339 continue;
340 sm_msg("info: sets_fn_ptr '(struct %s)->%s' '%s'", struct_type->ident->name,
341 expr->expr_ident->name,
342 expr->ident_expression->symbol_name->name);
343 } END_FOR_EACH_PTR(expr);
346 void open_smatch_db(void)
348 #ifdef SQLITE_OPEN_READONLY
349 int rc;
351 if (option_no_db)
352 return;
354 rc = sqlite3_open_v2("smatch_db.sqlite", &db, SQLITE_OPEN_READONLY, NULL);
355 if (rc != SQLITE_OK) {
356 option_no_db = 1;
357 return;
359 return;
360 #else
361 option_no_db = 1;
362 return;
363 #endif
366 void register_definition_db_callbacks(int id)
368 if (option_info) {
369 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
370 add_hook(&match_call_hack, FUNCTION_CALL_HOOK);
371 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
372 add_hook(&global_variable, BASE_HOOK);
373 add_hook(&global_variable, DECLARATION_HOOK);
376 if (option_no_db)
377 return;
379 add_hook(&match_data_from_db, FUNC_DEF_HOOK);