function_hooks: fix how database comparisons are done
[smatch.git] / smatch_param_cleared.c
blob69bc6bb4bb6eb2f1fba80e2114515ea4a7355cb6
1 /*
2 * Copyright (C) 2012 Oracle.
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 works together with smatch_clear_buffer.c. This one is only for
20 * tracking the information and smatch_clear_buffer.c changes SMATCH_EXTRA.
22 * This tracks functions like memset() which clear out a chunk of memory.
23 * It fills in a gap that smatch_param_set.c can't handle. It only handles
24 * void pointers because smatch_param_set.c should handle the rest.
27 #include "scope.h"
28 #include "smatch.h"
29 #include "smatch_slist.h"
30 #include "smatch_extra.h"
32 static int my_id;
34 STATE(cleared);
35 STATE(zeroed);
37 static void db_param_cleared(struct expression *expr, int param, char *key, char *value)
39 struct expression *arg;
41 while (expr->type == EXPR_ASSIGNMENT)
42 expr = strip_expr(expr->right);
43 if (expr->type != EXPR_CALL)
44 return;
46 arg = get_argument_from_call_expr(expr->args, param);
47 arg = strip_expr(arg);
48 if (!arg)
49 return;
50 if (arg->type != EXPR_SYMBOL)
51 return;
52 if (get_param_num_from_sym(arg->symbol) < 0)
53 return;
55 if (strcmp(value, "0") == 0)
56 set_state_expr(my_id, arg, &zeroed);
57 else
58 set_state_expr(my_id, arg, &cleared);
61 static void match_memset(const char *fn, struct expression *expr, void *arg)
63 db_param_cleared(expr, PTR_INT(arg), (char *)"$$", (char *)"0");
66 static void match_memcpy(const char *fn, struct expression *expr, void *arg)
68 db_param_cleared(expr, PTR_INT(arg), (char *)"$$", (char *)"");
71 static void print_return_value_param(int return_id, char *return_ranges, struct expression *expr)
73 struct stree *stree;
74 struct sm_state *sm;
75 int param;
77 stree = __get_cur_stree();
79 FOR_EACH_MY_SM(my_id, stree, sm) {
80 param = get_param_num_from_sym(sm->sym);
81 if (param < 0)
82 continue;
84 if (sm->state == &zeroed) {
85 sql_insert_return_states(return_id, return_ranges,
86 PARAM_CLEARED, param, "$$", "0");
89 if (sm->state == &cleared) {
90 sql_insert_return_states(return_id, return_ranges,
91 PARAM_CLEARED, param, "$$", "");
93 } END_FOR_EACH_SM(sm);
96 static void register_clears_param(void)
98 struct token *token;
99 char name[256];
100 const char *function;
101 int param;
103 if (option_project == PROJ_NONE)
104 return;
106 snprintf(name, 256, "%s.clears_argument", option_project_str);
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 function = show_ident(token->ident);
118 token = token->next;
119 if (token_type(token) != TOKEN_NUMBER)
120 return;
121 param = atoi(token->number);
122 add_function_hook(function, &match_memcpy, INT_PTR(param));
123 token = token->next;
125 clear_token_alloc();
128 #define USB_DIR_IN 0x80
129 static void match_usb_control_msg(const char *fn, struct expression *expr, void *_size_arg)
131 struct expression *inout;
132 sval_t sval;
134 inout = get_argument_from_call_expr(expr->args, 3);
136 if (get_value(inout, &sval) && !(sval.uvalue & USB_DIR_IN))
137 return;
139 db_param_cleared(expr, 6, (char *)"$$", (char *)"");
142 static void match_assign(struct expression *expr)
144 struct symbol *type;
146 type = get_type(expr->left);
147 if (!type || type->type != SYM_STRUCT)
148 return;
149 set_state_expr(my_id, expr->left, &cleared);
152 void register_param_cleared(int id)
154 my_id = id;
156 add_function_hook("memset", &match_memset, INT_PTR(0));
157 add_function_hook("__memzero", &match_memset, INT_PTR(0));
158 add_function_hook("memzero", &match_memset, INT_PTR(0));
160 add_function_hook("memcpy", &match_memcpy, INT_PTR(0));
161 add_function_hook("memmove", &match_memcpy, INT_PTR(0));
162 add_function_hook("strcpy", &match_memcpy, INT_PTR(0));
163 add_function_hook("strncpy", &match_memcpy, INT_PTR(0));
164 add_function_hook("sprintf", &match_memcpy, INT_PTR(0));
165 add_function_hook("snprintf", &match_memcpy, INT_PTR(0));
167 add_hook(&match_assign, ASSIGNMENT_HOOK);
169 register_clears_param();
171 select_return_states_hook(PARAM_CLEARED, &db_param_cleared);
172 add_split_return_callback(&print_return_value_param);
174 if (option_project == PROJ_KERNEL) {
175 add_function_hook("usb_control_msg", &match_usb_control_msg, NULL);