rizin/test/unit/test_analysis_hints.c

356 lines
11 KiB
C

// SPDX-FileCopyrightText: 2020 Florian Märkl <info@florianmaerkl.de>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_analysis.h>
#include "minunit.h"
const RzAnalysisHint empty_hint = {
.addr = UT64_MAX,
.ptr = 0,
.val = UT64_MAX,
.jump = UT64_MAX,
.fail = UT64_MAX,
.ret = UT64_MAX,
.arch = 0,
.opcode = NULL,
.syntax = NULL,
.esil = NULL,
.offset = NULL,
.type = 0,
.size = 0,
.bits = 0,
.new_bits = 0,
.immbase = 0,
.high = 0,
.nword = 0,
.stackframe = UT64_MAX,
.enum_name = NULL,
};
bool hint_equals(const RzAnalysisHint *a, const RzAnalysisHint *b) {
#define CHECK_EQ(member) mu_assert_eq(a->member, b->member, "hint member " #member)
CHECK_EQ(ptr);
CHECK_EQ(val);
CHECK_EQ(jump);
CHECK_EQ(fail);
CHECK_EQ(ret);
CHECK_EQ(type);
CHECK_EQ(size);
CHECK_EQ(bits);
CHECK_EQ(new_bits);
CHECK_EQ(immbase);
CHECK_EQ(high);
CHECK_EQ(nword);
CHECK_EQ(stackframe);
#undef CHECK_EQ
#define CHECK_STREQ(member) mu_assert_nullable_streq(a->member, b->member, "hint member " #member)
CHECK_STREQ(arch);
CHECK_STREQ(opcode);
CHECK_STREQ(syntax);
CHECK_STREQ(esil);
CHECK_STREQ(offset);
CHECK_STREQ(enum_name);
#undef CHECK_STREQ
return true;
}
#define assert_hint_eq(actual, expected) \
do { \
if (actual == NULL) \
mu_assert("hint", expected == &empty_hint); /* TODO: remove this part, only else should be used! */ \
else \
mu_assert("hint", hint_equals(actual, expected)); \
} while (0)
bool test_rz_analysis_addr_hints() {
RzAnalysis *analysis = rz_analysis_new(NULL);
RzAnalysisHint *hint = rz_analysis_hint_get(analysis, 0x1337);
assert_hint_eq(hint, &empty_hint);
rz_analysis_hint_free(hint);
RzAnalysisHint cur = empty_hint;
#define CHECK \
hint = rz_analysis_hint_get(analysis, 0x1337); \
assert_hint_eq(hint, &cur); \
rz_analysis_hint_free(hint);
hint = rz_analysis_hint_get(analysis, 0x1338);
assert_hint_eq(hint, &empty_hint);
rz_analysis_hint_free(hint);
hint = rz_analysis_hint_get(analysis, 0x1336);
assert_hint_eq(hint, &empty_hint);
rz_analysis_hint_free(hint);
// set --------
rz_analysis_hint_set_syntax(analysis, 0x1337, "mysyntax");
cur.syntax = "mysyntax";
CHECK
rz_analysis_hint_set_type(analysis, 0x1337, RZ_ANALYSIS_OP_TYPE_RET);
cur.type = RZ_ANALYSIS_OP_TYPE_RET;
CHECK
rz_analysis_hint_set_jump(analysis, 0x1337, 0xdeadbeef);
cur.jump = 0xdeadbeef;
CHECK
rz_analysis_hint_set_fail(analysis, 0x1337, 0xc0ffee);
cur.fail = 0xc0ffee;
CHECK
rz_analysis_hint_set_nword(analysis, 0x1337, 42);
cur.nword = 42;
CHECK
rz_analysis_hint_set_offset(analysis, 0x1337, "mytypeoff");
cur.offset = "mytypeoff";
CHECK
rz_analysis_hint_set_immbase(analysis, 0x1337, 7);
cur.immbase = 7;
CHECK
rz_analysis_hint_set_enum(analysis, 0x1337, "BLA");
cur.enum_name = "BLA";
CHECK
rz_analysis_hint_set_size(analysis, 0x1337, 0x123);
cur.size = 0x123;
CHECK
rz_analysis_hint_set_opcode(analysis, 0x1337, "myopcode");
cur.opcode = "myopcode";
CHECK
rz_analysis_hint_set_esil(analysis, 0x1337, "/,-rf,rm");
cur.esil = "/,-rf,rm";
CHECK
rz_analysis_hint_set_pointer(analysis, 0x1337, 0x4242);
cur.ptr = 0x4242;
CHECK
rz_analysis_hint_set_ret(analysis, 0x1337, 0xf00d);
cur.ret = 0xf00d;
CHECK
rz_analysis_hint_set_high(analysis, 0x1337);
cur.high = true;
CHECK
rz_analysis_hint_set_stackframe(analysis, 0x1337, 0x4321);
cur.stackframe = 0x4321;
CHECK
rz_analysis_hint_set_val(analysis, 0x1337, 0x112358d);
cur.val = 0x112358d;
CHECK
rz_analysis_hint_set_newbits(analysis, 0x1337, 16);
cur.new_bits = 16;
CHECK
// unset --------
rz_analysis_hint_unset_syntax(analysis, 0x1337);
cur.syntax = NULL;
CHECK
rz_analysis_hint_unset_type(analysis, 0x1337);
cur.type = 0;
CHECK
rz_analysis_hint_unset_jump(analysis, 0x1337);
cur.jump = UT64_MAX;
CHECK
rz_analysis_hint_unset_fail(analysis, 0x1337);
cur.fail = UT64_MAX;
CHECK
rz_analysis_hint_unset_nword(analysis, 0x1337);
cur.nword = 0;
CHECK
rz_analysis_hint_unset_offset(analysis, 0x1337);
cur.offset = NULL;
CHECK
rz_analysis_hint_unset_immbase(analysis, 0x1337);
cur.immbase = 0;
CHECK
rz_analysis_hint_unset_enum(analysis, 0x1337);
cur.enum_name = NULL;
CHECK
rz_analysis_hint_unset_size(analysis, 0x1337);
cur.size = 0;
CHECK
rz_analysis_hint_unset_opcode(analysis, 0x1337);
cur.opcode = NULL;
CHECK
rz_analysis_hint_unset_esil(analysis, 0x1337);
cur.esil = NULL;
CHECK
rz_analysis_hint_unset_pointer(analysis, 0x1337);
cur.ptr = 0;
CHECK
rz_analysis_hint_unset_ret(analysis, 0x1337);
cur.ret = UT64_MAX;
CHECK
rz_analysis_hint_unset_high(analysis, 0x1337);
cur.high = false;
CHECK
rz_analysis_hint_unset_stackframe(analysis, 0x1337);
cur.stackframe = UT64_MAX;
CHECK
rz_analysis_hint_unset_val(analysis, 0x1337);
cur.val = UT64_MAX;
CHECK
rz_analysis_hint_unset_newbits(analysis, 0x1337);
cur.new_bits = 0;
// CHECK
hint = rz_analysis_hint_get(analysis, 0x1337);
assert_hint_eq(hint, &empty_hint);
rz_analysis_hint_free(hint);
rz_analysis_free(analysis);
mu_end;
#undef CHECK
}
#define RANGED_TEST(name, val, resetval, assert_val) \
bool test_rz_analysis_hints_##name() { \
RzAnalysis *analysis = rz_analysis_new(NULL); \
\
ut64 hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0x1337, &hint_addr), resetval, "no " #name ""); \
mu_assert_eq(hint_addr, UT64_MAX, "hint addr"); \
\
rz_analysis_hint_##name##_at(analysis, 0x1337, NULL); /* make sure this does not null-deref */ \
\
/* -- */ \
rz_analysis_hint_set_##name(analysis, 0x1337, val); \
\
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0x1337, &hint_addr), val, #name " at addr"); \
mu_assert_eq(hint_addr, 0x1337, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0x1338, &hint_addr), val, #name " after addr"); \
mu_assert_eq(hint_addr, 0x1337, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, UT64_MAX, &hint_addr), val, #name " after addr"); \
mu_assert_eq(hint_addr, 0x1337, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0x1336, &hint_addr), resetval, "no " #name " before addr"); \
mu_assert_eq(hint_addr, UT64_MAX, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0, &hint_addr), resetval, "no " #name " before addr"); \
mu_assert_eq(hint_addr, UT64_MAX, "hint addr"); \
\
rz_analysis_hint_##name##_at(analysis, 0x1337, NULL); /* make sure this does not null-deref */ \
\
RzAnalysisHint cur = empty_hint; \
cur.name = val; \
RzAnalysisHint *hint = rz_analysis_hint_get(analysis, 0x1337); \
assert_hint_eq(hint, &cur); \
rz_analysis_hint_free(hint); \
hint = rz_analysis_hint_get(analysis, 0x1338); \
assert_hint_eq(hint, &cur); \
rz_analysis_hint_free(hint); \
hint = rz_analysis_hint_get(analysis, 0x1336); \
assert_hint_eq(hint, &empty_hint); \
rz_analysis_hint_free(hint); \
\
/* -- */ \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0xdeadbeef, &hint_addr), val, "before reset " #name " at addr"); \
mu_assert_eq(hint_addr, 0x1337, "hint addr"); \
rz_analysis_hint_set_##name(analysis, 0xdeadbeef, resetval); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0xdeadbeef, &hint_addr), resetval, "reset " #name " at addr"); \
mu_assert_eq(hint_addr, 0xdeadbeef, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0xdeadbeef + 1, &hint_addr), resetval, "reset " #name " after addr"); \
mu_assert_eq(hint_addr, 0xdeadbeef, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, UT64_MAX, &hint_addr), resetval, "reset " #name " after addr"); \
mu_assert_eq(hint_addr, 0xdeadbeef, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0xdeadbeef - 1, &hint_addr), val, "" #name " before addr"); \
mu_assert_eq(hint_addr, 0x1337, "hint addr"); \
\
/* -- */ \
rz_analysis_hint_unset_##name(analysis, 0xdeadbeef); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0x1337, &hint_addr), val, #name " at addr"); \
mu_assert_eq(hint_addr, 0x1337, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0x1338, &hint_addr), val, #name " after addr"); \
mu_assert_eq(hint_addr, 0x1337, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, UT64_MAX, &hint_addr), val, #name " after addr"); \
mu_assert_eq(hint_addr, 0x1337, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0x1336, &hint_addr), resetval, "no " #name " before addr"); \
mu_assert_eq(hint_addr, UT64_MAX, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0, &hint_addr), resetval, "no " #name " before addr"); \
mu_assert_eq(hint_addr, UT64_MAX, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0xdeadbeef, &hint_addr), val, "unset reset " #name " at addr"); \
mu_assert_eq(hint_addr, 0x1337, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0xdeadbeef + 1, &hint_addr), val, "unset reset " #name " after addr"); \
mu_assert_eq(hint_addr, 0x1337, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, UT64_MAX, &hint_addr), val, "unset reset " #name " after addr"); \
mu_assert_eq(hint_addr, 0x1337, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0xdeadbeef - 1, &hint_addr), val, #name " before addr"); \
mu_assert_eq(hint_addr, 0x1337, "hint addr"); \
\
/* -- */ \
rz_analysis_hint_unset_##name(analysis, 0x1337); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0x1336, &hint_addr), resetval, "unset " #name ""); \
mu_assert_eq(hint_addr, UT64_MAX, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0, &hint_addr), resetval, "unset " #name ""); \
mu_assert_eq(hint_addr, UT64_MAX, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0x1337, &hint_addr), resetval, "unset " #name ""); \
mu_assert_eq(hint_addr, UT64_MAX, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, 0x1338, &hint_addr), resetval, "unset " #name ""); \
mu_assert_eq(hint_addr, UT64_MAX, "hint addr"); \
hint_addr = 0xdead; \
assert_val(rz_analysis_hint_##name##_at(analysis, UT64_MAX, &hint_addr), resetval, "unset " #name ""); \
mu_assert_eq(hint_addr, UT64_MAX, "hint addr"); \
hint_addr = 0xdead; \
\
rz_analysis_free(analysis); \
mu_end; \
}
RANGED_TEST(arch, "6502", NULL, mu_assert_nullable_streq)
RANGED_TEST(bits, 16, 0, mu_assert_eq)
bool all_tests() {
mu_run_test(test_rz_analysis_addr_hints);
mu_run_test(test_rz_analysis_hints_arch);
mu_run_test(test_rz_analysis_hints_bits);
return tests_passed != tests_run;
}
mu_main(all_tests)