1
2static bool block_check_invariants(RAnal *anal) {
3	RBIter iter;
4	RAnalBlock *block;
5	ut64 last_start = UT64_MAX;
6	r_rbtree_foreach (anal->bb_tree, iter, block, RAnalBlock, _rb) {
7		if (last_start != UT64_MAX) {
8			mu_assert ("corrupted binary tree", block->addr >= last_start);
9			mu_assert_neq (block->addr, last_start, "double blocks");
10		}
11		last_start = block->addr;
12
13		mu_assert ("block->ref < 1, but it is still in the tree", block->ref >= 1);
14		mu_assert ("block->ref < r_list_length (block->fcns)", block->ref >= r_list_length (block->fcns));
15
16		RListIter *fcniter;
17		RAnalFunction *fcn;
18		r_list_foreach (block->fcns, fcniter, fcn) {
19			RListIter *fcniter2;
20			RAnalFunction *fcn2;
21			for (fcniter2 = fcniter->n; fcniter2 && (fcn2 = fcniter2->data, 1); fcniter2 = fcniter2->n) {
22				mu_assert_ptrneq (fcn, fcn2, "duplicate function in basic block");
23			}
24			mu_assert ("block references function, but function does not reference block", r_list_contains (fcn->bbs, block));
25		}
26	}
27
28	RListIter *fcniter;
29	RAnalFunction *fcn;
30	r_list_foreach (anal->fcns, fcniter, fcn) {
31		RListIter *blockiter;
32		ut64 min = UT64_MAX;
33		ut64 max = UT64_MIN;
34		ut64 realsz = 0;
35		r_list_foreach (fcn->bbs, blockiter, block) {
36			RListIter *blockiter2;
37			RAnalBlock *block2;
38			if (block->addr < min) {
39				min = block->addr;
40			}
41			if (block->addr + block->size > max) {
42				max = block->addr + block->size;
43			}
44			realsz += block->size;
45			for (blockiter2 = blockiter->n; blockiter2 && (block2 = blockiter2->data, 1); blockiter2 = blockiter2->n) {
46				mu_assert_ptrneq (block, block2, "duplicate basic block in function");
47			}
48			mu_assert ("function references block, but block does not reference function", r_list_contains (block->fcns, fcn));
49		}
50
51		if (fcn->meta._min != UT64_MAX) {
52			mu_assert_eq (fcn->meta._min, min, "function min wrong");
53			mu_assert_eq (fcn->meta._max, max, "function max wrong");
54		}
55
56		mu_assert_eq (r_anal_function_realsize (fcn), realsz, "realsize wrong");
57	}
58	return true;
59}
60
61static bool block_check_leaks(RAnal *anal) {
62	RBIter iter;
63	RAnalBlock *block;
64	r_rbtree_foreach (anal->bb_tree, iter, block, RAnalBlock, _rb) {
65		if (block->ref != r_list_length (block->fcns))  {
66			mu_assert ("leaked basic block", false);
67		}
68	}
69	return true;
70}
71