rizin/test/unit/test_il_definitions.c
Florian Märkl 1a3ba85c48 [RzIL] Add rz_il_value_eq()
Needed for rz-tracetest
2022-01-22 18:40:10 +01:00

359 lines
11 KiB
C

// SPDX-FileCopyrightText: 2021 heersin <teablearcher@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_il.h>
#include <rz_util.h>
#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)