rizin/test/unit/test_analysis_block_invars.inl
Giovanni b5fee3471c
Move RzAnalysis as private and force usage of C API (#6123)
* Hide RzAnalysis structure to force the usage of the C APIs.

* Fix rop code & test

* Fix linter

* Fix rz_analysis_free to return void
2026-04-06 16:07:53 +00:00

76 lines
2.7 KiB
C++

// SPDX-FileCopyrightText: 2020 Florian Märkl <info@florianmaerkl.de>
// SPDX-License-Identifier: LGPL-3.0-only
static bool block_check_invariants(RzAnalysis *analysis) {
RzListIter *fcniter;
RzAnalysisFunction *fcn;
RBIter iter;
RzAnalysisBlock *block;
ut64 last_start = UT64_MAX;
RBTree *bb_tree = rz_analysis_get_bb_tree(analysis);
rz_rbtree_foreach ((*bb_tree), iter, block, RzAnalysisBlock, _rb) {
if (last_start != UT64_MAX) {
mu_assert ("corrupted binary tree", block->addr >= last_start);
mu_assert_neq (block->addr, last_start, "double blocks");
}
last_start = block->addr;
mu_assert ("block->ref < 1, but it is still in the tree", block->ref >= 1);
mu_assert ("block->ref < rz_list_length (block->fcns)", block->ref >= rz_list_length (block->fcns));
rz_list_foreach (block->fcns, fcniter, fcn) {
RzListIter *fcniter2;
RzAnalysisFunction *fcn2;
rz_list_foreach_iter(rz_list_next(fcniter), fcniter2, fcn2) {
mu_assert_ptrneq (fcn, fcn2, "duplicate function in basic block");
}
mu_assert ("block references function, but function does not reference block", rz_pvector_contains(fcn->bbs, block));
}
}
RzList *fcns = rz_analysis_function_list(analysis);
rz_list_foreach (fcns, fcniter, fcn) {
ut64 min = UT64_MAX;
ut64 max = UT64_MIN;
ut64 realsz = 0;
size_t count = rz_pvector_len(fcn->bbs);
for (size_t i = 0; i < count; ++i) {
block = (RzAnalysisBlock *)rz_pvector_at(fcn->bbs, i);
if (block->addr < min) {
min = block->addr;
}
if (block->addr + block->size > max) {
max = block->addr + block->size;
}
realsz += block->size;
for (size_t j = i + 1; j < count; ++j) {
RzAnalysisBlock *block2 = (RzAnalysisBlock *)rz_pvector_at(fcn->bbs, j);
mu_assert_ptrneq (block, block2, "duplicate basic block in function");
}
mu_assert ("function references block, but block does not reference function", rz_list_contains (block->fcns, fcn));
}
if (fcn->meta._min != UT64_MAX) {
mu_assert_eq (fcn->meta._min, min, "function min wrong");
mu_assert_eq (fcn->meta._max, max, "function max wrong");
}
mu_assert_eq (rz_analysis_function_realsize (fcn), realsz, "realsize wrong");
}
return true;
}
static bool block_check_leaks(RzAnalysis *analysis) {
RBIter iter;
RzAnalysisBlock *block;
RBTree *bb_tree = rz_analysis_get_bb_tree(analysis);
rz_rbtree_foreach ((*bb_tree), iter, block, RzAnalysisBlock, _rb) {
if (block->ref != rz_list_length (block->fcns)) {
mu_assert ("leaked basic block", false);
}
}
return true;
}
#define assert_block_invariants(analysis) do { if (!block_check_invariants (analysis)) { return false; } } while (0)
#define assert_block_leaks(analysis) do { if (!block_check_leaks (analysis)) { return false; } } while (0)