2 * sparse/smatch_param_cleared.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
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.
21 #include "smatch_slist.h"
22 #include "smatch_extra.h"
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
)
38 arg
= get_argument_from_call_expr(expr
->args
, param
);
39 arg
= strip_expr(arg
);
42 if (arg
->type
!= EXPR_SYMBOL
)
44 if (get_param_num_from_sym(arg
->symbol
) < 0)
47 if (strcmp(value
, "0") == 0)
48 set_state_expr(my_id
, arg
, &zeroed
);
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
;
69 my_slist
= get_all_states(my_id
);
71 FOR_EACH_PTR(my_slist
, sm
) {
72 param
= get_param_num_from_sym(sm
->sym
);
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)
95 if (option_project
== PROJ_NONE
)
98 snprintf(name
, 256, "%s.clears_argument", option_project_str
);
100 token
= get_tokens_file(name
);
103 if (token_type(token
) != TOKEN_STREAMBEGIN
)
106 while (token_type(token
) != TOKEN_STREAMEND
) {
107 if (token_type(token
) != TOKEN_IDENT
)
109 function
= show_ident(token
->ident
);
111 if (token_type(token
) != TOKEN_NUMBER
)
113 param
= atoi(token
->number
);
114 add_function_hook(function
, &match_memcpy
, INT_PTR(param
));
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
;
126 inout
= get_argument_from_call_expr(expr
->args
, 3);
128 if (get_value(inout
, &sval
) && !(sval
.uvalue
& USB_DIR_IN
))
131 db_param_cleared(expr
, 6, (char *)"$$", (char *)"");
134 void register_param_cleared(int 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
);