33 *
34 * Another place where we would maybe name the pointer is when they are passed
35 * to the probe(). Because that's an important pointer, since there is one
36 * per driver (sort of).
37 *
38 * My vision is that you could take a pointer and trace it back to a global. So
39 * I'm going to track that pointer_tag - 28 bytes takes you to another pointer
40 * tag. You could follow that one back and so on. Also when we pass a pointer
41 * to a function that would be recorded as sort of a link or path or something.
42 *
43 */
44
45 #include "smatch.h"
46 #include "smatch_slist.h"
47 #include "smatch_extra.h"
48
49 #include <openssl/md5.h>
50
51 static int my_id;
52
53 static mtag_t str_to_tag(const char *str)
54 {
55 unsigned char c[MD5_DIGEST_LENGTH];
56 unsigned long long *tag = (unsigned long long *)&c;
57 MD5_CTX mdContext;
58 int len;
59
60 len = strlen(str);
61 MD5_Init(&mdContext);
62 MD5_Update(&mdContext, str, len);
63 MD5_Final(c, &mdContext);
64
65 *tag &= ~MTAG_ALIAS_BIT;
66 *tag &= ~MTAG_OFFSET_MASK;
67
68 return *tag;
69 }
70
71 const struct {
72 const char *name;
73 int size_arg;
115
116 if (!expr || expr->type != EXPR_ASSIGNMENT || expr->op != '=')
117 return state;
118
119 if (!estate_rl(state) || strcmp(state->name, "0,4096-ptr_max") != 0)
120 return state;
121
122 left = strip_expr(expr->left);
123 right = strip_expr(expr->right);
124
125 if (!is_mtag_call(right))
126 return state;
127
128 left_name = expr_to_str_sym(left, &left_sym);
129 if (!left_name || !left_sym)
130 return state;
131 right_name = expr_to_str(right);
132
133 snprintf(buf, sizeof(buf), "%s %s %s %s", get_filename(), get_function(),
134 left_name, right_name);
135 tag = str_to_tag(buf);
136 tag_sval.type = estate_type(state);
137 tag_sval.uvalue = tag;
138
139 rl = rl_filter(estate_rl(state), valid_ptr_rl);
140 rl = clone_rl(rl);
141 add_range(&rl, tag_sval, tag_sval);
142
143 sql_insert_mtag_about(tag, left_name, buf);
144
145 free_string(left_name);
146 free_string(right_name);
147
148 return alloc_estate_rl(rl);
149 }
150
151 int get_string_mtag(struct expression *expr, mtag_t *tag)
152 {
153 mtag_t xor;
154
155 if (expr->type != EXPR_STRING || !expr->string)
156 return 0;
157
158 /* I was worried about collisions so I added a xor */
159 xor = str_to_tag("__smatch string");
160 *tag = str_to_tag(expr->string->data);
161 *tag = *tag ^ xor;
162
163 return 1;
164 }
165
166 int get_toplevel_mtag(struct symbol *sym, mtag_t *tag)
167 {
168 char buf[256];
169
170 if (!sym)
171 return 0;
172
173 if (!sym->ident ||
174 !(sym->ctype.modifiers & MOD_TOPLEVEL))
175 return 0;
176
177 snprintf(buf, sizeof(buf), "%s %s",
178 (sym->ctype.modifiers & MOD_STATIC) ? get_filename() : "extern",
179 sym->ident->name);
180 *tag = str_to_tag(buf);
181 return 1;
182 }
183
184 bool get_symbol_mtag(struct symbol *sym, mtag_t *tag)
185 {
186 char buf[256];
187
188 if (!sym || !sym->ident)
189 return false;
190
191 if (get_toplevel_mtag(sym, tag))
192 return true;
193
194 if (get_param_num_from_sym(sym) >= 0)
195 return false;
196
197 snprintf(buf, sizeof(buf), "%s %s %s",
198 get_filename(), get_function(), sym->ident->name);
199 *tag = str_to_tag(buf);
200 return true;
201 }
202
203 static void global_variable(struct symbol *sym)
204 {
205 mtag_t tag;
206
207 if (!get_toplevel_mtag(sym, &tag))
208 return;
209
210 sql_insert_mtag_about(tag,
211 sym->ident->name,
212 (sym->ctype.modifiers & MOD_STATIC) ? get_filename() : "extern");
213 }
214
215 static int get_array_mtag_offset(struct expression *expr, mtag_t *tag, int *offset)
216 {
217 struct expression *array, *offset_expr;
218 struct symbol *type;
219 sval_t sval;
241 *offset = start_offset + sval.value * type_bytes(type);
242
243 return 1;
244 }
245
246 struct range_list *swap_mtag_seed(struct expression *expr, struct range_list *rl)
247 {
248 char buf[256];
249 char *name;
250 sval_t sval;
251 mtag_t tag;
252
253 if (!rl_to_sval(rl, &sval))
254 return rl;
255 if (sval.type->type != SYM_PTR || sval.uvalue != MTAG_SEED)
256 return rl;
257
258 name = expr_to_str(expr);
259 snprintf(buf, sizeof(buf), "%s %s %s", get_filename(), get_function(), name);
260 free_string(name);
261 tag = str_to_tag(buf);
262 sval.value = tag;
263 return alloc_rl(sval, sval);
264 }
265
266 int create_mtag_alias(mtag_t tag, struct expression *expr, mtag_t *new)
267 {
268 char buf[256];
269 int lines_from_start;
270 char *str;
271
272 /*
273 * We need the alias to be unique. It's not totally required that it
274 * be the same from one DB build to then next, but it makes debugging
275 * a bit simpler.
276 *
277 */
278
279 if (!cur_func_sym)
280 return 0;
281
282 lines_from_start = expr->pos.line - cur_func_sym->pos.line;
283 str = expr_to_str(expr);
284 snprintf(buf, sizeof(buf), "%lld %d %s", tag, lines_from_start, str);
285 free_string(str);
286
287 *new = str_to_tag(buf);
288 sql_insert_mtag_alias(tag, *new);
289
290 return 1;
291 }
292
293 static int get_implied_mtag_offset(struct expression *expr, mtag_t *tag, int *offset)
294 {
295 struct smatch_state *state;
296 struct symbol *type;
297 sval_t sval;
298
299 type = get_type(expr);
300 if (!type_is_ptr(type))
301 return 0;
302 state = get_extra_state(expr);
303 if (!state || !estate_get_single_value(state, &sval) || sval.value == 0)
304 return 0;
305
306 *tag = sval.uvalue & ~MTAG_OFFSET_MASK;
307 *offset = sval.uvalue & MTAG_OFFSET_MASK;
|
33 *
34 * Another place where we would maybe name the pointer is when they are passed
35 * to the probe(). Because that's an important pointer, since there is one
36 * per driver (sort of).
37 *
38 * My vision is that you could take a pointer and trace it back to a global. So
39 * I'm going to track that pointer_tag - 28 bytes takes you to another pointer
40 * tag. You could follow that one back and so on. Also when we pass a pointer
41 * to a function that would be recorded as sort of a link or path or something.
42 *
43 */
44
45 #include "smatch.h"
46 #include "smatch_slist.h"
47 #include "smatch_extra.h"
48
49 #include <openssl/md5.h>
50
51 static int my_id;
52
53 mtag_t str_to_mtag(const char *str)
54 {
55 unsigned char c[MD5_DIGEST_LENGTH];
56 unsigned long long *tag = (unsigned long long *)&c;
57 MD5_CTX mdContext;
58 int len;
59
60 len = strlen(str);
61 MD5_Init(&mdContext);
62 MD5_Update(&mdContext, str, len);
63 MD5_Final(c, &mdContext);
64
65 *tag &= ~MTAG_ALIAS_BIT;
66 *tag &= ~MTAG_OFFSET_MASK;
67
68 return *tag;
69 }
70
71 const struct {
72 const char *name;
73 int size_arg;
115
116 if (!expr || expr->type != EXPR_ASSIGNMENT || expr->op != '=')
117 return state;
118
119 if (!estate_rl(state) || strcmp(state->name, "0,4096-ptr_max") != 0)
120 return state;
121
122 left = strip_expr(expr->left);
123 right = strip_expr(expr->right);
124
125 if (!is_mtag_call(right))
126 return state;
127
128 left_name = expr_to_str_sym(left, &left_sym);
129 if (!left_name || !left_sym)
130 return state;
131 right_name = expr_to_str(right);
132
133 snprintf(buf, sizeof(buf), "%s %s %s %s", get_filename(), get_function(),
134 left_name, right_name);
135 tag = str_to_mtag(buf);
136 tag_sval.type = estate_type(state);
137 tag_sval.uvalue = tag;
138
139 rl = rl_filter(estate_rl(state), valid_ptr_rl);
140 rl = clone_rl(rl);
141 add_range(&rl, tag_sval, tag_sval);
142
143 sql_insert_mtag_about(tag, left_name, buf);
144
145 free_string(left_name);
146 free_string(right_name);
147
148 return alloc_estate_rl(rl);
149 }
150
151 int get_string_mtag(struct expression *expr, mtag_t *tag)
152 {
153 mtag_t xor;
154
155 if (expr->type != EXPR_STRING || !expr->string)
156 return 0;
157
158 /* I was worried about collisions so I added a xor */
159 xor = str_to_mtag("__smatch string");
160 *tag = str_to_mtag(expr->string->data);
161 *tag = *tag ^ xor;
162
163 return 1;
164 }
165
166 int get_toplevel_mtag(struct symbol *sym, mtag_t *tag)
167 {
168 char buf[256];
169
170 if (!sym)
171 return 0;
172
173 if (!sym->ident ||
174 !(sym->ctype.modifiers & MOD_TOPLEVEL))
175 return 0;
176
177 snprintf(buf, sizeof(buf), "%s %s",
178 (sym->ctype.modifiers & MOD_STATIC) ? get_filename() : "extern",
179 sym->ident->name);
180 *tag = str_to_mtag(buf);
181 return 1;
182 }
183
184 bool get_symbol_mtag(struct symbol *sym, mtag_t *tag)
185 {
186 char buf[256];
187
188 if (!sym || !sym->ident)
189 return false;
190
191 if (get_toplevel_mtag(sym, tag))
192 return true;
193
194 if (get_param_num_from_sym(sym) >= 0)
195 return false;
196
197 snprintf(buf, sizeof(buf), "%s %s %s",
198 get_filename(), get_function(), sym->ident->name);
199 *tag = str_to_mtag(buf);
200 return true;
201 }
202
203 static void global_variable(struct symbol *sym)
204 {
205 mtag_t tag;
206
207 if (!get_toplevel_mtag(sym, &tag))
208 return;
209
210 sql_insert_mtag_about(tag,
211 sym->ident->name,
212 (sym->ctype.modifiers & MOD_STATIC) ? get_filename() : "extern");
213 }
214
215 static int get_array_mtag_offset(struct expression *expr, mtag_t *tag, int *offset)
216 {
217 struct expression *array, *offset_expr;
218 struct symbol *type;
219 sval_t sval;
241 *offset = start_offset + sval.value * type_bytes(type);
242
243 return 1;
244 }
245
246 struct range_list *swap_mtag_seed(struct expression *expr, struct range_list *rl)
247 {
248 char buf[256];
249 char *name;
250 sval_t sval;
251 mtag_t tag;
252
253 if (!rl_to_sval(rl, &sval))
254 return rl;
255 if (sval.type->type != SYM_PTR || sval.uvalue != MTAG_SEED)
256 return rl;
257
258 name = expr_to_str(expr);
259 snprintf(buf, sizeof(buf), "%s %s %s", get_filename(), get_function(), name);
260 free_string(name);
261 tag = str_to_mtag(buf);
262 sval.value = tag;
263 return alloc_rl(sval, sval);
264 }
265
266 int create_mtag_alias(mtag_t tag, struct expression *expr, mtag_t *new)
267 {
268 char buf[256];
269 int lines_from_start;
270 char *str;
271
272 /*
273 * We need the alias to be unique. It's not totally required that it
274 * be the same from one DB build to then next, but it makes debugging
275 * a bit simpler.
276 *
277 */
278
279 if (!cur_func_sym)
280 return 0;
281
282 lines_from_start = expr->pos.line - cur_func_sym->pos.line;
283 str = expr_to_str(expr);
284 snprintf(buf, sizeof(buf), "%lld %d %s", tag, lines_from_start, str);
285 free_string(str);
286
287 *new = str_to_mtag(buf);
288 sql_insert_mtag_alias(tag, *new);
289
290 return 1;
291 }
292
293 static int get_implied_mtag_offset(struct expression *expr, mtag_t *tag, int *offset)
294 {
295 struct smatch_state *state;
296 struct symbol *type;
297 sval_t sval;
298
299 type = get_type(expr);
300 if (!type_is_ptr(type))
301 return 0;
302 state = get_extra_state(expr);
303 if (!state || !estate_get_single_value(state, &sval) || sval.value == 0)
304 return 0;
305
306 *tag = sval.uvalue & ~MTAG_OFFSET_MASK;
307 *offset = sval.uvalue & MTAG_OFFSET_MASK;
|