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.
29 #include "smatch_slist.h"
30 #include "smatch_extra.h"
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
)
46 arg
= get_argument_from_call_expr(expr
->args
, param
);
47 arg
= strip_expr(arg
);
50 if (arg
->type
!= EXPR_SYMBOL
)
52 if (get_param_num_from_sym(arg
->symbol
) < 0)
55 if (strcmp(value
, "0") == 0)
56 set_state_expr(my_id
, arg
, &zeroed
);
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
)
77 stree
= __get_cur_stree();
79 FOR_EACH_MY_SM(my_id
, stree
, sm
) {
80 param
= get_param_num_from_sym(sm
->sym
);
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)
100 const char *function
;
103 if (option_project
== PROJ_NONE
)
106 snprintf(name
, 256, "%s.clears_argument", option_project_str
);
108 token
= get_tokens_file(name
);
111 if (token_type(token
) != TOKEN_STREAMBEGIN
)
114 while (token_type(token
) != TOKEN_STREAMEND
) {
115 if (token_type(token
) != TOKEN_IDENT
)
117 function
= show_ident(token
->ident
);
119 if (token_type(token
) != TOKEN_NUMBER
)
121 param
= atoi(token
->number
);
122 add_function_hook(function
, &match_memcpy
, INT_PTR(param
));
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
;
134 inout
= get_argument_from_call_expr(expr
->args
, 3);
136 if (get_value(inout
, &sval
) && !(sval
.uvalue
& USB_DIR_IN
))
139 db_param_cleared(expr
, 6, (char *)"$$", (char *)"");
142 void register_param_cleared(int id
)
149 add_function_hook("memset", &match_memset
, INT_PTR(0));
151 add_function_hook("memcpy", &match_memcpy
, INT_PTR(0));
152 add_function_hook("memmove", &match_memcpy
, INT_PTR(0));
153 add_function_hook("strcpy", &match_memcpy
, INT_PTR(0));
154 add_function_hook("strncpy", &match_memcpy
, INT_PTR(0));
155 add_function_hook("sprintf", &match_memcpy
, INT_PTR(0));
156 add_function_hook("snprintf", &match_memcpy
, INT_PTR(0));
158 register_clears_param();
160 select_return_states_hook(PARAM_CLEARED
, &db_param_cleared
);
161 add_split_return_callback(&print_return_value_param
);
163 if (option_project
== PROJ_KERNEL
) {
164 add_function_hook("usb_control_msg", &match_usb_control_msg
, NULL
);