// SPDX-FileCopyrightText: 2021 heersin // SPDX-License-Identifier: LGPL-3.0-only #include #include #include "minunit.h" static bool is_equal_bool(RzILBool *x, RzILBool *y) { return x->b == y->b; } bool test_il_bool_init(void) { RzILBool *b = rz_il_bool_new(true); mu_assert_notnull(b, "New RzILBool"); mu_assert_eq(b->b, true, "bool is true"); rz_il_bool_free(b); mu_end; } bool test_il_bool_logic(void) { RzILBool *t = rz_il_bool_new(true); RzILBool *f = rz_il_bool_new(false); RzILBool *result; // and // t and t => true // f and f => false // t and f => false result = rz_il_bool_and(t, t); mu_assert("true and true", is_equal_bool(result, t)); rz_il_bool_free(result); result = rz_il_bool_and(t, f); mu_assert("true and false", is_equal_bool(result, f)); rz_il_bool_free(result); result = rz_il_bool_and(f, f); mu_assert("false and false", is_equal_bool(result, f)); rz_il_bool_free(result); // or // t or t => true // t or f => true // f or f => false result = rz_il_bool_or(t, t); mu_assert("true or true", is_equal_bool(result, t)); rz_il_bool_free(result); result = rz_il_bool_or(t, f); mu_assert("true or false", is_equal_bool(result, t)); rz_il_bool_free(result); result = rz_il_bool_or(f, f); mu_assert("false or false", is_equal_bool(result, f)); rz_il_bool_free(result); // not // not t => false // not f => true result = rz_il_bool_not(t); mu_assert("not true", is_equal_bool(result, f)); rz_il_bool_free(result); result = rz_il_bool_not(f); mu_assert("not false", is_equal_bool(result, t)); rz_il_bool_free(result); // xor // t xor t => false // f xor f => false // t xor f => true result = rz_il_bool_xor(t, t); mu_assert("t xor t", is_equal_bool(result, f)); rz_il_bool_free(result); result = rz_il_bool_xor(f, f); mu_assert("f xor f", is_equal_bool(result, f)); rz_il_bool_free(result); result = rz_il_bool_xor(t, f); mu_assert("t xor f", is_equal_bool(result, t)); rz_il_bool_free(result); rz_il_bool_free(t); rz_il_bool_free(f); mu_end; } static bool test_il_mem_load() { ut8 data[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x0, 0x0 }; RzBuffer *buf = rz_buf_new_with_pointers(data, sizeof(data), false); rz_buf_set_overflow_byte(buf, 0xaa); RzILMem *mem = rz_il_mem_new(buf, 16); rz_buf_free(buf); // buf is refcounted mu_assert_notnull(mem, "Create mem"); // valid read RzBitVector *addr = rz_bv_new_from_ut64(16, 5); RzBitVector *val = rz_il_mem_load(mem, addr); mu_assert_notnull(val, "load success"); mu_assert_eq(rz_bv_len(val), 8, "load size"); mu_assert_eq(rz_bv_to_ut64(val), 0x42, "load val"); rz_bv_free(val); rz_bv_free(addr); // invalid key size addr = rz_bv_new_from_ut64(8, 1); val = rz_il_mem_load(mem, addr); mu_assert_null(val, "invalid key size"); rz_bv_free(addr); // valid read (overflow) addr = rz_bv_new_from_ut64(16, 100); val = rz_il_mem_load(mem, addr); mu_assert_notnull(val, "load success"); mu_assert_eq(rz_bv_len(val), 8, "load size"); mu_assert_eq(rz_bv_to_ut64(val), 0xaa, "load val"); rz_bv_free(val); rz_bv_free(addr); rz_il_mem_free(mem); mu_end; } static bool test_il_mem_store() { ut8 data[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x0, 0x0 }; RzBuffer *buf = rz_buf_new_with_pointers(data, sizeof(data), false); RzILMem *mem = rz_il_mem_new(buf, 16); rz_buf_free(buf); // buf is refcounted mu_assert_notnull(mem, "Create mem"); RzBitVector *addr = rz_bv_new_from_ut64(16, 1); // valid write RzBitVector *val = rz_bv_new_from_ut64(8, 177); bool succ = rz_il_mem_store(mem, addr, val); rz_bv_free(val); mu_assert_true(succ, "Store successfully"); const ut8 expect0[] = { 0x0, 177, 0x0, 0x0, 0x0, 0x42, 0x0, 0x0 }; mu_assert_memeq(data, expect0, sizeof(expect0), "stored"); // invalid data size val = rz_bv_new_from_ut64(4, 2); succ = rz_il_mem_store(mem, addr, val); rz_bv_free(val); mu_assert_false(succ, "Unmatched value type"); mu_assert_memeq(data, expect0, sizeof(expect0), "not stored"); // invalid key size rz_bv_free(addr); addr = rz_bv_new_from_ut64(8, 1); val = rz_bv_new_from_ut64(8, 177); succ = rz_il_mem_store(mem, addr, val); rz_bv_free(val); mu_assert_false(succ, "invalid key size"); mu_assert_memeq(data, expect0, sizeof(expect0), "not stored"); rz_bv_free(addr); rz_il_mem_free(mem); mu_end; } static bool test_il_mem_loadw() { ut8 data[] = { 0x0, 0x0, 0x0, 0x0, 0x13, 0x37, 0x0, 0x0 }; RzBuffer *buf = rz_buf_new_with_pointers(data, sizeof(data), false); rz_buf_set_overflow_byte(buf, 0xaa); RzILMem *mem = rz_il_mem_new(buf, 16); rz_buf_free(buf); // buf is refcounted mu_assert_notnull(mem, "Create mem"); // valid read (le) RzBitVector *addr = rz_bv_new_from_ut64(16, 4); RzBitVector *val = rz_il_mem_loadw(mem, addr, 16, false); mu_assert_notnull(val, "loadw success"); mu_assert_eq(rz_bv_len(val), 16, "loadw size"); mu_assert_eq(rz_bv_to_ut64(val), 0x3713, "loadw val"); rz_bv_free(val); // valid read (be) val = rz_il_mem_loadw(mem, addr, 16, true); mu_assert_notnull(val, "loadw success"); mu_assert_eq(rz_bv_len(val), 16, "loadw size"); mu_assert_eq(rz_bv_to_ut64(val), 0x1337, "loadw val"); rz_bv_free(val); rz_bv_free(addr); // invalid key size addr = rz_bv_new_from_ut64(8, 1); val = rz_il_mem_loadw(mem, addr, 16, false); rz_bv_free(addr); mu_assert_null(val, "invalid key size"); rz_bv_free(val); // valid read (overflow) addr = rz_bv_new_from_ut64(16, 100); val = rz_il_mem_loadw(mem, addr, 16, false); mu_assert_notnull(val, "load success"); mu_assert_eq(rz_bv_len(val), 16, "load size"); mu_assert_eq(rz_bv_to_ut64(val), 0xaaaa, "load val"); rz_bv_free(val); rz_bv_free(addr); rz_il_mem_free(mem); mu_end; } static bool test_il_mem_storew() { ut8 data[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; RzBuffer *buf = rz_buf_new_with_pointers(data, sizeof(data), false); RzILMem *mem = rz_il_mem_new(buf, 32); rz_buf_free(buf); // buf is refcounted mu_assert_notnull(mem, "Create mem"); // valid write (le) RzBitVector *addr = rz_bv_new_from_ut64(32, 4); RzBitVector *val = rz_bv_new_from_ut64(16, 0x1337); bool succ = rz_il_mem_storew(mem, addr, val, false); rz_bv_free(addr); mu_assert_true(succ, "storew success"); const ut8 expect0[] = { 0x0, 0x0, 0x0, 0x0, 0x37, 0x13, 0x0, 0x0 }; mu_assert_memeq(data, expect0, sizeof(expect0), "stored"); // valid write (be) addr = rz_bv_new_from_ut64(32, 2); succ = rz_il_mem_storew(mem, addr, val, true); mu_assert_true(succ, "storew success"); const ut8 expect1[] = { 0x0, 0x0, 0x13, 0x37, 0x37, 0x13, 0x0, 0x0 }; mu_assert_memeq(data, expect1, sizeof(expect1), "stored"); rz_bv_free(val); rz_bv_free(addr); // invalid key size addr = rz_bv_new_from_ut64(8, 1); val = rz_il_mem_load(mem, addr); mu_assert_null(val, "invalid key size"); mu_assert_memeq(data, expect1, sizeof(expect1), "not stored"); rz_bv_free(addr); rz_il_mem_free(mem); mu_end; } static bool test_il_seqn() { // n = 0 ==> just a nop RzILOpEffect *s = rz_il_op_new_seqn(0); mu_assert_notnull(s, "seqn 0"); mu_assert_eq(s->code, RZ_IL_OP_NOP, "seqn 0 nop"); rz_il_op_effect_free(s); // n = 1 ==> just the op RzILOpEffect *e0 = rz_il_op_new_goto("beach"); s = rz_il_op_new_seqn(1, e0); mu_assert_notnull(s, "seqn 1"); mu_assert_ptreq(s, e0, "seqn 1 op"); rz_il_op_effect_free(s); // n = 2 ==> single seq // (seq e0 e1) e0 = rz_il_op_new_goto("beach"); RzILOpEffect *e1 = rz_il_op_new_goto("beach2"); s = rz_il_op_new_seqn(2, e0, e1); mu_assert_notnull(s, "seqn 2"); mu_assert_eq(s->code, RZ_IL_OP_SEQ, "seqn 2 seq"); mu_assert_ptreq(s->op.seq.x, e0, "seqn 2 first"); mu_assert_ptreq(s->op.seq.y, e1, "seqn 2 second"); rz_il_op_effect_free(s); // n = 3 ==> nested seq with recursion in the second op: // (seq e0 (seq e1 e2)) e0 = rz_il_op_new_goto("beach"); e1 = rz_il_op_new_goto("beach2"); RzILOpEffect *e2 = rz_il_op_new_goto("beach3"); s = rz_il_op_new_seqn(3, e0, e1, e2); mu_assert_notnull(s, "seqn 3"); mu_assert_eq(s->code, RZ_IL_OP_SEQ, "seqn 3 seq"); mu_assert_ptreq(s->op.seq.x, e0, "seqn 3 first"); mu_assert_eq(s->op.seq.y->code, RZ_IL_OP_SEQ, "seqn 3 second seq"); mu_assert_ptreq(s->op.seq.y->op.seq.x, e1, "seqn 3 second"); mu_assert_ptreq(s->op.seq.y->op.seq.y, e2, "seqn 3 third"); rz_il_op_effect_free(s); // n = 4 ==> nested seq with recursion in the second op and no confusion: // (seq e0 (seq e1 (seq e2 e3))) e0 = rz_il_op_new_goto("beach"); e1 = rz_il_op_new_goto("beach2"); e2 = rz_il_op_new_goto("beach3"); RzILOpEffect *e3 = rz_il_op_new_goto("beach3"); s = rz_il_op_new_seqn(4, e0, e1, e2, e3); mu_assert_notnull(s, "seqn 4"); mu_assert_eq(s->code, RZ_IL_OP_SEQ, "seqn 4 seq"); mu_assert_ptreq(s->op.seq.x, e0, "seqn 4 first"); mu_assert_eq(s->op.seq.y->code, RZ_IL_OP_SEQ, "seqn 4 second seq"); mu_assert_ptreq(s->op.seq.y->op.seq.x, e1, "seqn 4 second"); mu_assert_eq(s->op.seq.y->op.seq.y->code, RZ_IL_OP_SEQ, "seqn 4 third seq"); mu_assert_ptreq(s->op.seq.y->op.seq.y->op.seq.x, e2, "seqn 4 third"); mu_assert_ptreq(s->op.seq.y->op.seq.y->op.seq.y, e3, "seqn 4 fourth"); rz_il_op_effect_free(s); mu_end; } static bool test_il_sort_pure_eq() { bool r = rz_il_sort_pure_eq(rz_il_sort_pure_bool(), rz_il_sort_pure_bool()); mu_assert_true(r, "sort eq"); r = rz_il_sort_pure_eq(rz_il_sort_pure_bv(32), rz_il_sort_pure_bv(32)); mu_assert_true(r, "sort eq"); r = rz_il_sort_pure_eq(rz_il_sort_pure_bv(32), rz_il_sort_pure_bv(31)); mu_assert_false(r, "sort eq"); r = rz_il_sort_pure_eq(rz_il_sort_pure_bool(), rz_il_sort_pure_bv(32)); mu_assert_false(r, "sort eq"); r = rz_il_sort_pure_eq(rz_il_sort_pure_bv(32), rz_il_sort_pure_bool()); mu_assert_false(r, "sort eq"); mu_end; } static bool test_il_value_eq() { RzILVal *b0 = rz_il_value_new_bool(rz_il_bool_new(false)); RzILVal *b0_dup = rz_il_value_new_bool(rz_il_bool_new(false)); RzILVal *b1 = rz_il_value_new_bool(rz_il_bool_new(true)); RzILVal *bv16_42 = rz_il_value_new_bitv(rz_bv_new_from_ut64(16, 42)); RzILVal *bv16_42_dup = rz_il_value_new_bitv(rz_bv_new_from_ut64(16, 42)); RzILVal *bv16_43 = rz_il_value_new_bitv(rz_bv_new_from_ut64(16, 43)); RzILVal *bv8_42 = rz_il_value_new_bitv(rz_bv_new_from_ut64(8, 42)); mu_assert_true(rz_il_value_eq(b0, b0), "eq"); mu_assert_true(rz_il_value_eq(b0, b0_dup), "eq"); mu_assert_true(rz_il_value_eq(bv16_42, bv16_42), "eq"); mu_assert_true(rz_il_value_eq(bv16_42, bv16_42_dup), "eq"); mu_assert_false(rz_il_value_eq(b0, b1), "not eq"); mu_assert_false(rz_il_value_eq(b0, bv16_42), "not eq"); mu_assert_false(rz_il_value_eq(bv16_42, bv16_43), "not eq"); mu_assert_false(rz_il_value_eq(bv16_42, bv8_42), "not eq"); rz_il_value_free(b0); rz_il_value_free(b0_dup); rz_il_value_free(b1); rz_il_value_free(bv16_42); rz_il_value_free(bv16_42_dup); rz_il_value_free(bv16_43); rz_il_value_free(bv8_42); mu_end; } bool all_tests() { mu_run_test(test_il_bool_init); mu_run_test(test_il_bool_logic); mu_run_test(test_il_mem_load); mu_run_test(test_il_mem_store); mu_run_test(test_il_mem_loadw); mu_run_test(test_il_mem_storew); mu_run_test(test_il_seqn); mu_run_test(test_il_sort_pure_eq); mu_run_test(test_il_value_eq); return tests_passed != tests_run; } mu_main(all_tests)