free: add kmem_cache_free() as a freeing function
[smatch.git] / smatch_param_cleared.c
blob9124c8dc93c149abc59c39e94a508ae766695c41
1 /*
2 * sparse/smatch_param_cleared.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
8 */
11 * This works together with smatch_clear_buffer.c. This one is only for
12 * tracking the information and smatch_clear_buffer.c changes SMATCH_EXTRA.
14 * This tracks functions like memset() which clear out a chunk of memory.
15 * It fills in a gap that smatch_param_set.c can't handle. It only handles
16 * void pointers because smatch_param_set.c should handle the rest.
19 #include "scope.h"
20 #include "smatch.h"
21 #include "smatch_slist.h"
22 #include "smatch_extra.h"
24 static int my_id;
26 STATE(cleared);
27 STATE(zeroed);
29 static void db_param_cleared(struct expression *expr, int param, char *key, char *value)
31 struct expression *arg;
33 while (expr->type == EXPR_ASSIGNMENT)
34 expr = strip_expr(expr->right);
35 if (expr->type != EXPR_CALL)
36 return;
38 arg = get_argument_from_call_expr(expr->args, param);
39 arg = strip_expr(arg);
40 if (!arg)
41 return;
42 if (arg->type != EXPR_SYMBOL)
43 return;
44 if (get_param_num_from_sym(arg->symbol) < 0)
45 return;
47 if (strcmp(value, "0") == 0)
48 set_state_expr(my_id, arg, &zeroed);
49 else
50 set_state_expr(my_id, arg, &cleared);
53 static void match_memset(const char *fn, struct expression *expr, void *arg)
55 db_param_cleared(expr, PTR_INT(arg), (char *)"$$", (char *)"0");
58 static void match_memcpy(const char *fn, struct expression *expr, void *arg)
60 db_param_cleared(expr, PTR_INT(arg), (char *)"$$", (char *)"");
63 static void print_return_value_param(int return_id, char *return_ranges, struct expression *expr)
65 struct state_list *my_slist;
66 struct sm_state *sm;
67 int param;
69 my_slist = get_all_states(my_id);
71 FOR_EACH_PTR(my_slist, sm) {
72 param = get_param_num_from_sym(sm->sym);
73 if (param < 0)
74 continue;
76 if (sm->state == &zeroed) {
77 sql_insert_return_states(return_id, return_ranges,
78 PARAM_CLEARED, param, "$$", "0");
81 if (sm->state == &cleared) {
82 sql_insert_return_states(return_id, return_ranges,
83 PARAM_CLEARED, param, "$$", "");
85 } END_FOR_EACH_PTR(sm);
88 static void register_clears_param(void)
90 struct token *token;
91 char name[256];
92 const char *function;
93 int param;
95 if (option_project == PROJ_NONE)
96 return;
98 snprintf(name, 256, "%s.clears_argument", option_project_str);
100 token = get_tokens_file(name);
101 if (!token)
102 return;
103 if (token_type(token) != TOKEN_STREAMBEGIN)
104 return;
105 token = token->next;
106 while (token_type(token) != TOKEN_STREAMEND) {
107 if (token_type(token) != TOKEN_IDENT)
108 return;
109 function = show_ident(token->ident);
110 token = token->next;
111 if (token_type(token) != TOKEN_NUMBER)
112 return;
113 param = atoi(token->number);
114 add_function_hook(function, &match_memcpy, INT_PTR(param));
115 token = token->next;
117 clear_token_alloc();
120 #define USB_DIR_IN 0x80
121 static void match_usb_control_msg(const char *fn, struct expression *expr, void *_size_arg)
123 struct expression *inout;
124 sval_t sval;
126 inout = get_argument_from_call_expr(expr->args, 3);
128 if (get_value(inout, &sval) && !(sval.uvalue & USB_DIR_IN))
129 return;
131 db_param_cleared(expr, 6, (char *)"$$", (char *)"");
134 void register_param_cleared(int id)
136 if (!option_info)
137 return;
139 my_id = id;
141 add_function_hook("memset", &match_memset, INT_PTR(0));
143 add_function_hook("memcpy", &match_memcpy, INT_PTR(0));
144 add_function_hook("memmove", &match_memcpy, INT_PTR(0));
145 add_function_hook("strcpy", &match_memcpy, INT_PTR(0));
146 add_function_hook("strncpy", &match_memcpy, INT_PTR(0));
147 add_function_hook("sprintf", &match_memcpy, INT_PTR(0));
148 add_function_hook("snprintf", &match_memcpy, INT_PTR(0));
150 register_clears_param();
152 select_return_states_hook(PARAM_CLEARED, &db_param_cleared);
153 add_split_return_callback(&print_return_value_param);
155 if (option_project == PROJ_KERNEL) {
156 add_function_hook("usb_control_msg", &match_usb_control_msg, NULL);