1 #include <r_anal.h>
2 #include <r_core.h>
3 #include "minunit.h"
4 
5 #include "test_anal_block_invars.inl"
6 #define check_invariants block_check_invariants
7 #define check_leaks block_check_leaks
8 
blocks_count(RAnal * anal)9 static size_t blocks_count(RAnal *anal) {
10 	size_t count = 0;
11 	RBIter iter;
12 	RAnalBlock *block;
13 	r_rbtree_foreach(anal->bb_tree, iter, block, RAnalBlock, _rb) {
14 		count++;
15 	}
16 	return count;
17 }
18 
19 
20 #define assert_invariants(anal) do { if (!check_invariants (anal)) { return false; } } while (0)
21 #define assert_leaks(anal) do { if (!check_leaks (anal)) { return false; } } while (0)
22 
test_r_anal_block_create()23 bool test_r_anal_block_create() {
24 	RAnal *anal = r_anal_new ();
25 	assert_invariants (anal);
26 
27 	mu_assert_eq (blocks_count (anal), 0, "initial count");
28 
29 	RAnalBlock *block = r_anal_create_block (anal, 0x1337, 42);
30 	assert_invariants (anal);
31 	mu_assert ("created block", block);
32 	mu_assert_eq (block->addr, 0x1337, "created addr");
33 	mu_assert_eq (block->size, 42, "created size");
34 	mu_assert_eq (block->ref, 1, "created initial ref");
35 	mu_assert_eq (blocks_count (anal), 1, "count after create");
36 
37 	RAnalBlock *block2 = r_anal_create_block (anal, 0x133f, 100);
38 	assert_invariants (anal);
39 	mu_assert ("created block (overlap)", block2);
40 	mu_assert_eq (block2->addr, 0x133f, "created addr");
41 	mu_assert_eq (block2->size, 100, "created size");
42 	mu_assert_eq (block2->ref, 1, "created initial ref");
43 	mu_assert_eq (blocks_count (anal), 2, "count after create");
44 
45 	RAnalBlock *block3 = r_anal_create_block (anal, 0x1337, 5);
46 	assert_invariants (anal);
47 	mu_assert ("no double create on same start", !block3);
48 	mu_assert_eq (blocks_count (anal), 2, "count after failed create");
49 
50 	r_anal_block_unref (block);
51 	r_anal_block_unref (block2);
52 
53 	assert_leaks (anal);
54 	r_anal_free (anal);
55 	mu_end;
56 }
57 
test_r_anal_block_contains()58 bool test_r_anal_block_contains() {
59 	RAnalBlock dummy = { 0 };
60 	dummy.addr = 0x1337;
61 	dummy.size = 42;
62 	mu_assert ("contains before", !r_anal_block_contains (&dummy, 100));
63 	mu_assert ("contains start", r_anal_block_contains (&dummy, 0x1337));
64 	mu_assert ("contains inside", r_anal_block_contains (&dummy, 0x1339));
65 	mu_assert ("contains last", r_anal_block_contains (&dummy, 0x1337 + 42 - 1));
66 	mu_assert ("contains after", !r_anal_block_contains (&dummy, 0x1337 + 42));
67 	mu_end;
68 }
69 
test_r_anal_block_split()70 bool test_r_anal_block_split() {
71 	RAnal *anal = r_anal_new ();
72 	assert_invariants (anal);
73 
74 	RAnalBlock *block = r_anal_create_block (anal, 0x1337, 42);
75 	assert_invariants (anal);
76 	mu_assert_eq (blocks_count (anal), 1, "count after create");
77 	block->jump = 0xdeadbeef;
78 	block->fail = 0xc0ffee;
79 	block->ninstr = 5;
80 	r_anal_bb_set_offset (block, 0, 0);
81 	r_anal_bb_set_offset (block, 1, 1);
82 	r_anal_bb_set_offset (block, 2, 2);
83 	r_anal_bb_set_offset (block, 3, 4);
84 	r_anal_bb_set_offset (block, 4, 30);
85 
86 	RAnalBlock *second = r_anal_block_split (block, 0x1337);
87 	assert_invariants (anal);
88 	mu_assert_ptreq (second, block, "nop split on first addr");
89 	mu_assert_eq (blocks_count (anal), 1, "count after nop split");
90 	mu_assert_eq (block->ref, 2, "ref after nop split");
91 	r_anal_block_unref (block);
92 
93 	second = r_anal_block_split (block, 0x1339);
94 	assert_invariants (anal);
95 	mu_assert_ptrneq (second, block, "non-nop split");
96 	mu_assert_eq (blocks_count (anal), 2, "count after non-nop split");
97 
98 	mu_assert_eq (block->addr, 0x1337, "first addr after split");
99 	mu_assert_eq (block->size, 2, "first size after split");
100 	mu_assert_eq (second->addr, 0x1339, "first addr after split");
101 	mu_assert_eq (second->size, 40, "first size after split");
102 
103 	mu_assert_eq (block->jump, second->addr, "first jump");
104 	mu_assert_eq (block->fail, UT64_MAX, "first fail");
105 	mu_assert_eq (second->jump, 0xdeadbeef, "second jump");
106 	mu_assert_eq (second->fail, 0xc0ffee, "second fail");
107 
108 	mu_assert_eq (block->ninstr, 2, "first ninstr after split");
109 	mu_assert_eq (r_anal_bb_offset_inst (block, 0), 0, "first op_pos[0]");
110 	mu_assert_eq (r_anal_bb_offset_inst (block, 1), 1, "first op_pos[1]");
111 
112 	mu_assert_eq (second->ninstr, 3, "second ninstr after split");
113 	mu_assert_eq (r_anal_bb_offset_inst (second, 0), 0, "second op_pos[0]");
114 	mu_assert_eq (r_anal_bb_offset_inst (second, 1), 2, "second op_pos[1]");
115 	mu_assert_eq (r_anal_bb_offset_inst (second, 2), 28, "second op_pos[2]");
116 
117 	r_anal_block_unref (block);
118 	r_anal_block_unref (second);
119 
120 	assert_leaks (anal);
121 	r_anal_free (anal);
122 	mu_end;
123 }
124 
test_r_anal_block_split_in_function()125 bool test_r_anal_block_split_in_function() {
126 	RAnal *anal = r_anal_new ();
127 	assert_invariants (anal);
128 
129 	RAnalFunction *fcn = r_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
130 	assert_invariants (anal);
131 
132 	RAnalBlock *block = r_anal_create_block (anal, 0x1337, 42);
133 	assert_invariants (anal);
134 	mu_assert_eq (blocks_count (anal), 1, "count after create");
135 	r_anal_function_add_block (fcn, block);
136 	assert_invariants (anal);
137 	mu_assert_eq (block->ref, 2, "block refs after adding to function");
138 
139 	RAnalBlock *second = r_anal_block_split (block, 0x1339);
140 	assert_invariants (anal);
141 	mu_assert_ptrneq (second, block, "non-nop split");
142 	mu_assert_eq (blocks_count (anal), 2, "count after non-nop split");
143 	mu_assert_eq (block->ref, 2, "first block refs after adding to function");
144 	mu_assert_eq (second->ref, 2, "second block refs after adding to function");
145 
146 	mu_assert ("function has first block after split", r_list_contains (fcn->bbs, block));
147 	mu_assert ("function has second block after split", r_list_contains (fcn->bbs, second));
148 	mu_assert ("second block is in function after split", r_list_contains (block->fcns, fcn));
149 	mu_assert ("second block is in function after split", r_list_contains (second->fcns, fcn));
150 
151 	r_anal_block_unref (block);
152 	r_anal_block_unref (second);
153 
154 	assert_leaks (anal);
155 	r_anal_free (anal);
156 	mu_end;
157 }
158 
test_r_anal_block_merge()159 bool test_r_anal_block_merge() {
160 	RAnal *anal = r_anal_new ();
161 	assert_invariants (anal);
162 
163 	RAnalBlock *first = r_anal_create_block (anal, 0x1337, 42);
164 	RAnalBlock *second = r_anal_create_block (anal, 0x1337 + 42, 624);
165 	assert_invariants (anal);
166 	mu_assert_eq (blocks_count (anal), 2, "count after create");
167 	second->jump = 0xdeadbeef;
168 	second->fail = 0xc0ffee;
169 
170 	first->ninstr = 3;
171 	r_anal_bb_set_offset (first, 0, 0);
172 	r_anal_bb_set_offset (first, 1, 13);
173 	r_anal_bb_set_offset (first, 2, 16);
174 
175 	second->ninstr = 4;
176 	r_anal_bb_set_offset (second, 0, 0);
177 	r_anal_bb_set_offset (second, 1, 4);
178 	r_anal_bb_set_offset (second, 2, 9);
179 	r_anal_bb_set_offset (second, 3, 30);
180 
181 	bool success = r_anal_block_merge (first, second);
182 	assert_invariants (anal);
183 	mu_assert ("merge success", success);
184 	mu_assert_eq (blocks_count (anal), 1, "count after merge");
185 	mu_assert_eq (first->addr, 0x1337, "addr after merge");
186 	mu_assert_eq (first->size, 666, "size after merge");
187 	mu_assert_eq (first->jump, 0xdeadbeef, "jump after merge");
188 	mu_assert_eq (first->fail, 0xc0ffee, "fail after merge");
189 
190 	mu_assert_eq (first->ninstr, 3+4, "ninstr after merge");
191 	mu_assert_eq (r_anal_bb_offset_inst (first, 0), 0, "offset 0 after merge");
192 	mu_assert_eq (r_anal_bb_offset_inst (first, 1), 13, "offset 1 after merge");
193 	mu_assert_eq (r_anal_bb_offset_inst (first, 2), 16, "offset 2 after merge");
194 	mu_assert_eq (r_anal_bb_offset_inst (first, 3), 42+0, "offset 3 after merge");
195 	mu_assert_eq (r_anal_bb_offset_inst (first, 4), 42+4, "offset 4 after merge");
196 	mu_assert_eq (r_anal_bb_offset_inst (first, 5), 42+9, "offset 5 after merge");
197 	mu_assert_eq (r_anal_bb_offset_inst (first, 6), 42+30, "offset 6 after merge");
198 
199 	r_anal_block_unref (first);
200 	// second must be already freed by the merge!
201 
202 	assert_invariants (anal);
203 	r_anal_free (anal);
204 	mu_end;
205 }
206 
test_r_anal_block_merge_in_function()207 bool test_r_anal_block_merge_in_function() {
208 	RAnal *anal = r_anal_new ();
209 	assert_invariants (anal);
210 
211 	RAnalFunction *fcn = r_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
212 
213 	RAnalBlock *first = r_anal_create_block (anal, 0x1337, 42);
214 	RAnalBlock *second = r_anal_create_block (anal, 0x1337 + 42, 624);
215 	assert_invariants (anal);
216 	mu_assert_eq (blocks_count (anal), 2, "count after create");
217 
218 	r_anal_function_add_block (fcn, first);
219 	assert_invariants (anal);
220 	r_anal_function_add_block (fcn, second);
221 	assert_invariants (anal);
222 
223 	bool success = r_anal_block_merge (first, second);
224 	assert_invariants (anal);
225 	mu_assert ("merge success", success);
226 	mu_assert_eq (blocks_count (anal), 1, "count after merge");
227 	mu_assert_eq (r_list_length (fcn->bbs), 1, "fcn bbs after merge");
228 	mu_assert_eq (r_list_length (first->fcns), 1, "bb functions after merge");
229 	mu_assert ("function has merged block", r_list_contains (fcn->bbs, first));
230 	mu_assert ("merged block is in function", r_list_contains (first->fcns, fcn));
231 
232 	r_anal_block_unref (first);
233 	// second must be already freed by the merge!
234 
235 	assert_invariants (anal);
236 	r_anal_free (anal);
237 	mu_end;
238 }
239 
test_r_anal_block_delete()240 bool test_r_anal_block_delete() {
241 	RAnal *anal = r_anal_new ();
242 	assert_invariants (anal);
243 
244 	RAnalFunction *fcn = r_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
245 
246 	RAnalBlock *block = r_anal_create_block (anal, 0x1337, 42);
247 	assert_invariants (anal);
248 	mu_assert_eq (blocks_count (anal), 1, "count after create");
249 
250 	r_anal_function_add_block (fcn, block);
251 	assert_invariants (anal);
252 	mu_assert_eq (block->ref, 2, "refs after adding");
253 	mu_assert_eq (r_list_length (fcn->bbs), 1, "fcn bbs after add");
254 	mu_assert_eq (r_list_length (block->fcns), 1, "bb fcns after add");
255 
256 	r_anal_delete_block (block);
257 	assert_invariants (anal);
258 	mu_assert_eq (block->ref, 1, "refs after delete");
259 	mu_assert_eq (r_list_length (fcn->bbs), 0, "fcn bbs after delete");
260 	mu_assert_eq (r_list_length (block->fcns), 0, "bb fcns after delete");
261 
262 	r_anal_block_unref (block);
263 
264 	r_anal_free (anal);
265 	mu_end;
266 }
267 
test_r_anal_block_set_size()268 bool test_r_anal_block_set_size() {
269 	RAnal *anal = r_anal_new ();
270 	assert_invariants (anal);
271 
272 	RAnalFunction *fcn = r_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
273 
274 	RAnalBlock *block = r_anal_create_block (anal, 0x1337, 42);
275 	assert_invariants (anal);
276 
277 	r_anal_function_add_block (fcn, block);
278 	assert_invariants (anal);
279 
280 	r_anal_block_set_size (block, 300);
281 	assert_invariants (anal);
282 	mu_assert_eq (block->size, 300, "size after set_size");
283 
284 	RAnalBlock *second = r_anal_create_block (anal, 0x1337+300, 100);
285 	assert_invariants (anal);
286 	r_anal_function_add_block (fcn, block);
287 	assert_invariants (anal);
288 	r_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
289 	assert_invariants (anal);
290 
291 	r_anal_block_set_size (second, 500);
292 	assert_invariants (anal);
293 	mu_assert_eq (second->size, 500, "size after set_size");
294 
295 	r_anal_block_set_size (block, 80);
296 	assert_invariants (anal);
297 	mu_assert_eq (block->size, 80, "size after set_size");
298 
299 	r_anal_block_unref (block);
300 	r_anal_block_unref (second);
301 	assert_invariants (anal);
302 
303 	r_anal_free (anal);
304 	mu_end;
305 }
306 
test_r_anal_block_relocate()307 bool test_r_anal_block_relocate() {
308 	RAnal *anal = r_anal_new ();
309 	assert_invariants (anal);
310 
311 	RAnalFunction *fcn = r_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
312 
313 	RAnalBlock *block = r_anal_create_block (anal, 0x1337, 42);
314 	assert_invariants (anal);
315 
316 	r_anal_function_add_block (fcn, block);
317 	assert_invariants (anal);
318 	r_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
319 	assert_invariants (anal);
320 
321 	bool success = r_anal_block_relocate (block, 0x200, 0x100);
322 	mu_assert ("relocate success", success);
323 	assert_invariants (anal);
324 	mu_assert_eq (block->addr, 0x200, "addr after relocate");
325 	mu_assert_eq (block->size, 0x100, "size after relocate");
326 
327 	RAnalBlock *second = r_anal_create_block (anal, 0x1337+300, 100);
328 	assert_invariants (anal);
329 	r_anal_function_add_block (fcn, second);
330 	assert_invariants (anal);
331 
332 	success = r_anal_block_relocate (second, 0x400, 0x123);
333 	mu_assert ("relocate success", success);
334 	assert_invariants (anal);
335 	mu_assert_eq (second->addr, 0x400, "addr after relocate");
336 	mu_assert_eq (second->size, 0x123, "size after relocate");
337 	r_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
338 	assert_invariants (anal);
339 
340 	success = r_anal_block_relocate (block, 0x400, 0x333);
341 	mu_assert ("relocate fail on same addr", !success);
342 	assert_invariants (anal);
343 	mu_assert_eq (block->addr, 0x200, "addr after failed relocate");
344 	mu_assert_eq (block->size, 0x100, "size after failed relocate");
345 	r_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
346 	assert_invariants (anal);
347 
348 	// jump after the other block
349 	success = r_anal_block_relocate (block, 0x500, 0x333);
350 	mu_assert ("relocate success", success);
351 	assert_invariants (anal);
352 	mu_assert_eq (block->addr, 0x500, "addr after failed relocate");
353 	mu_assert_eq (block->size, 0x333, "size after failed relocate");
354 	r_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
355 	assert_invariants (anal);
356 
357 	// jump before the other block
358 	success = r_anal_block_relocate (block, 0x10, 0x333);
359 	mu_assert ("relocate success", success);
360 	assert_invariants (anal);
361 	mu_assert_eq (block->addr, 0x10, "addr after failed relocate");
362 	mu_assert_eq (block->size, 0x333, "size after failed relocate");
363 
364 	r_anal_block_unref (block);
365 	r_anal_block_unref (second);
366 	assert_invariants (anal);
367 
368 	r_anal_free (anal);
369 	mu_end;
370 }
371 
test_r_anal_block_query()372 bool test_r_anal_block_query() {
373 	RAnal *anal = r_anal_new ();
374 	assert_invariants (anal);
375 
376 #define N 200
377 #define MAXSIZE 0x300
378 #define SPACE 0x10000
379 #define SAMPLES 300
380 
381 	RAnalBlock *blocks[N];
382 	size_t i;
383 	for (i = 0; i < N; i++) {
384 		blocks[i] = r_anal_create_block (anal, rand () % SPACE, rand () % MAXSIZE); // may return null on duplicates
385 		assert_invariants (anal);
386 	}
387 
388 	// --
389 	// test r_anal_get_block_at()
390 
391 	for (i = 0; i < N; i++) {
392 		if (!blocks[i]) {
393 			continue;
394 		}
395 		mu_assert_ptreq (r_anal_get_block_at (anal, blocks[i]->addr), blocks[i], "r_anal_get_block_at");
396 	}
397 
398 	for (i = 0; i < SAMPLES; i++) {
399 		ut64 addr = rand () % SPACE;
400 		size_t j;
401 
402 		// goal is to check cases where r_anal_get_block_at() returns null,
403 		// but since the addr is random, there may be a block sometimes too.
404 		RAnalBlock *block = NULL;
405 		for (j = 0; j < N; j++) {
406 			if (!blocks[j]) {
407 				continue;
408 			}
409 			if (blocks[j]->addr == addr) {
410 				block = blocks[j];
411 				break;
412 			}
413 		}
414 
415 		mu_assert_ptreq (r_anal_get_block_at (anal, addr), block, "r_anal_get_block_at");
416 	}
417 
418 	// --
419 	// test r_anal_get_blocks_in()
420 
421 	for (i = 0; i < SAMPLES; i++) {
422 		ut64 addr = rand () % SPACE;
423 		RList *in = r_anal_get_blocks_in (anal, addr);
424 
425 		RAnalBlock *block;
426 		RListIter *it;
427 		r_list_foreach (in, it, block) {
428 			mu_assert_eq (block->ref, 2, "block refd in returned list");
429 		}
430 
431 		size_t linear_found = 0;
432 		size_t j;
433 		for (j = 0; j < N; j++) {
434 			if (!blocks[j]) {
435 				continue;
436 			}
437 			if (r_anal_block_contains (blocks[j], addr)) {
438 				linear_found++;
439 				mu_assert ("intersect linear found in list", r_list_contains (in, blocks[j]));
440 			}
441 		}
442 		mu_assert_eq ((size_t)r_list_length (in), linear_found, "r_anal_get_blocks_in count");
443 		r_list_free (in);
444 	}
445 
446 	// --
447 	// test r_anal_get_blocks_intersect()
448 
449 	for (i = 0; i < SAMPLES; i++) {
450 		ut64 addr = rand () % SPACE;
451 		ut64 size = rand() % MAXSIZE;
452 		RList *in = r_anal_get_blocks_intersect (anal, addr, size);
453 
454 		RAnalBlock *block;
455 		RListIter *it;
456 		r_list_foreach (in, it, block) {
457 			mu_assert_eq (block->ref, 2, "block refd in returned list");
458 		}
459 
460 		size_t linear_found = 0;
461 		size_t j;
462 		for (j = 0; j < N; j++) {
463 			RAnalBlock *block = blocks[j];
464 			if (!block || addr + size <= block->addr || addr >= block->addr + block->size) {
465 				continue;
466 			}
467 			linear_found++;
468 			mu_assert ("in linear found in list", r_list_contains (in, blocks[j]));
469 		}
470 		mu_assert_eq ((size_t)r_list_length (in), linear_found, "r_anal_get_blocks_intersect count");
471 		r_list_free (in);
472 	}
473 
474 	for (i = 0; i < N; i++) {
475 		r_anal_block_unref (blocks[i]);
476 	}
477 
478 	assert_leaks (anal);
479 	r_anal_free (anal);
480 	mu_end;
481 }
482 
addr_list_cb(ut64 addr,void * user)483 bool addr_list_cb(ut64 addr, void *user) {
484 	RList *list = user;
485 	r_list_push (list, (void *)addr);
486 	return true;
487 }
488 
test_r_anal_block_successors()489 bool test_r_anal_block_successors() {
490 	RAnal *anal = r_anal_new ();
491 	assert_invariants (anal);
492 
493 	RAnalBlock *blocks[10];
494 	blocks[0] = r_anal_create_block (anal, 0x10, 0x10);
495 	blocks[1] = r_anal_create_block (anal, 0x30, 0x10);
496 	blocks[2] = r_anal_create_block (anal, 0x50, 0x10);
497 	blocks[3] = r_anal_create_block (anal, 0x100, 0x10);
498 	blocks[4] = r_anal_create_block (anal, 0x110, 0x10);
499 	blocks[5] = r_anal_create_block (anal, 0x120, 0x10);
500 	blocks[6] = r_anal_create_block (anal, 0x130, 0x10);
501 	blocks[7] = r_anal_create_block (anal, 0x140, 0x10);
502 	blocks[8] = r_anal_create_block (anal, 0xa0, 0x10);
503 	blocks[9] = r_anal_create_block (anal, 0xc0, 0x10);
504 	assert_invariants (anal);
505 
506 	blocks[0]->jump = 0x30;
507 	blocks[0]->fail = 0x50;
508 	blocks[1]->jump = 0x10;
509 	blocks[1]->fail = 0x50;
510 	blocks[2]->jump = 0x10;
511 
512 	RAnalSwitchOp *sop = r_anal_switch_op_new (0x55, 0x13, 0x15, 0x42);
513 	mu_assert_eq (sop->addr, 0x55, "addr");
514 	mu_assert_eq (sop->min_val, 0x13, "addr");
515 	mu_assert_eq (sop->max_val, 0x15, "addr");
516 	mu_assert_eq (sop->def_val, 0x42, "addr");
517 	r_anal_switch_op_add_case (sop, 0x55, 1, 0x100);
518 	r_anal_switch_op_add_case (sop, 0x55, 2, 0x110);
519 	r_anal_switch_op_add_case (sop, 0x55, 3, 0x120);
520 	r_anal_switch_op_add_case (sop, 0x55, 4, 0x130);
521 	r_anal_switch_op_add_case (sop, 0x55, 5, 0x140);
522 	blocks[2]->switch_op = sop;
523 
524 	RList *result = r_list_new ();
525 	r_anal_block_successor_addrs_foreach (blocks[0], addr_list_cb, result);
526 	mu_assert_eq (r_list_length (result), 2, "jump/fail successors count");
527 	mu_assert ("jmp successor", r_list_contains (result, (void *)0x30));
528 	mu_assert ("fail successor", r_list_contains (result, (void *)0x50));
529 	r_list_purge (result);
530 
531 	r_anal_block_successor_addrs_foreach (blocks[2], addr_list_cb, result);
532 	mu_assert_eq (r_list_length (result), 6, "switch successors count");
533 	mu_assert ("jmp successor", r_list_contains (result, (void *)0x10));
534 	mu_assert ("case successor", r_list_contains (result, (void *)0x100));
535 	mu_assert ("case successor", r_list_contains (result, (void *)0x110));
536 	mu_assert ("case successor", r_list_contains (result, (void *)0x120));
537 	mu_assert ("case successor", r_list_contains (result, (void *)0x130));
538 	mu_assert ("case successor", r_list_contains (result, (void *)0x140));
539 	r_list_free (result);
540 
541 	result = r_anal_block_recurse_list (blocks[0]);
542 	RAnalBlock *block;
543 	RListIter *it;
544 	r_list_foreach (result, it, block) {
545 		mu_assert_eq (block->ref, 2, "block refd in returned list");
546 	}
547 
548 	mu_assert_eq (r_list_length (result), 8, "recursive successors count");
549 	mu_assert ("recursive successor", r_list_contains (result, blocks[0]));
550 	mu_assert ("recursive successor", r_list_contains (result, blocks[1]));
551 	mu_assert ("recursive successor", r_list_contains (result, blocks[2]));
552 	mu_assert ("recursive successor", r_list_contains (result, blocks[3]));
553 	mu_assert ("recursive successor", r_list_contains (result, blocks[4]));
554 	mu_assert ("recursive successor", r_list_contains (result, blocks[5]));
555 	mu_assert ("recursive successor", r_list_contains (result, blocks[6]));
556 	mu_assert ("recursive successor", r_list_contains (result, blocks[7]));
557 
558 	r_list_free (result);
559 
560 	size_t i;
561 	for (i = 0; i < sizeof (blocks) / sizeof (RAnalBlock *); i++) {
562 		r_anal_block_unref (blocks[i]);
563 	}
564 
565 	assert_leaks (anal);
566 	r_anal_free (anal);
567 	mu_end;
568 }
569 
test_r_anal_block_automerge()570 bool test_r_anal_block_automerge() {
571 	size_t i;
572 	for (i = 0; i < SAMPLES; i++) {
573 		RAnal *anal = r_anal_new ();
574 		assert_invariants (anal);
575 
576 		RAnalBlock *a = r_anal_create_block (anal, 0x100, 0x10);
577 
578 		RAnalBlock *b = r_anal_create_block (anal, 0x110, 0x10);
579 		a->jump = b->addr;
580 
581 		RAnalBlock *c = r_anal_create_block (anal, 0x120, 0x10);
582 		b->jump = c->addr;
583 		c->fail = b->addr;
584 
585 		RAnalBlock *d = r_anal_create_block (anal, 0x130, 0x10);
586 		c->jump = d->addr;
587 
588 		RAnalBlock *e = r_anal_create_block (anal, 0x140, 0x10);
589 		d->jump = e->addr;
590 
591 		RAnalBlock *f = r_anal_create_block (anal, 0x150, 0x10);
592 		e->jump = f->addr;
593 
594 		RAnalFunction *fa = r_anal_create_function (anal, "fcn", 0x100, R_ANAL_FCN_TYPE_FCN, NULL);
595 		r_anal_function_add_block (fa, a);
596 		r_anal_function_add_block (fa, c);
597 		r_anal_function_add_block (fa, d);
598 		r_anal_function_add_block (fa, e);
599 		r_anal_function_add_block (fa, f);
600 
601 		RAnalFunction *fb = r_anal_create_function (anal, "fcn2", 0x110, R_ANAL_FCN_TYPE_FCN, NULL);
602 		r_anal_function_add_block (fb, b);
603 		r_anal_function_add_block (fb, c);
604 		r_anal_function_add_block (fb, d);
605 		r_anal_function_add_block (fb, e);
606 		r_anal_function_add_block (fb, f);
607 
608 		RList *all_blocks = r_list_new ();
609 		r_list_push (all_blocks, a);
610 		r_list_push (all_blocks, b);
611 		r_list_push (all_blocks, c);
612 		r_list_push (all_blocks, d);
613 		r_list_push (all_blocks, e);
614 		r_list_push (all_blocks, f);
615 
616 		// Randomize the order in which we give the automerge the block.
617 		// The outcome should always be the same but it can have some delicate implications on the algorithm inside.
618 		RList *shuffled_blocks = r_list_newf ((RListFree)r_anal_block_unref);
619 		while (!r_list_empty (all_blocks)) {
620 			int n = rand () % r_list_length (all_blocks);
621 			r_list_push (shuffled_blocks, r_list_get_n (all_blocks, n));
622 			r_list_del_n (all_blocks, n);
623 		}
624 		r_list_free (all_blocks);
625 
626 		r_anal_block_automerge (shuffled_blocks);
627 		assert_invariants (anal);
628 		//mu_assert_eq (r_list_length (shuffled_blocks), 4, "length after automerge");
629 		mu_assert ("remaining blocks a", r_list_contains (shuffled_blocks, a));
630 		mu_assert ("remaining blocks b", r_list_contains (shuffled_blocks, b));
631 		mu_assert ("remaining blocks c", r_list_contains (shuffled_blocks, c));
632 		mu_assert ("remaining blocks d", r_list_contains (shuffled_blocks, d));
633 		mu_assert_eq (blocks_count (anal), r_list_length (shuffled_blocks), "blocks in anal count");
634 		RListIter *it;
635 		RAnalBlock *block;
636 		r_list_foreach (shuffled_blocks, it, block) {
637 			mu_assert_ptreq (r_anal_get_block_at (anal, block->addr), block, "remaining blocks in anal");
638 		}
639 		r_list_free (shuffled_blocks);
640 
641 		assert_invariants (anal);
642 		assert_leaks (anal);
643 		r_anal_free (anal);
644 	}
645 	mu_end;
646 }
647 
test_r_anal_block_chop_noreturn(void)648 bool test_r_anal_block_chop_noreturn(void) {
649 	RAnal *anal = r_anal_new ();
650 	assert_invariants (anal);
651 
652 	RAnalBlock *a = r_anal_create_block (anal, 0x100, 0x10);
653 	RAnalBlock *b = r_anal_create_block (anal, 0x110, 0x10);
654 	RAnalBlock *c = r_anal_create_block (anal, 0x120, 0x10);
655 	a->jump = c->addr;
656 	b->jump = c->addr;
657 
658 	RAnalFunction *fa = r_anal_create_function (anal, "fcn", 0x100, R_ANAL_FCN_TYPE_FCN, NULL);
659 	r_anal_function_add_block (fa, a);
660 	r_anal_function_add_block (fa, b);
661 	r_anal_function_add_block (fa, c);
662 
663 	RAnalFunction *fb = r_anal_create_function (anal, "fcn2", 0x130, R_ANAL_FCN_TYPE_FCN, NULL);
664 	fb->is_noreturn = true;
665 
666 	r_anal_block_chop_noreturn (b, 0x111);
667 
668 	assert_invariants (anal);
669 	r_anal_free (anal);
670 
671 	mu_end;
672 }
673 
all_tests()674 int all_tests() {
675 	mu_run_test (test_r_anal_block_chop_noreturn);
676 	mu_run_test (test_r_anal_block_create);
677 	mu_run_test (test_r_anal_block_contains);
678 	mu_run_test (test_r_anal_block_split);
679 	mu_run_test (test_r_anal_block_split_in_function);
680 	mu_run_test (test_r_anal_block_merge);
681 	mu_run_test (test_r_anal_block_merge_in_function);
682 	mu_run_test (test_r_anal_block_delete);
683 	mu_run_test (test_r_anal_block_set_size);
684 	mu_run_test (test_r_anal_block_relocate);
685 	mu_run_test (test_r_anal_block_query);
686 	mu_run_test (test_r_anal_block_successors);
687 	mu_run_test (test_r_anal_block_automerge);
688 	return tests_passed != tests_run;
689 }
690 
main(int argc,char ** argv)691 int main(int argc, char **argv) {
692 	struct timeval tv;
693 	gettimeofday (&tv, NULL);
694 	unsigned int seed = argc > 1 ? strtoul (argv[1], NULL, 0) : tv.tv_sec + tv.tv_usec;
695 	printf("seed for test_anal_block: %u\n", seed);
696 	return all_tests();
697 }
698