Print this page
12724 update smatch to 0.6.1-rc1-il-5
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_fresh_alloc.c
+++ new/usr/src/tools/smatch/src/smatch_fresh_alloc.c
1 1 /*
2 2 * Copyright (C) 2019 Oracle.
3 3 *
4 4 * This program is free software; you can redistribute it and/or
5 5 * modify it under the terms of the GNU General Public License
6 6 * as published by the Free Software Foundation; either version 2
7 7 * of the License, or (at your option) any later version.
8 8 *
9 9 * This program is distributed in the hope that it will be useful,
10 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 * GNU General Public License for more details.
13 13 *
14 14 * You should have received a copy of the GNU General Public License
15 15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 */
17 17
18 18 /*
19 19 * There are a bunch of allocation functions where we allocate some memory,
20 20 * set up some struct members and then return the allocated memory. One
21 21 * nice thing about this is that we just one pointer to the allocated memory
22 22 * so what we can do is we can generate a mtag alias for it in the caller.
23 23 */
24 24
25 25 #include "smatch.h"
26 +#include "smatch_extra.h"
26 27 #include "smatch_slist.h"
27 28
28 29 static int my_id;
29 30
30 31 STATE(fresh);
31 32
32 33 struct alloc_info *alloc_funcs;
33 34
34 35 struct alloc_info kernel_allocation_funcs[] = {
35 36 {"kmalloc", 0},
36 37 {"kmalloc_node", 0},
37 38 {"kzalloc", 0},
38 39 {"kzalloc_node", 0},
39 40 {"vmalloc", 0},
40 41 {"__vmalloc", 0},
41 42 {"kvmalloc", 0},
42 43 {"kcalloc", 0, 1},
43 44 {"kmalloc_array", 0, 1},
44 45 {"sock_kmalloc", 1},
45 46 {"kmemdup", 1},
46 47 {"kmemdup_user", 1},
47 48 {"dma_alloc_attrs", 1},
48 49 {"pci_alloc_consistent", 1},
49 50 {"pci_alloc_coherent", 1},
50 51 {"devm_kmalloc", 1},
51 52 {"devm_kzalloc", 1},
52 53 {"krealloc", 1},
53 54 {"__alloc_bootmem", 0},
54 55 {"alloc_bootmem", 0},
55 56 {"dma_alloc_contiguous", 1},
56 57 {"dma_alloc_coherent", 1},
57 58 {},
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
58 59 };
59 60
60 61 struct alloc_info general_allocation_funcs[] = {
61 62 {"malloc", 0},
62 63 {"calloc", 0, 1},
63 64 {"memdup", 1},
64 65 {"realloc", 1},
65 66 {},
66 67 };
67 68
69 +static void pre_merge_hook(struct sm_state *cur, struct sm_state *other)
70 +{
71 + struct smatch_state *state;
72 + sval_t sval;
73 +
74 + state = get_state(SMATCH_EXTRA, cur->name, cur->sym);
75 + if (estate_get_single_value(state, &sval) && sval.value == 0)
76 + set_state(my_id, cur->name, cur->sym, &undefined);
77 +}
78 +
68 79 static int fresh_callback(void *fresh, int argc, char **argv, char **azColName)
69 80 {
70 81 *(int *)fresh = 1;
71 82 return 0;
72 83 }
73 84
74 85 static int fresh_from_db(struct expression *call)
75 86 {
76 87 int fresh = 0;
77 88
78 89 /* for function pointers assume everything is used */
79 90 if (call->fn->type != EXPR_SYMBOL)
80 91 return 0;
81 92
82 93 run_sql(&fresh_callback, &fresh,
83 94 "select * from return_states where %s and type = %d and parameter = -1 and key = '$' limit 1;",
84 95 get_static_filter(call->fn->symbol), FRESH_ALLOC);
85 96 return fresh;
86 97 }
87 98
88 99 bool is_fresh_alloc_var_sym(const char *var, struct symbol *sym)
89 100 {
90 101 return get_state(my_id, var, sym) == &fresh;
91 102 }
92 103
93 104 bool is_fresh_alloc(struct expression *expr)
94 105 {
95 106 sval_t sval;
96 107 int i;
97 108
98 109 if (!expr)
99 110 return false;
100 111
101 112 if (get_implied_value_fast(expr, &sval) && sval.value == 0)
102 113 return false;
103 114
104 115 if (get_state_expr(my_id, expr) == &fresh)
105 116 return true;
106 117
107 118 if (expr->type != EXPR_CALL)
108 119 return false;
109 120 if (fresh_from_db(expr))
110 121 return true;
111 122 i = -1;
112 123 while (alloc_funcs[++i].fn) {
113 124 if (sym_name_is(kernel_allocation_funcs[i].fn, expr->fn))
114 125 return true;
115 126 }
116 127 return false;
117 128 }
118 129
119 130 static void record_alloc_func(int return_id, char *return_ranges, struct expression *expr)
120 131 {
121 132 if (!is_fresh_alloc(expr))
122 133 return;
123 134 sql_insert_return_states(return_id, return_ranges, FRESH_ALLOC, -1, "$", "");
124 135 }
125 136
126 137 static void set_unfresh(struct expression *expr)
127 138 {
128 139 struct sm_state *sm;
129 140
130 141 sm = get_sm_state_expr(my_id, expr);
131 142 if (!sm)
132 143 return;
133 144 if (!slist_has_state(sm->possible, &fresh))
134 145 return;
135 146 // TODO call unfresh hooks
136 147 set_state_expr(my_id, expr, &undefined);
137 148 }
138 149
139 150 static void match_assign(struct expression *expr)
140 151 {
141 152 set_unfresh(expr->right);
142 153 }
↓ open down ↓ |
65 lines elided |
↑ open up ↑ |
143 154
144 155 static void match_call(struct expression *expr)
145 156 {
146 157 struct expression *arg;
147 158
148 159 FOR_EACH_PTR(expr->args, arg) {
149 160 set_unfresh(arg);
150 161 } END_FOR_EACH_PTR(arg);
151 162 }
152 163
164 +static struct expression *handled;
153 165 static void set_fresh(struct expression *expr)
154 166 {
167 + struct range_list *rl;
168 +
155 169 expr = strip_expr(expr);
156 170 if (expr->type != EXPR_SYMBOL)
157 171 return;
172 + if (expr == handled)
173 + return;
174 +
175 + get_absolute_rl(expr, &rl);
176 + rl = rl_intersection(rl, valid_ptr_rl);
177 + if (!rl)
178 + return;
158 179 set_state_expr(my_id, expr, &fresh);
180 + handled = expr;
159 181 }
160 182
161 183 static void returns_fresh_alloc(struct expression *expr, int param, char *key, char *value)
162 184 {
163 185 if (param != -1 || !key || strcmp(key, "$") != 0)
164 186 return;
165 187 if (expr->type != EXPR_ASSIGNMENT)
166 188 return;
167 189
168 190 set_fresh(expr->left);
169 191 }
170 192
171 193 static void match_alloc(const char *fn, struct expression *expr, void *_size_arg)
172 194 {
173 195 set_fresh(expr->left);
174 196 }
175 197
176 198 void register_fresh_alloc(int id)
177 199 {
178 200 int i;
179 201
180 202 my_id = id;
181 203
182 204 if (option_project == PROJ_KERNEL)
183 205 alloc_funcs = kernel_allocation_funcs;
184 206 else
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
185 207 alloc_funcs = general_allocation_funcs;
186 208
187 209 i = -1;
188 210 while (alloc_funcs[++i].fn)
189 211 add_function_assign_hook(alloc_funcs[i].fn, &match_alloc, 0);
190 212
191 213 add_split_return_callback(&record_alloc_func);
192 214 select_return_states_hook(FRESH_ALLOC, &returns_fresh_alloc);
193 215 add_hook(&match_assign, ASSIGNMENT_HOOK);
194 216 add_hook(&match_call, FUNCTION_CALL_HOOK);
217 +
218 + add_pre_merge_hook(my_id, &pre_merge_hook);
195 219 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX