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