// SPDX-FileCopyrightText: 2022 Florian Märkl // SPDX-License-Identifier: LGPL-3.0-only #include #include #include "minunit.h" static bool test_il_validate_pure_bool() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpPure *op = rz_il_op_new_b0(); RzILSortPure sort = rz_il_sort_pure_bv(0xffff); RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bool()), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); op = rz_il_op_new_b1(); sort = rz_il_sort_pure_bv(0xffff); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bool()), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_null() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(NULL, ctx, &sort, &report); mu_assert_false(val, "valid"); mu_assert_streq_free(report, "Encountered NULL for pure op.", "no report"); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_bitv() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpPure *op = rz_il_op_new_bitv_from_ut64(42, 123); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(42)), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_ite() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpPure *op = rz_il_op_new_ite(rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(32, 0), rz_il_op_new_bitv_from_ut64(32, 0)); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(32)), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); op = rz_il_op_new_ite(rz_il_op_new_b0(), rz_il_op_new_b0(), rz_il_op_new_b1()); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bool()), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); op = rz_il_op_new_ite(rz_il_op_new_bitv_from_ut64(12, 0), rz_il_op_new_bitv_from_ut64(32, 0), rz_il_op_new_bitv_from_ut64(32, 0)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "valid"); mu_assert_streq_free(report, "Condition of ite op is not boolean.", "report"); rz_il_op_pure_free(op); op = rz_il_op_new_ite(rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(32, 0), rz_il_op_new_bitv_from_ut64(31, 0)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "valid"); mu_assert_streq_free(report, "Types of ite branches do not agree: bitvector:32 vs. bitvector:31.", "report"); rz_il_op_pure_free(op); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_let() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); // body type RzILOpPure *op = rz_il_op_new_let( "x", rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(64, 456)); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(64)), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); // bound op = rz_il_op_new_let( "x", rz_il_op_new_b0(), rz_il_op_new_var("x", RZ_IL_VAR_KIND_LOCAL_PURE)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bool()), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); // shadowing op = rz_il_op_new_let( "x", rz_il_op_new_b0(), rz_il_op_new_let( "y", rz_il_op_new_bitv_from_ut64(32, 123), rz_il_op_new_let( "x", rz_il_op_new_bitv_from_ut64(42, 321), rz_il_op_new_var("x", RZ_IL_VAR_KIND_LOCAL_PURE)))); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(42)), "sort"); mu_assert_null(report, "no report"); free(report); rz_il_op_pure_free(op); op = rz_il_op_new_let( "x", rz_il_op_new_b0(), rz_il_op_new_let( "y", rz_il_op_new_bitv_from_ut64(32, 123), rz_il_op_new_let( "x", rz_il_op_new_bitv_from_ut64(42, 321), rz_il_op_new_var("y", RZ_IL_VAR_KIND_LOCAL_PURE)))); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(32)), "sort"); mu_assert_null(report, "no report"); free(report); rz_il_op_pure_free(op); // invalid cases op = rz_il_op_new_let( "x", rz_il_op_new_b0(), rz_il_op_new_var("x", RZ_IL_VAR_KIND_LOCAL)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "valid"); free(report); rz_il_op_pure_free(op); op = rz_il_op_new_let( "x", rz_il_op_new_b0(), rz_il_op_new_var("x", RZ_IL_VAR_KIND_GLOBAL)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "valid"); free(report); rz_il_op_pure_free(op); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_var() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); rz_il_validate_global_context_add_var(ctx, "y", rz_il_sort_pure_bv(42)); RzILOpPure *op = rz_il_op_new_var("y", RZ_IL_VAR_KIND_GLOBAL); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(42)), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); RzILOpEffect *eop = rz_il_op_new_seq( rz_il_op_new_set("y", true, rz_il_op_new_bitv_from_ut64(24, 0x1234)), rz_il_op_new_jmp(rz_il_op_new_var("y", RZ_IL_VAR_KIND_LOCAL))); RzILTypeEffect t; val = rz_il_validate_effect(eop, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA | RZ_IL_TYPE_EFFECT_CTRL, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(eop); op = rz_il_op_new_var("x", RZ_IL_VAR_KIND_GLOBAL); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Global variable \"x\" referenced by var op does not exist.", "report"); rz_il_op_pure_free(op); op = rz_il_op_new_var("x", RZ_IL_VAR_KIND_LOCAL); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Local variable \"x\" is not available at var op.", "report"); rz_il_op_pure_free(op); eop = rz_il_op_new_seq( rz_il_op_new_set("y", true, rz_il_op_new_bitv_from_ut64(23, 0x1234)), rz_il_op_new_jmp(rz_il_op_new_var("y", RZ_IL_VAR_KIND_LOCAL))); val = rz_il_validate_effect(eop, ctx, NULL, &t, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Length of dst operand (23) of jmp op is not equal to pc length 24.", "report"); rz_il_op_effect_free(eop); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_inv() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpPure *op = rz_il_op_new_bool_inv(rz_il_op_new_b0()); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bool()), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); op = rz_il_op_new_bool_inv(rz_il_op_new_bitv_from_ut64(32, 0)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Operand of boolean inv op is not boolean.", "report"); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_bool_binop() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpPure *op = rz_il_op_new_bool_and( rz_il_op_new_b0(), rz_il_op_new_b1()); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bool()), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); op = rz_il_op_new_bool_and( rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(64, 456)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Right operand of and op is not bool.", "report"); op = rz_il_op_new_bool_and( rz_il_op_new_bitv_from_ut64(64, 456), rz_il_op_new_b0()); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Left operand of and op is not bool.", "report"); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_bitv_binop() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpPure *op = rz_il_op_new_add( rz_il_op_new_bitv_from_ut64(64, 123), rz_il_op_new_bitv_from_ut64(64, 456)); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(64)), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); op = rz_il_op_new_add( rz_il_op_new_bitv_from_ut64(63, 123), rz_il_op_new_bitv_from_ut64(64, 456)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Operand sizes of add op do not agree: 63 vs. 64.", "report"); op = rz_il_op_new_add( rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(64, 456)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Left operand of add op is not a bitvector.", "report"); op = rz_il_op_new_add( rz_il_op_new_bitv_from_ut64(64, 456), rz_il_op_new_b0()); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Right operand of add op is not a bitvector.", "report"); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_bitv_bool_unop() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpPure *op = rz_il_op_new_msb(rz_il_op_new_bitv_from_ut64(64, 123)); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bool()), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); op = rz_il_op_new_msb(rz_il_op_new_b0()); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Operand of msb op is not a bitvector.", "report"); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_bitv_unop() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpPure *op = rz_il_op_new_log_not(rz_il_op_new_bitv_from_ut64(64, 123)); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(64)), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); op = rz_il_op_new_log_not(rz_il_op_new_b0()); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Operand of lognot op is not a bitvector.", "report"); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_shift() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpPure *op = rz_il_op_new_shiftl(rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(64, 123), rz_il_op_new_bitv_from_ut64(32, 32)); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(64)), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); op = rz_il_op_new_shiftl(rz_il_op_new_bitv_from_ut64(8, 0), rz_il_op_new_bitv_from_ut64(64, 123), rz_il_op_new_bitv_from_ut64(32, 32)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Fill operand of shiftl op is not bool.", "report"); op = rz_il_op_new_shiftl(rz_il_op_new_b0(), rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(32, 32)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Value operand of shiftl op is not a bitvector.", "report"); op = rz_il_op_new_shiftl(rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(32, 32), rz_il_op_new_b0()); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Distance operand of shiftl op is not a bitvector.", "report"); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_cmp() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpPure *op = rz_il_op_new_eq( rz_il_op_new_bitv_from_ut64(64, 123), rz_il_op_new_bitv_from_ut64(64, 456)); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bool()), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); op = rz_il_op_new_eq( rz_il_op_new_bitv_from_ut64(63, 123), rz_il_op_new_bitv_from_ut64(64, 456)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Operand sizes of eq op do not agree: 63 vs. 64.", "report"); op = rz_il_op_new_eq( rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(64, 456)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Left operand of eq op is not a bitvector.", "report"); op = rz_il_op_new_eq( rz_il_op_new_bitv_from_ut64(64, 456), rz_il_op_new_b0()); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Right operand of eq op is not a bitvector.", "report"); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_cast() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpPure *op = rz_il_op_new_cast(13, rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(64, 456)); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(13)), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); op = rz_il_op_new_cast(13, rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(64, 456)); op->op.cast.length = 0; val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Length of cast op is 0.", "report"); op = rz_il_op_new_cast(13, rz_il_op_new_bitv_from_ut64(12, 0), rz_il_op_new_bitv_from_ut64(64, 456)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Fill operand of cast op is not bool.", "report"); op = rz_il_op_new_cast(13, rz_il_op_new_b0(), rz_il_op_new_b0()); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Value operand of cast op is not a bitvector.", "report"); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_append() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpPure *op = rz_il_op_new_append( rz_il_op_new_bitv_from_ut64(64, 123), rz_il_op_new_bitv_from_ut64(41, 456)); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(64 + 41)), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); op = rz_il_op_new_append( rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(64, 456)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "High operand of append op is not a bitvector.", "report"); op = rz_il_op_new_append( rz_il_op_new_bitv_from_ut64(64, 456), rz_il_op_new_b0()); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Low operand of append op is not a bitvector.", "report"); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_load() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); rz_il_validate_global_context_add_mem(ctx, 1, 16, 9); RzILOpPure *op = rz_il_op_new_load(1, rz_il_op_new_bitv_from_ut64(16, 123)); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(9)), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); op = rz_il_op_new_load(1, rz_il_op_new_bitv_from_ut64(9, 123)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Length of key operand (9) of load op is not equal to key length 16 of mem 1.", "report"); op = rz_il_op_new_load(0, rz_il_op_new_bitv_from_ut64(16, 123)); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Mem 0 referenced by load op does not exist.", "report"); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_pure_loadw() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); rz_il_validate_global_context_add_mem(ctx, 1, 16, 9); RzILOpPure *op = rz_il_op_new_loadw(1, rz_il_op_new_bitv_from_ut64(16, 123), 32); RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_true(val, "valid"); mu_assert_true(rz_il_sort_pure_eq(sort, rz_il_sort_pure_bv(32)), "sort"); mu_assert_null(report, "no report"); rz_il_op_pure_free(op); op = rz_il_op_new_loadw(1, rz_il_op_new_bitv_from_ut64(12, 123), 32); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Length of key operand (12) of loadw op is not equal to key length 16 of mem 1.", "report"); op = rz_il_op_new_loadw(0, rz_il_op_new_bitv_from_ut64(16, 123), 32); val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Mem 0 referenced by loadw op does not exist.", "report"); op = rz_il_op_new_loadw(1, rz_il_op_new_bitv_from_ut64(16, 123), 32); op->op.loadw.n_bits = 0; val = rz_il_validate_pure(op, ctx, &sort, &report); mu_assert_false(val, "invalid"); rz_il_op_pure_free(op); mu_assert_streq_free(report, "Length of loadw op is 0.", "report"); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_effect_null() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILValidateReport report; bool val = rz_il_validate_effect(NULL, ctx, NULL, NULL, &report); mu_assert_false(val, "valid"); mu_assert_streq_free(report, "Encountered NULL for effect op.", "no report"); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_effect_empty() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpEffect *op = rz_il_op_new_empty(); RzILValidateReport report; RzILTypeEffect t; bool val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_NONE, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_effect_nop() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpEffect *op = rz_il_op_new_nop(); RzILValidateReport report; RzILTypeEffect t; bool val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_NONE, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_effect_store() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); rz_il_validate_global_context_add_mem(ctx, 1, 16, 9); RzILOpEffect *op = rz_il_op_new_store(1, rz_il_op_new_bitv_from_ut64(16, 123), rz_il_op_new_bitv_from_ut64(9, 42)); RzILValidateReport report; RzILTypeEffect t; bool val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_store(0, rz_il_op_new_bitv_from_ut64(16, 123), rz_il_op_new_bitv_from_ut64(9, 42)); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Mem 0 referenced by store op does not exist.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_store(1, rz_il_op_new_bitv_from_ut64(12, 123), rz_il_op_new_bitv_from_ut64(9, 42)); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Length of key operand (12) of store op is not equal to key length 16 of mem 1.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_store(1, rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(9, 42)); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Key operand of store op is not a bitvector.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_store(1, rz_il_op_new_bitv_from_ut64(16, 123), rz_il_op_new_bitv_from_ut64(8, 42)); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Length of value operand (8) of store op is not equal to value length 9 of mem 1.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_store(1, rz_il_op_new_bitv_from_ut64(16, 123), rz_il_op_new_b0()); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Value operand of store op is not a bitvector.", "report"); rz_il_op_effect_free(op); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_effect_storew() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); rz_il_validate_global_context_add_mem(ctx, 1, 16, 9); RzILOpEffect *op = rz_il_op_new_storew(1, rz_il_op_new_bitv_from_ut64(16, 123), rz_il_op_new_bitv_from_ut64(42, 42)); RzILValidateReport report; RzILTypeEffect t; bool val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_storew(0, rz_il_op_new_bitv_from_ut64(16, 123), rz_il_op_new_bitv_from_ut64(9, 42)); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Mem 0 referenced by storew op does not exist.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_storew(1, rz_il_op_new_bitv_from_ut64(12, 123), rz_il_op_new_bitv_from_ut64(9, 42)); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Length of key operand (12) of storew op is not equal to key length 16 of mem 1.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_storew(1, rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(9, 42)); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Key operand of storew op is not a bitvector.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_storew(1, rz_il_op_new_bitv_from_ut64(16, 123), rz_il_op_new_b0()); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Value operand of storew op is not a bitvector.", "report"); rz_il_op_effect_free(op); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_effect_set() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); rz_il_validate_global_context_add_var(ctx, "x", rz_il_sort_pure_bv(42)); // global RzILOpEffect *op = rz_il_op_new_set("x", false, rz_il_op_new_bitv_from_ut64(42, 0)); RzILValidateReport report; RzILTypeEffect t; bool val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_set("y", false, rz_il_op_new_bitv_from_ut64(42, 0)); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Global variable \"y\" referenced by set op does not exist.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_set("x", false, rz_il_op_new_bitv_from_ut64(41, 0)); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Types of global variable \"x\" and set op do not agree: bitvector:42 vs. bitvector:41.", "report"); rz_il_op_effect_free(op); // local op = rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(20, 0)); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_true(val, "valid"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_seq( rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(22, 0)), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(22, 42))); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_true(val, "valid"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_seq( rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(22, 0)), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(21, 42))); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Types of local variable \"x\" and set op do not agree: bitvector:22 vs. bitvector:21.", "report"); rz_il_op_effect_free(op); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_effect_jmp() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpEffect *op = rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(24, 0x1000)); RzILValidateReport report; RzILTypeEffect t; bool val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_CTRL, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(42, 0x1000)); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Length of dst operand (42) of jmp op is not equal to pc length 24.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_jmp(rz_il_op_new_b0()); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Dst operand of jmp op is not a bitvector.", "report"); rz_il_op_effect_free(op); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_effect_goto() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpEffect *op = rz_il_op_new_goto("beach"); RzILValidateReport report; RzILTypeEffect t; bool val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_CTRL, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_effect_seq() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpEffect *op = rz_il_op_new_seq(rz_il_op_new_nop(), rz_il_op_new_nop()); RzILValidateReport report; RzILTypeEffect t; bool val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_NONE, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_seq(rz_il_op_new_set("nexist", false, rz_il_op_new_b0()), rz_il_op_new_nop()); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Global variable \"nexist\" referenced by set op does not exist.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_seq(rz_il_op_new_nop(), rz_il_op_new_set("nexist", false, rz_il_op_new_b0())); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Global variable \"nexist\" referenced by set op does not exist.", "report"); rz_il_op_effect_free(op); // effect type handling op = rz_il_op_new_seq(rz_il_op_new_set("x", true, rz_il_op_new_b0()), rz_il_op_new_nop()); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_seq(rz_il_op_new_set("x", true, rz_il_op_new_b0()), rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(24, 0x100))); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA | RZ_IL_TYPE_EFFECT_CTRL, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_seq(rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(24, 0x100)), rz_il_op_new_set("x", true, rz_il_op_new_b0())); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Encountered further effects after a ctrl effect in seq op.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_seq(rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(24, 0x100)), rz_il_op_new_nop()); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_CTRL, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_seq(rz_il_op_new_nop(), rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(24, 0x100))); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_CTRL, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_seq(rz_il_op_new_nop(), rz_il_op_new_set("x", true, rz_il_op_new_b0())); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_effect_blk() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpEffect *op = rz_il_op_new_blk(NULL, rz_il_op_new_nop(), rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(24, 0x1000))); RzILValidateReport report; RzILTypeEffect t; bool val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_CTRL, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_blk(NULL, rz_il_op_new_set("nexist", false, rz_il_op_new_b0()), rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(24, 0x1000))); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Global variable \"nexist\" referenced by set op does not exist.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_blk(NULL, rz_il_op_new_nop(), rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(23, 0x1000))); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Length of dst operand (23) of jmp op is not equal to pc length 24.", "report"); rz_il_op_effect_free(op); // effect type handling op = rz_il_op_new_blk(NULL, rz_il_op_new_set("x", true, rz_il_op_new_b0()), rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(24, 0x1000))); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA | RZ_IL_TYPE_EFFECT_CTRL, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_blk(NULL, rz_il_op_new_set("x", true, rz_il_op_new_b0()), rz_il_op_new_nop()); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_blk(NULL, rz_il_op_new_nop(), rz_il_op_new_set("x", true, rz_il_op_new_b0())); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Control effect operand of blk op does not only perform control effects.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_blk(NULL, rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(24, 0x1000)), rz_il_op_new_nop()); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Data effect operand of blk op does not only perform data effects.", "report"); rz_il_op_effect_free(op); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_effect_repeat() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpEffect *op = rz_il_op_new_repeat(rz_il_op_new_b0(), rz_il_op_new_nop()); RzILValidateReport report; RzILTypeEffect t; bool val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_NONE, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_repeat(rz_il_op_new_bitv_from_ut64(16, 0), rz_il_op_new_nop()); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Condition of repeat op is not boolean.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_repeat(rz_il_op_new_b0(), rz_il_op_new_set("nexist", false, rz_il_op_new_b0())); val = rz_il_validate_effect(op, ctx, NULL, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Global variable \"nexist\" referenced by set op does not exist.", "report"); rz_il_op_effect_free(op); ////////////////////////// // local context handling // types remembered from the loop op = rz_il_op_new_repeat(rz_il_op_new_b0(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 0))); HtPP *local_var_sorts; val = rz_il_validate_effect(op, ctx, &local_var_sorts, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA, "effect type"); mu_assert_null(report, "no report"); mu_assert_notnull(local_var_sorts, "local var sorts"); mu_assert_eq(local_var_sorts->count, 1, "local var sorts count"); RzILSortPure *sort = ht_pp_find(local_var_sorts, "x", NULL); mu_assert_notnull(sort, "local var sort"); mu_assert_true(rz_il_sort_pure_eq(*sort, rz_il_sort_pure_bv(14)), "local var sort"); ht_pp_free(local_var_sorts); local_var_sorts = NULL; rz_il_op_effect_free(op); // vars available before are still available after op = rz_il_op_new_seqn(3, rz_il_op_new_set("y", true, rz_il_op_new_b0()), rz_il_op_new_repeat(rz_il_op_new_b0(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 0))), rz_il_op_new_set("y", true, rz_il_op_new_ite(rz_il_op_new_var("y", RZ_IL_VAR_KIND_LOCAL), rz_il_op_new_b0(), rz_il_op_new_b1()))); val = rz_il_validate_effect(op, ctx, &local_var_sorts, NULL, &report); mu_assert_true(val, "valid"); mu_assert_null(report, "no report"); mu_assert_notnull(local_var_sorts, "local var sorts"); mu_assert_eq(local_var_sorts->count, 2, "local var sorts count"); sort = ht_pp_find(local_var_sorts, "x", NULL); mu_assert_notnull(sort, "local var sort"); mu_assert_true(rz_il_sort_pure_eq(*sort, rz_il_sort_pure_bv(14)), "local var sort"); sort = ht_pp_find(local_var_sorts, "y", NULL); mu_assert_notnull(sort, "local var sort"); mu_assert_true(rz_il_sort_pure_eq(*sort, rz_il_sort_pure_bool()), "local var sort"); ht_pp_free(local_var_sorts); local_var_sorts = NULL; rz_il_op_effect_free(op); // vars available only inside the loop can be made available again if they have the same type op = rz_il_op_new_seqn(3, rz_il_op_new_set("y", true, rz_il_op_new_b0()), rz_il_op_new_repeat(rz_il_op_new_b0(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 0))), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 32))); val = rz_il_validate_effect(op, ctx, &local_var_sorts, NULL, &report); mu_assert_true(val, "valid"); mu_assert_null(report, "no report"); mu_assert_notnull(local_var_sorts, "local var sorts"); mu_assert_eq(local_var_sorts->count, 2, "local var sorts count"); sort = ht_pp_find(local_var_sorts, "x", NULL); mu_assert_notnull(sort, "local var sort"); mu_assert_true(rz_il_sort_pure_eq(*sort, rz_il_sort_pure_bv(14)), "local var sort"); sort = ht_pp_find(local_var_sorts, "y", NULL); mu_assert_notnull(sort, "local var sort"); mu_assert_true(rz_il_sort_pure_eq(*sort, rz_il_sort_pure_bool()), "local var sort"); ht_pp_free(local_var_sorts); local_var_sorts = NULL; rz_il_op_effect_free(op); // vars defined inside the loop already can not be used again with another type op = rz_il_op_new_seqn(3, rz_il_op_new_set("y", true, rz_il_op_new_b0()), rz_il_op_new_repeat(rz_il_op_new_b0(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 0))), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(13, 32))); val = rz_il_validate_effect(op, ctx, &local_var_sorts, &t, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Types of local variable \"x\" and set op do not agree: bitvector:14 vs. bitvector:13.", "report"); rz_il_op_effect_free(op); // vars available only inside the loop are not available after it anymore op = rz_il_op_new_seqn(3, rz_il_op_new_set("y", true, rz_il_op_new_b0()), rz_il_op_new_repeat(rz_il_op_new_b0(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 0))), rz_il_op_new_set("x", true, rz_il_op_new_var("x", RZ_IL_VAR_KIND_LOCAL))); val = rz_il_validate_effect(op, ctx, &local_var_sorts, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Local variable \"x\" is not available at var op.", "report"); rz_il_op_effect_free(op); ////////////////////////// // effect type handling op = rz_il_op_new_repeat(rz_il_op_new_b0(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 0))); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_repeat(rz_il_op_new_b0(), rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(24, 0x100))); val = rz_il_validate_effect(op, ctx, &local_var_sorts, &t, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Body operand of repeat op does not only perform data effects.", "report"); rz_il_op_effect_free(op); rz_il_validate_global_context_free(ctx); mu_end; } static bool test_il_validate_effect_branch() { RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24); RzILOpEffect *op = rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_nop(), rz_il_op_new_nop()); RzILValidateReport report; RzILTypeEffect t; bool val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_NONE, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_branch(rz_il_op_new_bitv_from_ut64(8, 0), rz_il_op_new_nop(), rz_il_op_new_nop()); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Condition of branch op is not boolean.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_set("nexist", false, rz_il_op_new_b0()), rz_il_op_new_nop()); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Global variable \"nexist\" referenced by set op does not exist.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_nop(), rz_il_op_new_set("nexist", false, rz_il_op_new_b0())); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Global variable \"nexist\" referenced by set op does not exist.", "report"); rz_il_op_effect_free(op); ////////////////////////// // local context handling // types remembered from the branches op = rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 0)), rz_il_op_new_set("y", true, rz_il_op_new_b0())); HtPP *local_var_sorts; val = rz_il_validate_effect(op, ctx, &local_var_sorts, &t, &report); mu_assert_true(val, "valid"); mu_assert_null(report, "no report"); mu_assert_notnull(local_var_sorts, "local var sorts"); mu_assert_eq(local_var_sorts->count, 2, "local var sorts count"); RzILSortPure *sort = ht_pp_find(local_var_sorts, "x", NULL); mu_assert_notnull(sort, "local var sort"); mu_assert_true(rz_il_sort_pure_eq(*sort, rz_il_sort_pure_bv(14)), "local var sort"); sort = ht_pp_find(local_var_sorts, "y", NULL); mu_assert_notnull(sort, "local var sort"); mu_assert_true(rz_il_sort_pure_eq(*sort, rz_il_sort_pure_bool()), "local var sort"); ht_pp_free(local_var_sorts); local_var_sorts = NULL; rz_il_op_effect_free(op); // vars available before are still available after op = rz_il_op_new_seqn(3, rz_il_op_new_set("y", true, rz_il_op_new_b0()), rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_nop(), rz_il_op_new_nop()), rz_il_op_new_set("y", true, rz_il_op_new_ite(rz_il_op_new_var("y", RZ_IL_VAR_KIND_LOCAL), rz_il_op_new_b0(), rz_il_op_new_b1()))); val = rz_il_validate_effect(op, ctx, &local_var_sorts, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA, "effect type"); mu_assert_null(report, "no report"); mu_assert_notnull(local_var_sorts, "local var sorts"); mu_assert_eq(local_var_sorts->count, 1, "local var sorts count"); sort = ht_pp_find(local_var_sorts, "y", NULL); mu_assert_notnull(sort, "local var sort"); mu_assert_true(rz_il_sort_pure_eq(*sort, rz_il_sort_pure_bool()), "local var sort"); ht_pp_free(local_var_sorts); local_var_sorts = NULL; rz_il_op_effect_free(op); // vars available only inside a branch can be made available again if they have the same type op = rz_il_op_new_seqn(3, rz_il_op_new_set("y", true, rz_il_op_new_b0()), rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_nop(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 0))), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 32))); val = rz_il_validate_effect(op, ctx, &local_var_sorts, NULL, &report); mu_assert_true(val, "valid"); mu_assert_null(report, "no report"); mu_assert_notnull(local_var_sorts, "local var sorts"); mu_assert_eq(local_var_sorts->count, 2, "local var sorts count"); sort = ht_pp_find(local_var_sorts, "x", NULL); mu_assert_notnull(sort, "local var sort"); mu_assert_true(rz_il_sort_pure_eq(*sort, rz_il_sort_pure_bv(14)), "local var sort"); sort = ht_pp_find(local_var_sorts, "y", NULL); mu_assert_notnull(sort, "local var sort"); mu_assert_true(rz_il_sort_pure_eq(*sort, rz_il_sort_pure_bool()), "local var sort"); ht_pp_free(local_var_sorts); local_var_sorts = NULL; rz_il_op_effect_free(op); op = rz_il_op_new_seqn(3, rz_il_op_new_set("y", true, rz_il_op_new_b0()), rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 0)), rz_il_op_new_nop()), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 32))); val = rz_il_validate_effect(op, ctx, &local_var_sorts, NULL, &report); mu_assert_true(val, "valid"); mu_assert_null(report, "no report"); mu_assert_notnull(local_var_sorts, "local var sorts"); mu_assert_eq(local_var_sorts->count, 2, "local var sorts count"); sort = ht_pp_find(local_var_sorts, "x", NULL); mu_assert_notnull(sort, "local var sort"); mu_assert_true(rz_il_sort_pure_eq(*sort, rz_il_sort_pure_bv(14)), "local var sort"); sort = ht_pp_find(local_var_sorts, "y", NULL); mu_assert_notnull(sort, "local var sort"); mu_assert_true(rz_il_sort_pure_eq(*sort, rz_il_sort_pure_bool()), "local var sort"); ht_pp_free(local_var_sorts); local_var_sorts = NULL; rz_il_op_effect_free(op); // vars defined in both branches are still available after it op = rz_il_op_new_seqn(3, rz_il_op_new_set("y", true, rz_il_op_new_b0()), rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 0)), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 42))), rz_il_op_new_set("x", true, rz_il_op_new_var("x", RZ_IL_VAR_KIND_LOCAL))); val = rz_il_validate_effect(op, ctx, &local_var_sorts, NULL, &report); mu_assert_true(val, "valid"); mu_assert_null(report, "no report"); mu_assert_notnull(local_var_sorts, "local var sorts"); mu_assert_eq(local_var_sorts->count, 2, "local var sorts count"); sort = ht_pp_find(local_var_sorts, "x", NULL); mu_assert_notnull(sort, "local var sort"); mu_assert_true(rz_il_sort_pure_eq(*sort, rz_il_sort_pure_bv(14)), "local var sort"); sort = ht_pp_find(local_var_sorts, "y", NULL); mu_assert_notnull(sort, "local var sort"); mu_assert_true(rz_il_sort_pure_eq(*sort, rz_il_sort_pure_bool()), "local var sort"); ht_pp_free(local_var_sorts); local_var_sorts = NULL; rz_il_op_effect_free(op); // vars defined already inside the branch can not be used again with another type op = rz_il_op_new_seqn(3, rz_il_op_new_set("y", true, rz_il_op_new_b0()), rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_nop(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 0))), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(13, 32))); val = rz_il_validate_effect(op, ctx, &local_var_sorts, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Types of local variable \"x\" and set op do not agree: bitvector:14 vs. bitvector:13.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_seqn(3, rz_il_op_new_set("y", true, rz_il_op_new_b0()), rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 0)), rz_il_op_new_nop()), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(13, 32))); val = rz_il_validate_effect(op, ctx, &local_var_sorts, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Types of local variable \"x\" and set op do not agree: bitvector:14 vs. bitvector:13.", "report"); rz_il_op_effect_free(op); // vars defined only inside one branch are not available after it anymore op = rz_il_op_new_seqn(3, rz_il_op_new_set("y", true, rz_il_op_new_b0()), rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_nop(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 0))), rz_il_op_new_set("x", true, rz_il_op_new_var("x", RZ_IL_VAR_KIND_LOCAL))); val = rz_il_validate_effect(op, ctx, &local_var_sorts, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Local variable \"x\" is not available at var op.", "report"); rz_il_op_effect_free(op); op = rz_il_op_new_seqn(3, rz_il_op_new_set("y", true, rz_il_op_new_b0()), rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 0)), rz_il_op_new_nop()), rz_il_op_new_set("x", true, rz_il_op_new_var("x", RZ_IL_VAR_KIND_LOCAL))); val = rz_il_validate_effect(op, ctx, &local_var_sorts, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Local variable \"x\" is not available at var op.", "report"); rz_il_op_effect_free(op); // vars defined in both branches must agree in their types op = rz_il_op_new_seqn(3, rz_il_op_new_set("y", true, rz_il_op_new_b0()), rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(13, 0)), rz_il_op_new_set("x", true, rz_il_op_new_bitv_from_ut64(14, 42))), rz_il_op_new_set("x", true, rz_il_op_new_var("x", RZ_IL_VAR_KIND_LOCAL))); val = rz_il_validate_effect(op, ctx, &local_var_sorts, NULL, &report); mu_assert_false(val, "invalid"); mu_assert_streq_free(report, "Control flow paths from branch op do not agree on the type of local variable \"x\": bitvector:14 vs. bitvector:13.", "report"); rz_il_op_effect_free(op); ////////////////////////// // effect type handling op = rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_set("x", true, rz_il_op_new_b0()), rz_il_op_new_nop()); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_nop(), rz_il_op_new_set("x", true, rz_il_op_new_b0())); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_nop(), rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(24, 0x100))); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_CTRL, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(24, 0x100)), rz_il_op_new_nop()); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_CTRL, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); op = rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(24, 0x100)), rz_il_op_new_set("x", true, rz_il_op_new_b0())); val = rz_il_validate_effect(op, ctx, NULL, &t, &report); mu_assert_true(val, "valid"); mu_assert_eq(t, RZ_IL_TYPE_EFFECT_DATA | RZ_IL_TYPE_EFFECT_CTRL, "effect type"); mu_assert_null(report, "no report"); rz_il_op_effect_free(op); rz_il_validate_global_context_free(ctx); mu_end; } bool all_tests() { mu_run_test(test_il_validate_pure_null); mu_run_test(test_il_validate_pure_bitv); mu_run_test(test_il_validate_pure_bool); mu_run_test(test_il_validate_pure_ite); mu_run_test(test_il_validate_pure_let); mu_run_test(test_il_validate_pure_var); mu_run_test(test_il_validate_pure_inv); mu_run_test(test_il_validate_pure_bool_binop); mu_run_test(test_il_validate_pure_bitv_binop); mu_run_test(test_il_validate_pure_bitv_bool_unop); mu_run_test(test_il_validate_pure_bitv_unop); mu_run_test(test_il_validate_pure_shift); mu_run_test(test_il_validate_pure_cmp); mu_run_test(test_il_validate_pure_cast); mu_run_test(test_il_validate_pure_append); mu_run_test(test_il_validate_pure_load); mu_run_test(test_il_validate_pure_loadw); mu_run_test(test_il_validate_effect_null); mu_run_test(test_il_validate_effect_empty); mu_run_test(test_il_validate_effect_nop); mu_run_test(test_il_validate_effect_store); mu_run_test(test_il_validate_effect_storew); mu_run_test(test_il_validate_effect_set); mu_run_test(test_il_validate_effect_jmp); mu_run_test(test_il_validate_effect_goto); mu_run_test(test_il_validate_effect_seq); mu_run_test(test_il_validate_effect_blk); mu_run_test(test_il_validate_effect_repeat); mu_run_test(test_il_validate_effect_branch); return tests_passed != tests_run; } mu_main(all_tests)