1
2 #include <magic_analysis.h>
3
4 PUBLIC char magic_ne_str[] = "NULL_TYPE";
5 PUBLIC char magic_enf_str[] = "UNKNOWN_TYPE";
6 PUBLIC char magic_bo_str[] = "BAD_TYPE";
7 PUBLIC char magic_be_str[] = "BAD_ENTRY_TYPE";
8 PUBLIC char magic_bv_str[] = "BAD_VALUE_TYPE";
9 PUBLIC char magic_vf_str[] = "VALUE_FOUND_TYPE";
10 PUBLIC const struct _magic_type magic_NULL_ENTRY_TYPE = MAGIC_TYPE_SPECIAL_INIT(magic_ne_str);
11 PUBLIC const struct _magic_type magic_ENTRY_NOT_FOUND_TYPE = MAGIC_TYPE_SPECIAL_INIT(magic_enf_str);
12 PUBLIC const struct _magic_type magic_BAD_OFFSET_TYPE = MAGIC_TYPE_SPECIAL_INIT(magic_bo_str);
13 PUBLIC const struct _magic_type magic_BAD_ENTRY_TYPE = MAGIC_TYPE_SPECIAL_INIT(magic_be_str);
14 PUBLIC const struct _magic_type magic_BAD_VALUE_TYPE = MAGIC_TYPE_SPECIAL_INIT(magic_bv_str);
15 PUBLIC const struct _magic_type magic_VALUE_FOUND = MAGIC_TYPE_SPECIAL_INIT(magic_vf_str);
16
17 PRIVATE magic_cb_sentries_analyze_pre_t magic_sentries_analyze_pre_cb = NULL;
18
19 /*===========================================================================*
20 * magic_setcb_sentries_analyze_pre *
21 *===========================================================================*/
magic_setcb_sentries_analyze_pre(magic_cb_sentries_analyze_pre_t cb)22 PUBLIC void magic_setcb_sentries_analyze_pre(magic_cb_sentries_analyze_pre_t cb)
23 {
24 magic_sentries_analyze_pre_cb = cb;
25 }
26
27 /*===========================================================================*
28 * magic_sentry_print_ptr_types *
29 *===========================================================================*/
magic_sentry_print_ptr_types(struct _magic_sentry * entry)30 PUBLIC int magic_sentry_print_ptr_types(struct _magic_sentry* entry)
31 {
32 int ret, ptrs_found = 0;
33 void* args_array[2];
34 args_array[0] = entry;
35 args_array[1] = &ptrs_found;
36 ret = magic_type_walk_root_all(entry->type, magic_type_examine_ptr_cb, args_array);
37 assert(ret >= 0);
38 return ptrs_found;
39 }
40
41 /*===========================================================================*
42 * magic_sentry_extract_ptrs *
43 *===========================================================================*/
magic_sentry_extract_ptrs(struct _magic_sentry * entry,void **** ptr_map,const struct _magic_type *** ptr_type_map,int * ptr_num)44 PUBLIC int magic_sentry_extract_ptrs(struct _magic_sentry* entry, void ****ptr_map, const struct _magic_type ***ptr_type_map, int *ptr_num)
45 {
46 int from_wrapper = MAGIC_MEM_WRAPPER_IS_ACTIVE();
47 int ret = magic_type_count_ptrs(entry->type, ptr_num);
48 assert(ret == 0);
49 if(*ptr_num == 0) {
50 *ptr_map = NULL;
51 *ptr_type_map = NULL;
52 }
53 else {
54 void* args_array[4];
55 int ptr_num2 = 0;
56 if(!from_wrapper) {
57 MAGIC_MEM_WRAPPER_BEGIN();
58 }
59 *ptr_map = (void ***) malloc((*ptr_num)*sizeof(void **));
60 *ptr_type_map = (const struct _magic_type **) malloc((*ptr_num)*sizeof(const struct _magic_type *));
61 if(!from_wrapper) {
62 MAGIC_MEM_WRAPPER_END();
63 }
64 args_array[0] = entry;
65 args_array[1] = *ptr_map;
66 args_array[2] = *ptr_type_map;
67 args_array[3] = &ptr_num2;
68 ret = magic_type_walk_root_all(entry->type, magic_type_extract_ptr_cb, args_array);
69 assert(ret >= 0);
70 assert(*ptr_num == ptr_num2);
71 }
72 return 0;
73 }
74
75 /*===========================================================================*
76 * magic_sentry_analyze *
77 *===========================================================================*/
magic_sentry_analyze(struct _magic_sentry * sentry,int flags,const magic_sentry_analyze_cb_t cb,void * cb_args,_magic_sel_stats_t * sentry_stats)78 PUBLIC int magic_sentry_analyze(struct _magic_sentry* sentry, int flags,
79 const magic_sentry_analyze_cb_t cb, void* cb_args,
80 _magic_sel_stats_t *sentry_stats)
81 {
82 int ret;
83 int selement_num = 0, sel_analyzed_num = 0;
84 void* args_array[7];
85 args_array[0] = (void*) &flags;
86 args_array[1] = (void*) __UNCONST(&cb);
87 args_array[2] = (void*) cb_args;
88 args_array[3] = (void*) sentry;
89 args_array[4] = (void*) sentry_stats;
90 args_array[5] = (void*) &selement_num;
91 args_array[6] = (void*) &sel_analyzed_num;
92 ret = magic_type_walk_root_all(sentry->type, magic_type_analyzer_cb,
93 args_array);
94 if(ret < 0) {
95 return ret;
96 }
97
98 return flags;
99 }
100
101 /*===========================================================================*
102 * magic_sentries_analyze *
103 *===========================================================================*/
magic_sentries_analyze(int flags,const magic_sentry_analyze_cb_t cb,void * cb_args,_magic_sel_stats_t * sentries_stats)104 PUBLIC int magic_sentries_analyze(int flags, const magic_sentry_analyze_cb_t cb,
105 void *cb_args, _magic_sel_stats_t *sentries_stats)
106 {
107 int i, ret;
108 struct _magic_sentry *sentry;
109
110 if (flags & MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS)
111 magic_reentrant_disable();
112
113 /* See if any pre-analyze callback has been registered. */
114 if (magic_sentries_analyze_pre_cb) {
115 ret = magic_sentries_analyze_pre_cb();
116 if (ret < 0) {
117 return ret;
118 }
119 }
120
121 /* Analyze all the sentries. */
122 for (i = 0 ; i < _magic_sentries_num ; i++) {
123 sentry = &_magic_sentries[i];
124 ret = magic_sentry_analyze(sentry, flags, cb, cb_args, sentries_stats);
125 if (ret < 0) {
126 return ret;
127 }
128 else {
129 flags |= ret;
130 }
131 }
132
133 /* Analyze all the dsentries if asked to. */
134 if (flags & MAGIC_SEL_ANALYZE_DYNAMIC) {
135 return magic_dsentries_analyze(flags, cb, cb_args, sentries_stats);
136 }
137
138 if (flags & MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS)
139 magic_reentrant_enable();
140
141 return flags;
142 }
143
144 /*===========================================================================*
145 * magic_sentry_print_selements *
146 *===========================================================================*/
magic_sentry_print_selements(struct _magic_sentry * sentry)147 PUBLIC int magic_sentry_print_selements(struct _magic_sentry* sentry)
148 {
149 int flags = (MAGIC_SEL_ANALYZE_POINTERS|MAGIC_SEL_ANALYZE_NONPOINTERS|MAGIC_SEL_ANALYZE_DATA|MAGIC_SEL_ANALYZE_INVARIANTS|MAGIC_SEL_ANALYZE_VIOLATIONS);
150 return magic_sentry_analyze(sentry, flags, magic_sentry_print_el_cb, NULL, NULL);
151 }
152
153 /*===========================================================================*
154 * magic_sentry_print_ptr_selements *
155 *===========================================================================*/
magic_sentry_print_ptr_selements(struct _magic_sentry * sentry,int skip_null_ptrs,int max_target_recusions)156 PUBLIC int magic_sentry_print_ptr_selements(struct _magic_sentry* sentry,
157 int skip_null_ptrs, int max_target_recusions)
158 {
159 int flags = (MAGIC_SEL_ANALYZE_POINTERS|MAGIC_SEL_ANALYZE_DATA|MAGIC_SEL_ANALYZE_INVARIANTS|MAGIC_SEL_ANALYZE_VIOLATIONS);
160 void* args_array[2];
161 args_array[0] = &skip_null_ptrs;
162 args_array[1] = &max_target_recusions;
163 return magic_sentry_analyze(sentry, flags, magic_sentry_print_ptr_el_cb, args_array, NULL);
164 }
165
166 /*===========================================================================*
167 * magic_dsentries_analyze *
168 *===========================================================================*/
magic_dsentries_analyze(int flags,const magic_sentry_analyze_cb_t cb,void * cb_args,_magic_sel_stats_t * dsentries_stats)169 PUBLIC int magic_dsentries_analyze(int flags, const magic_sentry_analyze_cb_t cb,
170 void *cb_args, _magic_sel_stats_t *dsentries_stats)
171 {
172 int ret = 0;
173 struct _magic_dsentry *prev_dsentry, *dsentry;
174 struct _magic_sentry* sentry;
175
176 /* If dead dsentries are enabled, garbage collect them to ensure consistency. */
177 if (magic_allow_dead_dsentries)
178 magic_free_dead_dsentries();
179
180 /* Analyze all the dsentries. */
181 /*
182 * We need to hold the DSENTRY, DFUNCTION and DSODESC locks for the
183 * magic_range_lookup_by_addr() function.
184 */
185 MAGIC_MULTIPLE_LOCK(1, 1, 1, 0);
186 MAGIC_DSENTRY_ALIVE_BLOCK_ITER(_magic_first_dsentry, prev_dsentry, dsentry,
187 sentry,
188
189 /*
190 * Check if we should analyze out-of-band dsentries.
191 */
192 if (!(flags & MAGIC_SEL_ANALYZE_OUT_OF_BAND) &&
193 MAGIC_STATE_FLAG(sentry, MAGIC_STATE_OUT_OF_BAND)) {
194 continue;
195 }
196
197 /*
198 * Check if we should analyze shlib state dsentries.
199 */
200 if (!(flags & MAGIC_SEL_ANALYZE_LIB_SRC) &&
201 MAGIC_STATE_FLAG(sentry, MAGIC_STATE_LIB)) {
202 continue;
203 }
204
205 ret = magic_sentry_analyze(sentry, flags, cb, cb_args, dsentries_stats);
206 if (ret < 0) {
207 break;
208 }
209 else {
210 flags |= ret;
211 }
212 );
213 MAGIC_MULTIPLE_UNLOCK(1, 1, 1, 0);
214
215 return ret < 0 ? ret : flags;
216 }
217
218 /*===========================================================================*
219 * magic_sentry_print_el_cb *
220 *===========================================================================*/
magic_sentry_print_el_cb(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,void * cb_args)221 PUBLIC int magic_sentry_print_el_cb(_magic_selement_t* selement,
222 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
223 void* cb_args)
224 {
225 if(sel_analyzed->num == 1) {
226 MAGIC_SENTRY_PRINT(selement->sentry, MAGIC_EXPAND_TYPE_STR);
227 _magic_printf("\n");
228 }
229
230 MAGIC_SELEMENT_PRINT(selement, MAGIC_EXPAND_TYPE_STR);
231 _magic_printf("\n");
232 MAGIC_SEL_ANALYZED_PRINT(sel_analyzed, MAGIC_EXPAND_TYPE_STR);
233 _magic_printf("\n");
234 MAGIC_SEL_STATS_PRINT(sel_stats);
235 _magic_printf("\n\n");
236
237 return MAGIC_SENTRY_ANALYZE_CONTINUE;
238 }
239
240 /*===========================================================================*
241 * magic_sentry_print_ptr_el_cb *
242 *===========================================================================*/
magic_sentry_print_ptr_el_cb(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,void * cb_args)243 PUBLIC int magic_sentry_print_ptr_el_cb(_magic_selement_t* selement,
244 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
245 void* cb_args)
246 {
247 int r;
248 void** args_array = (void**) cb_args;
249 int skip_null_ptrs = args_array ? *((int*)args_array[0]) : 0;
250 int max_target_recursions = args_array ? *((int*)args_array[1]) : 0;
251
252 if(sel_analyzed->type_id != MAGIC_TYPE_POINTER) {
253 return MAGIC_SENTRY_ANALYZE_CONTINUE;
254 }
255 if(skip_null_ptrs && sel_analyzed->u.ptr.value == 0) {
256 return MAGIC_SENTRY_ANALYZE_CONTINUE;
257 }
258 magic_sentry_print_el_cb(selement, sel_analyzed, sel_stats, cb_args);
259 if(max_target_recursions>0 && !(sel_analyzed->flags & MAGIC_SEL_FOUND_VIOLATIONS)) {
260 struct _magic_sentry *sentry = &sel_analyzed->u.ptr.trg.dsentry.sentry;
261 if(MAGIC_SEL_ANALYZED_PTR_HAS_TRG_SENTRY(sel_analyzed) && MAGIC_SENTRY_ID(sentry)!=MAGIC_SENTRY_ID(selement->sentry)) {
262 r = magic_sentry_print_ptr_selements(sentry, skip_null_ptrs,
263 max_target_recursions-1);
264 if(r < 0) {
265 _magic_printf("magic_sentry_print_ptr_el_cb: recursive step reported error %d\n", r);
266 return r;
267 }
268 }
269 }
270
271 return MAGIC_SENTRY_ANALYZE_CONTINUE;
272 }
273
274 /*===========================================================================*
275 * magic_sentry_print_el_with_trg_reg_cb *
276 *===========================================================================*/
magic_sentry_print_el_with_trg_reg_cb(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,void * cb_args)277 PUBLIC int magic_sentry_print_el_with_trg_reg_cb(_magic_selement_t* selement,
278 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
279 void* cb_args)
280 {
281 if(MAGIC_SEL_ANALYZED_TRG_FLAGS(sel_analyzed)) {
282 return magic_sentry_print_el_cb(selement, sel_analyzed, sel_stats,
283 cb_args);
284 }
285
286 return MAGIC_SENTRY_ANALYZE_CONTINUE;
287 }
288
289 /*===========================================================================*
290 * magic_sentry_print_el_with_trg_cb *
291 *===========================================================================*/
magic_sentry_print_el_with_trg_cb(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,void * cb_args)292 PUBLIC int magic_sentry_print_el_with_trg_cb(_magic_selement_t* selement,
293 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
294 void* cb_args)
295 {
296 if(MAGIC_SEL_ANALYZED_TRG_FLAGS(sel_analyzed)
297 && MAGIC_SELEMENT_HAS_TRG(selement)) {
298 return magic_sentry_print_el_cb(selement, sel_analyzed, sel_stats,
299 cb_args);
300 }
301
302 return MAGIC_SENTRY_ANALYZE_CONTINUE;
303 }
304
305 /*===========================================================================*
306 * magic_type_count_ptrs *
307 *===========================================================================*/
magic_type_count_ptrs(const struct _magic_type * type,int * ptr_num)308 PUBLIC int magic_type_count_ptrs(const struct _magic_type* type, int* ptr_num)
309 {
310 int ret;
311 void* args_array[4] = { NULL, NULL, NULL };
312 args_array[3] = ptr_num;
313 *ptr_num = 0;
314 ret = magic_type_walk_root_all(type, magic_type_extract_ptr_cb, args_array);
315 assert(ret >= 0);
316 return 0;
317 }
318
319 /*===========================================================================*
320 * magic_type_examine_ptr_cb *
321 *===========================================================================*/
magic_type_examine_ptr_cb(const struct _magic_type * parent_type,const unsigned parent_offset,int child_num,const struct _magic_type * type,const unsigned offset,int depth,void * cb_args)322 PUBLIC int magic_type_examine_ptr_cb(const struct _magic_type* parent_type,
323 const unsigned parent_offset, int child_num,
324 const struct _magic_type* type, const unsigned offset, int depth, void* cb_args)
325 {
326 int ret;
327 void** args_array = (void**) cb_args;
328 if(type->type_id == MAGIC_TYPE_POINTER) {
329 const struct _magic_sentry *root_entry = (const struct _magic_sentry *) args_array[0];
330 int *ptrs_found = (int*) args_array[1];
331 char* root_address = root_entry->address;
332 void* ptr_address = root_address ? root_address+offset : NULL;
333 void* target_address = ptr_address ? *((void**)ptr_address) : NULL;
334 (*ptrs_found)++;
335 _magic_printf("Pointer found for root entry (name=%s, address=0x%08x) at offset %d, static target type is: ", root_entry->name, (unsigned) root_address, offset);
336 magic_type_str_print(type->contained_types[0]);
337 _magic_printf(" - dynamic target types are: ");
338 if(!target_address) {
339 _magic_printf("NULL");
340 }
341 else {
342 ret = magic_type_str_print_from_target(target_address);
343 if(ret < 0) {
344 _magic_printf("ENTRY NOT FOUND");
345 }
346 }
347 _magic_printf("\n");
348 }
349 return MAGIC_TYPE_WALK_CONTINUE;
350 }
351
352 /*===========================================================================*
353 * magic_type_extract_ptr_cb *
354 *===========================================================================*/
magic_type_extract_ptr_cb(const struct _magic_type * parent_type,const unsigned parent_offset,int child_num,const struct _magic_type * type,const unsigned offset,int depth,void * cb_args)355 PUBLIC int magic_type_extract_ptr_cb(const struct _magic_type* parent_type,
356 const unsigned parent_offset, int child_num,
357 const struct _magic_type* type, const unsigned offset, int depth, void* cb_args)
358 {
359 void** args_array = (void**) cb_args;
360 static void* null_ptr=NULL;
361 if(type->type_id == MAGIC_TYPE_POINTER) {
362 const struct _magic_sentry *root_entry = (const struct _magic_sentry *) args_array[0];
363 void ***ptr_map = (void ***) args_array[1];
364 const struct _magic_type **ptr_type_map = (const struct _magic_type **) args_array[2];
365 int *ptr_num = (int*) args_array[3];
366 char* root_ptr;
367 void** ptr_ptr;
368 assert(ptr_num);
369 if(root_entry && ptr_map && ptr_type_map) {
370 root_ptr = root_entry->address;
371 ptr_ptr= root_ptr ? (void**)(root_ptr+offset) : &null_ptr;
372 ptr_map[*ptr_num] = ptr_ptr;
373 ptr_type_map[*ptr_num] = type;
374 }
375 (*ptr_num)++;
376 }
377 return MAGIC_TYPE_WALK_CONTINUE;
378 }
379
380 /*===========================================================================*
381 * magic_type_analyzer_cb *
382 *===========================================================================*/
magic_type_analyzer_cb(const struct _magic_type * parent_type,const unsigned parent_offset,int child_num,const struct _magic_type * type,const unsigned offset,int depth,void * cb_args)383 PUBLIC int magic_type_analyzer_cb(const struct _magic_type* parent_type,
384 const unsigned parent_offset, int child_num, const struct _magic_type* type,
385 const unsigned offset, int depth, void* cb_args)
386 {
387 int ret;
388 void **args_array = (void **) cb_args;
389 int *flags = (int *)args_array[0];
390 magic_sentry_analyze_cb_t sentry_analyze_cb =
391 *((magic_sentry_analyze_cb_t *) args_array[1]);
392 void *sentry_analyze_cb_args = (void *) args_array[2];
393 struct _magic_sentry* sentry = (struct _magic_sentry *) args_array[3];
394 _magic_sel_stats_t *sentry_stats = (_magic_sel_stats_t *) args_array[4];
395 int *selement_num = (int *) args_array[5];
396 int *sel_analyzed_num = (int *) args_array[6];
397 static int likely_pointer_orig_type_id;
398 static int likely_pointer_orig_contained_type_id;
399 _magic_selement_t selement;
400 _magic_sel_analyzed_t sel_analyzed;
401 _magic_sel_stats_t sel_stats;
402
403 if (type->type_id == MAGIC_TYPE_UNION &&
404 ((*flags) & MAGIC_SEL_SKIP_UNIONS)) {
405 /* Skip unions when requested. */
406 return MAGIC_TYPE_WALK_SKIP_PATH;
407 }
408
409 if ((type->type_id == MAGIC_TYPE_INTEGER ||
410 type->type_id == MAGIC_TYPE_ENUM) &&
411 ((*flags) & MAGIC_SEL_SKIP_INTEGERS)) {
412 /* Skip integers when requested. */
413 return MAGIC_TYPE_WALK_SKIP_PATH;
414 }
415
416 if (((*flags) & MAGIC_SEL_ANALYZE_LIKELYPOINTERS) &&
417 (MAGIC_TYPE_IS_RAW_ARRAY(type) ||
418 (MAGIC_TYPE_IS_INT_ARRAY(type) &&
419 type->contained_types[0]->size != sizeof(void *) &&
420 type->size >= sizeof(void *)) ||
421 (type->type_id == MAGIC_TYPE_INTEGER && type->size > sizeof(void *)))) {
422 /* This can be either UNION, INTEGER or ARRAY (of VOID or INTEGER). */
423 likely_pointer_orig_type_id = type->type_id;
424 if (type->type_id == MAGIC_TYPE_ARRAY)
425 likely_pointer_orig_contained_type_id =
426 type->contained_types[0]->type_id;
427 /* Try to find likely pointers in raw arrays. */
428 ret = magic_type_walk_as_ptrint_array(parent_type, parent_offset,
429 child_num, type, (char *)sentry->address + offset, offset,
430 0, ULONG_MAX, magic_type_analyzer_cb, cb_args);
431 likely_pointer_orig_type_id = likely_pointer_orig_contained_type_id = 0;
432 if (ret != MAGIC_EBADWALK) {
433 return ret == 0 ? MAGIC_TYPE_WALK_SKIP_PATH : ret;
434 }
435 }
436
437 selement.sentry = sentry;
438 selement.parent_type = parent_type;
439 selement.parent_address = (char *)sentry->address + parent_offset;
440 selement.child_num = child_num;
441 selement.type = type;
442 selement.address = (char *)sentry->address + offset;
443 selement.depth = depth;
444 selement.num = ++(*selement_num);
445 selement.cb_args = cb_args;
446
447 ret = magic_selement_analyze(&selement, *flags, &sel_analyzed, &sel_stats);
448 if (ret &&
449 (((ret & MAGIC_SEL_FOUND_DATA) &&
450 ((*flags) & MAGIC_SEL_ANALYZE_DATA)) ||
451 ((ret & MAGIC_SEL_FOUND_INVARIANTS) &&
452 ((*flags) & MAGIC_SEL_ANALYZE_INVARIANTS)) ||
453 ((ret & MAGIC_SEL_FOUND_VIOLATIONS) &&
454 ((*flags) & MAGIC_SEL_ANALYZE_VIOLATIONS)) ||
455 ((ret & MAGIC_SEL_FOUND_WALKABLE) &&
456 ((*flags) & MAGIC_SEL_ANALYZE_WALKABLE))
457 )) {
458 *flags |= ret;
459 sel_analyzed.num = ++(*sel_analyzed_num);
460 if (likely_pointer_orig_type_id) {
461 sel_analyzed.type_id = likely_pointer_orig_type_id;
462 sel_analyzed.contained_type_id =
463 likely_pointer_orig_contained_type_id;
464 }
465 ret = sentry_analyze_cb(&selement, &sel_analyzed, &sel_stats,
466 sentry_analyze_cb_args);
467 if (sel_analyzed.flags & MAGIC_SEL_FOUND_INVARIANTS) {
468 _magic_sel_stats_t* sel_stats_ptr = &sel_stats;
469 if (sentry_stats) {
470 MAGIC_SEL_STATS_INCR(sentry_stats, sel_stats_ptr);
471 }
472 }
473 if (ret != MAGIC_SENTRY_ANALYZE_CONTINUE) {
474 switch (ret) {
475 case MAGIC_SENTRY_ANALYZE_SKIP_PATH:
476 ret = MAGIC_TYPE_WALK_SKIP_PATH;
477 break;
478 case MAGIC_SENTRY_ANALYZE_STOP:
479 ret = MAGIC_TYPE_WALK_STOP;
480 break;
481 default:
482 assert(ret < 0 && "Invalid error code!");
483 break;
484 }
485 return ret;
486 }
487 }
488
489 return MAGIC_TYPE_WALK_CONTINUE;
490 }
491
492 /*===========================================================================*
493 * magic_selement_analyze *
494 *===========================================================================*/
magic_selement_analyze(_magic_selement_t * selement,int flags,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats)495 PUBLIC int magic_selement_analyze(_magic_selement_t *selement, int flags,
496 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats)
497 {
498 const struct _magic_type *type = selement->type;
499 short is_ptr_el = type->type_id == MAGIC_TYPE_POINTER;
500 short is_nonptr_el = type->num_child_types == 0 || (type->type_id == MAGIC_TYPE_INTEGER && type->num_child_types > 0);
501 short analyze_ptr_el, analyze_nonptr_el;
502
503 if (!is_ptr_el && !is_nonptr_el) {
504 if (MAGIC_TYPE_IS_WALKABLE(type)) {
505 sel_analyzed->type_id = MAGIC_TYPE_OPAQUE;
506 return MAGIC_SEL_FOUND_WALKABLE;
507 }
508 /* Not an element to analyze. */
509 return 0;
510 }
511 assert(is_ptr_el ^ is_nonptr_el);
512
513 analyze_ptr_el = is_ptr_el && (flags & MAGIC_SEL_ANALYZE_POINTERS);
514 analyze_nonptr_el = 0;
515 if (is_nonptr_el && ((flags & MAGIC_SEL_ANALYZE_DATA) || MAGIC_TYPE_HAS_VALUE_SET(type))) {
516 if (flags & MAGIC_SEL_ANALYZE_NONPOINTERS) {
517 analyze_nonptr_el = 1;
518 }
519 else if (flags & MAGIC_SEL_ANALYZE_LIKELYPOINTERS) {
520 short is_intvalue_el = type->type_id == MAGIC_TYPE_ENUM
521 || type->type_id == MAGIC_TYPE_INTEGER;
522 if (is_intvalue_el && type->size == sizeof(void *)) {
523 long value = magic_selement_to_int(selement);
524 analyze_nonptr_el = MAGIC_INT_IS_LIKELY_PTR(value);
525 }
526 }
527 }
528
529 if (analyze_nonptr_el && (flags & MAGIC_SEL_ANALYZE_NONPTRS_AS_PTRS) &&
530 type->size == sizeof(void *)) {
531 struct _magic_type tmp_type;
532 int ret;
533 tmp_type = *(selement->type);
534 tmp_type.type_id = MAGIC_TYPE_POINTER;
535 selement->type = &tmp_type;
536
537 /* Analyze non-pointer element as a pointer. */
538 ret = magic_selement_analyze_ptr(selement, flags, sel_analyzed, sel_stats);
539
540 selement->type = type;
541 /* Keep original type in sel_analyzed. */
542 sel_analyzed->type_id = type->type_id;
543
544 return ret;
545 }
546
547 assert(!analyze_ptr_el || !analyze_nonptr_el);
548
549 if (analyze_ptr_el) {
550 /* Analyze pointer element. */
551 return magic_selement_analyze_ptr(selement, flags, sel_analyzed,
552 sel_stats);
553 }
554 if (analyze_nonptr_el) {
555 /* Analyze nonpointer element. */
556 return magic_selement_analyze_nonptr(selement, flags, sel_analyzed,
557 sel_stats);
558 }
559
560 /* Nothing to analyze. */
561 return 0;
562 }
563
564 /*===========================================================================*
565 * magic_selement_analyze_ptr_value_invs *
566 *===========================================================================*/
magic_selement_analyze_ptr_value_invs(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats)567 PUBLIC int magic_selement_analyze_ptr_value_invs(_magic_selement_t *selement,
568 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats)
569 {
570 const struct _magic_type* ptr_type = selement->type;
571 int i, ret = 0;
572 const struct _magic_type *first_trg_type;
573 void* value = sel_analyzed->u.ptr.value;
574
575 first_trg_type = MAGIC_SEL_ANALYZED_PTR_FIRST_TRG_TYPE(sel_analyzed);
576 assert(sel_analyzed->u.ptr.num_trg_types > 0 && first_trg_type);
577 if(first_trg_type == MAGIC_TYPE_NULL_ENTRY) {
578 ret |= MAGIC_SEL_FOUND_INVARIANTS;
579 sel_stats->null_type_found++;
580 }
581 else if(MAGIC_TYPE_FLAG(ptr_type, MAGIC_TYPE_INT_CAST)) {
582 if(MAGIC_TYPE_HAS_VALUE_SET(ptr_type)) {
583 i=0;
584 while(MAGIC_TYPE_HAS_VALUE(ptr_type, i)) {
585 int trg_value = MAGIC_TYPE_VALUE(ptr_type, i);
586 if(trg_value == (int) value) {
587 ret |= MAGIC_SEL_FOUND_INVARIANTS;
588 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed, MAGIC_TYPE_VALUE_FOUND);
589 sel_stats->value_found++;
590 break;
591 }
592 i++;
593 }
594 if(!(ret & MAGIC_SEL_FOUND_INVARIANTS) && MAGIC_TYPE_FLAG(ptr_type, MAGIC_TYPE_STRICT_VALUE_SET)) {
595 ret |= MAGIC_SEL_FOUND_INVARIANTS;
596 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed, MAGIC_TYPE_BAD_VALUE);
597 sel_stats->badvalue_found++;
598 }
599 }
600 else if(MAGIC_PTR_IS_LIKELY_INT(value)) {
601 ret |= MAGIC_SEL_FOUND_INVARIANTS;
602 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed, MAGIC_TYPE_VALUE_FOUND);
603 sel_stats->value_found++;
604 }
605 }
606
607 return ret;
608 }
609
610 /*===========================================================================*
611 * magic_selement_analyze_ptr_trg_invs *
612 *===========================================================================*/
magic_selement_analyze_ptr_trg_invs(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats)613 PUBLIC int magic_selement_analyze_ptr_trg_invs(_magic_selement_t *selement,
614 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats)
615 {
616 int ret = 0;
617 const struct _magic_type *first_trg_type;
618
619 first_trg_type = MAGIC_SEL_ANALYZED_PTR_FIRST_TRG_TYPE(sel_analyzed);
620 assert(sel_analyzed->u.ptr.num_trg_types > 0 && first_trg_type);
621 sel_stats->trg_flags |= sel_analyzed->u.ptr.trg_flags;
622 if(first_trg_type == MAGIC_TYPE_ENTRY_NOT_FOUND) {
623 ret |= MAGIC_SEL_FOUND_INVARIANTS;
624 sel_stats->unknown_found++;
625 }
626 else if(first_trg_type == MAGIC_TYPE_BAD_ENTRY) {
627 ret |= MAGIC_SEL_FOUND_INVARIANTS;
628 sel_stats->badentry_found++;
629 }
630 else if(first_trg_type == MAGIC_TYPE_BAD_OFFSET) {
631 ret |= MAGIC_SEL_FOUND_INVARIANTS;
632 sel_stats->badoffset_found++;
633 }
634
635 return ret;
636 }
637
638 /*===========================================================================*
639 * magic_selement_analyze_ptr_target *
640 *===========================================================================*/
magic_selement_analyze_ptr_target(const struct _magic_type * ptr_type,const struct _magic_type * trg_type,int trg_flags)641 PUBLIC _magic_trg_stats_t magic_selement_analyze_ptr_target(const struct _magic_type *ptr_type,
642 const struct _magic_type *trg_type, int trg_flags)
643 {
644 const struct _magic_type* type = ptr_type->contained_types[0];
645
646 /* Analyze void target types first. */
647 if(MAGIC_TYPE_IS_VOID(trg_type)) {
648 int ptr_can_point_to_text = magic_type_ptr_is_text(ptr_type);
649 int ptr_can_point_to_data = magic_type_ptr_is_data(ptr_type);
650 int is_trg_data = (MAGIC_STATE_FLAGS_REGION(trg_flags) & ~MAGIC_STATE_TEXT) != 0;
651 int is_trg_text = trg_flags & MAGIC_STATE_TEXT;
652 assert(ptr_can_point_to_text || ptr_can_point_to_data);
653 assert(is_trg_text || is_trg_data);
654 if((!ptr_can_point_to_text && is_trg_text)
655 || (!ptr_can_point_to_data && is_trg_data)) {
656 return _badentry_found;
657 }
658 else {
659 return _void_type_found;
660 }
661 }
662
663 /* Analyze void types next. */
664 if(MAGIC_TYPE_IS_VOID(type)) {
665 /* Pretend the pointer has been found, void* can point to any valid target. */
666 return _ptr_type_found;
667 }
668
669 /* See if the target type is compatible with the static type. */
670 if(magic_type_compatible(trg_type, type, 0)) {
671 return _ptr_type_found;
672 }
673
674 /* See if the target type is compatible with some static cast type. */
675 if(MAGIC_TYPE_HAS_COMP_TYPES(ptr_type) && magic_type_comp_compatible(ptr_type, trg_type)) {
676 return _comp_trg_types_found;
677 }
678
679 /* No chance. The pointer is pointing to some other invalid type. */
680 return _other_types_found;
681 }
682
683 /*===========================================================================*
684 * magic_selement_analyze_ptr_type_invs *
685 *===========================================================================*/
magic_selement_analyze_ptr_type_invs(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats)686 PUBLIC int magic_selement_analyze_ptr_type_invs(_magic_selement_t *selement,
687 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats)
688 {
689 const struct _magic_type* ptr_type = selement->type;
690 unsigned int i;
691 int ret = 0;
692 int trg_flags;
693 const struct _magic_type *trg_type;
694 _magic_trg_stats_t trg_stats;
695
696 assert(sel_analyzed->u.ptr.num_trg_types > 0);
697 if(MAGIC_SEL_ANALYZED_PTR_HAS_SPECIAL_TRG_TYPE(sel_analyzed)) {
698 /* No invariants if we only have a special target type. */
699 return ret;
700 }
701 trg_flags= sel_analyzed->u.ptr.trg_flags;
702 sel_stats->trg_flags |= trg_flags;
703 ret |= MAGIC_SEL_FOUND_INVARIANTS;
704
705 /* Analyze targets. */
706 sel_analyzed->u.ptr.first_legal_trg_type = -1;
707 sel_analyzed->u.ptr.num_legal_trg_types = 0;
708 for(i=0;i<sel_analyzed->u.ptr.num_trg_types;i++) {
709 trg_type = sel_analyzed->u.ptr.trg_selements[i].type;
710 trg_stats = magic_selement_analyze_ptr_target(ptr_type, trg_type, trg_flags);
711 sel_analyzed->u.ptr.trg_stats[i] = trg_stats;
712 if(!MAGIC_SEL_ANALYZED_TRG_STATS_HAS_VIOLATIONS(trg_stats)) {
713 sel_analyzed->u.ptr.num_legal_trg_types++;
714 if(sel_analyzed->u.ptr.first_legal_trg_type == -1) {
715 sel_analyzed->u.ptr.first_legal_trg_type = i;
716 }
717 }
718 }
719
720 /* Set global stats. */
721 for(i=0;i<sel_analyzed->u.ptr.num_trg_types;i++) {
722 trg_stats = sel_analyzed->u.ptr.trg_stats[i];
723 if(trg_stats == _badentry_found) {
724 sel_stats->badentry_found++;
725 return ret;
726 }
727 else if(trg_stats == _void_type_found) {
728 sel_stats->void_type_found++;
729 return ret;
730 }
731 }
732 for(i=0;i<sel_analyzed->u.ptr.num_trg_types;i++) {
733 trg_stats = sel_analyzed->u.ptr.trg_stats[i];
734 if(trg_stats == _ptr_type_found) {
735 sel_stats->ptr_type_found++;
736 return ret;
737 }
738 }
739 for(i=0;i<sel_analyzed->u.ptr.num_trg_types;i++) {
740 trg_stats = sel_analyzed->u.ptr.trg_stats[i];
741 if(trg_stats == _comp_trg_types_found) {
742 sel_stats->comp_trg_types_found++;
743 return ret;
744 }
745 }
746 sel_stats->other_types_found++;
747 return ret;
748 }
749
750 /*===========================================================================*
751 * magic_selement_recurse_ptr *
752 *===========================================================================*/
magic_selement_recurse_ptr(_magic_selement_t * selement,_magic_selement_t * new_selement,int max_steps)753 PUBLIC int magic_selement_recurse_ptr(_magic_selement_t *selement,
754 _magic_selement_t *new_selement, int max_steps)
755 {
756 _magic_sel_stats_t sel_stats;
757 _magic_sel_analyzed_t sel_analyzed;
758 int steps = 0;
759
760 if(selement->type->type_id != MAGIC_TYPE_POINTER) {
761 return MAGIC_EINVAL;
762 }
763
764 *new_selement = *selement;
765 while(1) {
766 magic_selement_analyze_ptr(new_selement, MAGIC_SEL_ANALYZE_ALL,
767 &sel_analyzed, &sel_stats);
768 if(MAGIC_SEL_ANALYZED_PTR_HAS_SPECIAL_TRG_TYPE(&sel_analyzed)) {
769 return steps;
770 }
771 *new_selement = sel_analyzed.u.ptr.trg_selements[0];
772 steps++;
773 if(new_selement->type->type_id != MAGIC_TYPE_POINTER || (max_steps > 0 && steps >= max_steps)) {
774 break;
775 }
776 }
777
778 return steps;
779 }
780
781 /*===========================================================================*
782 * magic_sentry_analyze_ptr_trg_cb *
783 *===========================================================================*/
magic_sentry_analyze_ptr_trg_cb(const struct _magic_type * trg_parent_type,const unsigned parent_offset,int child_num,const struct _magic_type * trg_type,const unsigned offset,int depth,void * cb_args)784 PRIVATE int magic_sentry_analyze_ptr_trg_cb(const struct _magic_type *trg_parent_type,
785 const unsigned parent_offset, int child_num,
786 const struct _magic_type *trg_type, const unsigned offset, int depth, void *cb_args)
787 {
788 void **args_array = (void **) cb_args;
789 _magic_sel_analyzed_t *sel_analyzed = (_magic_sel_analyzed_t *) args_array[3];
790 _magic_selement_t *sel;
791 char *trg_address;
792 int analysis_flags = (*(int *)(args_array[4]));
793
794 if (trg_type->type_id == MAGIC_TYPE_ARRAY) {
795 /* Skip arrays. */
796 return MAGIC_TYPE_WALK_CONTINUE;
797 }
798
799 if (!sel_analyzed->u.ptr.trg_flags) {
800 /* Set trg flags and offset only the first time. */
801 struct _magic_dsentry **trg_dsentry = (struct _magic_dsentry **) args_array[0];
802 struct _magic_dfunction **trg_dfunction = (struct _magic_dfunction **) args_array[1];
803 int flags;
804 if (*trg_dsentry) {
805 assert(!(*trg_dfunction));
806 flags = MAGIC_DSENTRY_TO_SENTRY(*trg_dsentry)->flags;
807 if (flags & MAGIC_STATE_DYNAMIC) {
808 assert(!(flags & MAGIC_STATE_DATA) || (flags & MAGIC_STATE_LIB));
809 assert(MAGIC_STATE_REGION(MAGIC_DSENTRY_TO_SENTRY(*trg_dsentry)));
810 }
811 else {
812 assert((flags & MAGIC_STATE_DATA) && !(flags & MAGIC_STATE_LIB));
813 }
814 }
815 else {
816 assert(*trg_dfunction);
817 flags = MAGIC_DFUNCTION_TO_FUNCTION(*trg_dfunction)->flags;
818 assert(flags & MAGIC_STATE_TEXT);
819 }
820 sel_analyzed->u.ptr.trg_flags = flags;
821 if (analysis_flags & MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS)
822 sel_analyzed->u.ptr.trg_flags |= MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS;
823 sel_analyzed->u.ptr.trg_offset = offset;
824 }
825
826 /* Add target types. */
827 trg_address = MAGIC_SEL_ANALYZED_PTR_TRG_ADDRESS(sel_analyzed);
828 assert(trg_address);
829 sel = &sel_analyzed->u.ptr.trg_selements[sel_analyzed->u.ptr.num_trg_types];
830 if (!(analysis_flags & MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS)) {
831 sel->sentry = MAGIC_SEL_ANALYZED_PTR_HAS_TRG_SENTRY(sel_analyzed) ? MAGIC_DSENTRY_TO_SENTRY(&sel_analyzed->u.ptr.trg.dsentry) : NULL;
832 } else {
833 sel->sentry = MAGIC_SEL_ANALYZED_PTR_HAS_TRG_SENTRY(sel_analyzed) ? MAGIC_DSENTRY_TO_SENTRY(sel_analyzed->u.ptr.trg_p.dsentry) : NULL;
834 }
835 sel->parent_type = trg_parent_type;
836 sel->parent_address = trg_address + parent_offset;
837 sel->child_num = child_num;
838 sel->type = trg_type;
839 sel->address = trg_address + offset;
840 sel_analyzed->u.ptr.num_trg_types++;
841
842 return MAGIC_TYPE_WALK_CONTINUE;
843 }
844
845 /*===========================================================================*
846 * magic_selement_analyze_ptr *
847 *===========================================================================*/
magic_selement_analyze_ptr(_magic_selement_t * selement,int flags,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats)848 PUBLIC int magic_selement_analyze_ptr(_magic_selement_t *selement, int flags,
849 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats)
850 {
851 const struct _magic_type *ptr_type = selement->type;
852 short is_ptr_el = ptr_type->type_id == MAGIC_TYPE_POINTER;
853 int r, ret = 0;
854
855 sel_analyzed->type_id = 0;
856 if (!is_ptr_el) {
857 /* Nothing to do. */
858 return 0;
859 }
860 memset(&sel_analyzed->u.ptr, 0, sizeof(sel_analyzed->u.ptr));
861 memset(sel_stats, 0, sizeof(_magic_sel_stats_t));
862
863 if (flags & (MAGIC_SEL_ANALYZE_DATA | MAGIC_SEL_ANALYZE_INVARIANTS | MAGIC_SEL_ANALYZE_VIOLATIONS)) {
864 /* Analyze data first. */
865 void *value = magic_selement_to_ptr(selement);
866 sel_analyzed->type_id = MAGIC_TYPE_POINTER;
867 sel_analyzed->u.ptr.value = value;
868 ret |= MAGIC_SEL_FOUND_DATA;
869 if (value == NULL) {
870 /* Null pointer. */
871 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed, MAGIC_TYPE_NULL_ENTRY);
872 }
873 else {
874 /* Check target. */
875 struct _magic_dsentry *trg_dsentry_ptr;
876 struct _magic_dfunction *trg_dfunction_ptr;
877 void *args_array[5];
878 if (!(flags & MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS)) {
879 trg_dsentry_ptr = &sel_analyzed->u.ptr.trg.dsentry;
880 trg_dfunction_ptr = &sel_analyzed->u.ptr.trg.dfunction;
881 args_array[0] = &trg_dsentry_ptr;
882 args_array[1] = &trg_dfunction_ptr;
883 } else {
884 args_array[0] = &sel_analyzed->u.ptr.trg_p.dsentry;
885 args_array[1] = &sel_analyzed->u.ptr.trg_p.dfunction;
886 }
887 args_array[2] = selement;
888 args_array[3] = sel_analyzed;
889 args_array[4] = &flags;
890 r = magic_type_target_walk(value, args_array[0], args_array[1],
891 magic_sentry_analyze_ptr_trg_cb, args_array);
892 if (r == MAGIC_ENOENT) {
893 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed, MAGIC_TYPE_ENTRY_NOT_FOUND);
894 sel_analyzed->u.ptr.trg_flags = magic_range_lookup_by_addr(value, NULL);
895 }
896 else if (r == MAGIC_EBADENT) {
897 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed, MAGIC_TYPE_BAD_ENTRY);
898 sel_analyzed->u.ptr.trg_flags = magic_range_lookup_by_addr(value, NULL);
899 }
900 else if (sel_analyzed->u.ptr.num_trg_types == 0) {
901 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed, MAGIC_TYPE_BAD_OFFSET);
902 sel_analyzed->u.ptr.trg_flags = magic_range_lookup_by_addr(value, NULL);
903 }
904 }
905
906 if (flags & (MAGIC_SEL_ANALYZE_INVARIANTS | MAGIC_SEL_ANALYZE_VIOLATIONS)) {
907 /* Check value-based invariants. */
908 ret |= magic_selement_analyze_ptr_value_invs(selement,
909 sel_analyzed, sel_stats);
910
911 /* Check target-based invariants. */
912 if (!(ret & MAGIC_SEL_FOUND_INVARIANTS)) {
913 ret |= magic_selement_analyze_ptr_trg_invs(selement,
914 sel_analyzed, sel_stats);
915 }
916
917 /* Check type-based invariants. */
918 if (!(ret & MAGIC_SEL_FOUND_INVARIANTS)) {
919 ret |= magic_selement_analyze_ptr_type_invs(selement,
920 sel_analyzed, sel_stats);
921 }
922
923 assert(ret & MAGIC_SEL_FOUND_INVARIANTS);
924 sel_stats->ptr_found++;
925 if (MAGIC_SEL_STATS_HAS_VIOLATIONS(sel_stats)) {
926 ret |= MAGIC_SEL_FOUND_VIOLATIONS;
927 }
928 }
929 }
930
931 sel_analyzed->flags = ret;
932 return ret;
933 }
934
935 /*===========================================================================*
936 * magic_selement_analyze_nonptr_value_invs *
937 *===========================================================================*/
magic_selement_analyze_nonptr_value_invs(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats)938 PRIVATE int magic_selement_analyze_nonptr_value_invs(_magic_selement_t *selement,
939 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats)
940 {
941 const struct _magic_type* type = selement->type;
942 int i, ret = 0;
943 int value = sel_analyzed->u.nonptr.value;
944
945 if(MAGIC_STATE_FLAG(selement->sentry, MAGIC_STATE_EXTERNAL))
946 return 0;
947
948 if(MAGIC_TYPE_HAS_VALUE_SET(type)) {
949 i=0;
950 ret |= MAGIC_SEL_FOUND_INVARIANTS;
951 while(MAGIC_TYPE_HAS_VALUE(type, i)) {
952 int trg_value = MAGIC_TYPE_VALUE(type, i);
953 if(trg_value == value) {
954 sel_stats->value_found++;
955 break;
956 }
957 i++;
958 }
959 if(!MAGIC_TYPE_HAS_VALUE(type, i)) {
960 sel_stats->badvalue_found++;
961 }
962 }
963
964 return ret;
965 }
966
967 /*===========================================================================*
968 * magic_selement_analyze_nonptr *
969 *===========================================================================*/
magic_selement_analyze_nonptr(_magic_selement_t * selement,int flags,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats)970 PUBLIC int magic_selement_analyze_nonptr(_magic_selement_t *selement, int flags,
971 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats)
972 {
973 int ret = 0;
974
975 sel_analyzed->type_id = 0;
976 memset(&sel_analyzed->u.nonptr, 0, sizeof(sel_analyzed->u.nonptr));
977 memset(sel_stats, 0, sizeof(_magic_sel_stats_t));
978
979 if(flags & (MAGIC_SEL_ANALYZE_DATA|MAGIC_SEL_ANALYZE_INVARIANTS|MAGIC_SEL_ANALYZE_VIOLATIONS)) {
980 /* Analyze data first. */
981 switch(selement->type->type_id) {
982 case MAGIC_TYPE_VOID:
983 sel_analyzed->type_id = MAGIC_TYPE_VOID;
984 sel_analyzed->u.nonptr.value = (long) *((char*)selement->address);
985 ret |= MAGIC_SEL_FOUND_DATA;
986 break;
987
988 case MAGIC_TYPE_FLOAT:
989 sel_analyzed->type_id = MAGIC_TYPE_FLOAT;
990 sel_analyzed->u.nonptr.value = (long) magic_selement_to_float(selement);
991 ret |= MAGIC_SEL_FOUND_DATA;
992 break;
993
994 case MAGIC_TYPE_INTEGER:
995 case MAGIC_TYPE_ENUM:
996 sel_analyzed->type_id = selement->type->type_id;
997 sel_analyzed->u.nonptr.value = magic_selement_to_int(selement);
998 ret |= MAGIC_SEL_FOUND_DATA;
999 if((flags & MAGIC_SEL_ANALYZE_LIKELYPOINTERS) && selement->type->size == sizeof(void*)) {
1000 sel_analyzed->u.nonptr.trg_flags = magic_range_lookup_by_addr((void*) sel_analyzed->u.nonptr.value, NULL);
1001 }
1002 if(flags & (MAGIC_SEL_ANALYZE_INVARIANTS|MAGIC_SEL_ANALYZE_VIOLATIONS)) {
1003 /* Check value-based invariants. */
1004 ret |= magic_selement_analyze_nonptr_value_invs(selement,
1005 sel_analyzed, sel_stats);
1006
1007 if(ret & MAGIC_SEL_FOUND_INVARIANTS) {
1008 sel_stats->nonptr_found++;
1009 if(MAGIC_SEL_STATS_HAS_VIOLATIONS(sel_stats)) {
1010 ret |= MAGIC_SEL_FOUND_VIOLATIONS;
1011 }
1012 }
1013 else {
1014 sel_stats->nonptr_unconstrained_found++;
1015 }
1016 }
1017 break;
1018 }
1019 }
1020
1021 sel_analyzed->flags = ret;
1022 return ret;
1023 }
1024
1025 /*===========================================================================*
1026 * magic_sel_analyzed_trg_selements_print *
1027 *===========================================================================*/
magic_sel_analyzed_trg_selements_print(_magic_sel_analyzed_t * sel_analyzed,int flags)1028 PUBLIC void magic_sel_analyzed_trg_selements_print(_magic_sel_analyzed_t *sel_analyzed,
1029 int flags)
1030 {
1031 int num;
1032 int i=0;
1033 const _magic_selement_t* trg_selement;
1034 _magic_trg_stats_t trg_stats;
1035
1036 num = sel_analyzed->u.ptr.num_trg_types;
1037 if(num == 0) {
1038 return;
1039 }
1040 _magic_printf("#%d|%d", num, sel_analyzed->u.ptr.num_legal_trg_types);
1041
1042 for(;i<num;i++) {
1043 trg_selement = &sel_analyzed->u.ptr.trg_selements[i];
1044 trg_stats = sel_analyzed->u.ptr.trg_stats[i];
1045 _magic_printf("%s%d|%c=", (i==0 ? ": " : ", "), i+1, MAGIC_SEL_ANALYZED_TRG_STATS_C(trg_stats));
1046 MAGIC_SELEMENT_PRINT(trg_selement, flags|MAGIC_SKIP_COMP_TYPES);
1047 }
1048 }
1049
1050 /*===========================================================================*
1051 * magic_selement_type_cast *
1052 *===========================================================================*/
magic_selement_type_cast(_magic_selement_t * selement,int flags,const struct _magic_type * type,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats)1053 PUBLIC _magic_selement_t* magic_selement_type_cast(
1054 _magic_selement_t *selement, int flags, const struct _magic_type* type,
1055 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats)
1056 {
1057 _magic_sel_stats_t my_sel_stats;
1058
1059 selement->type = type;
1060 if(sel_analyzed) {
1061 magic_selement_analyze(selement, flags,
1062 sel_analyzed, sel_stats ? sel_stats : &my_sel_stats);
1063 }
1064 return selement;
1065 }
1066
1067