[RzIL] Forbid data after ctrl effects by validation
Because there is currently no reason to have non-ctrl effects after a ctrl effect (because then we have already jumped somewhere else), we reject this kind of code altogether. This leaves future semantics of such code open without breaking any existing IL, in case it will be needed at some point.
This commit is contained in:
parent
111cd2c476
commit
1fcf76faf8
5 changed files with 263 additions and 65 deletions
|
|
@ -621,6 +621,7 @@ RZ_API bool rz_il_validate_pure(RZ_NULLABLE RzILOpPure *op, RZ_NONNULL RzILValid
|
|||
// clang-format off
|
||||
#define VALIDATOR_EFFECT_ARGS \
|
||||
RZ_NULLABLE RzILOpEffect *op, \
|
||||
RZ_NONNULL RzILTypeEffect *type_out, \
|
||||
RZ_NONNULL RzStrBuf *report_builder, \
|
||||
RZ_NONNULL LocalContext *ctx
|
||||
// clang-format on
|
||||
|
|
@ -636,14 +637,15 @@ typedef bool (*ValidateEffectFn)(VALIDATOR_EFFECT_ARGS);
|
|||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
#define VALIDATOR_DESCEND_EFFECT(op, ectx, cleanup) \
|
||||
#define VALIDATOR_DESCEND_EFFECT(op, etype, ectx, cleanup) \
|
||||
do { \
|
||||
if (!validate_effect(op, report_builder, ectx)) { \
|
||||
if (!validate_effect(op, etype, report_builder, ectx)) { \
|
||||
cleanup return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
VALIDATOR_EFFECT(nop) {
|
||||
*type_out = RZ_IL_TYPE_EFFECT_NONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -664,6 +666,7 @@ VALIDATOR_EFFECT(store) {
|
|||
VALIDATOR_ASSERT(sv.type == RZ_IL_TYPE_PURE_BITVECTOR, "Value operand of store op is not a bitvector.\n");
|
||||
VALIDATOR_ASSERT(sv.props.bv.length == val_len, "Length of value operand (%u) of store op is not equal to value length %u of mem %u.\n",
|
||||
(unsigned int)sv.props.bv.length, (unsigned int)val_len, (unsigned int)args->mem);
|
||||
*type_out = RZ_IL_TYPE_EFFECT_DATA;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -681,6 +684,7 @@ VALIDATOR_EFFECT(storew) {
|
|||
RzILSortPure sv;
|
||||
VALIDATOR_DESCEND_PURE(args->value, &sv);
|
||||
VALIDATOR_ASSERT(sv.type == RZ_IL_TYPE_PURE_BITVECTOR, "Value operand of storew op is not a bitvector.\n");
|
||||
*type_out = RZ_IL_TYPE_EFFECT_DATA;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -713,6 +717,7 @@ VALIDATOR_EFFECT(set) {
|
|||
}
|
||||
ht_pp_update(ctx->local_vars_available, args->v, sort);
|
||||
}
|
||||
*type_out = RZ_IL_TYPE_EFFECT_DATA;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -724,6 +729,7 @@ VALIDATOR_EFFECT(jmp) {
|
|||
VALIDATOR_ASSERT(sd.props.bv.length == ctx->global_ctx->pc_len,
|
||||
"Length of dst operand (%u) of jmp op is not equal to pc length %u.\n",
|
||||
(unsigned int)sd.props.bv.length, (unsigned int)ctx->global_ctx->pc_len);
|
||||
*type_out = RZ_IL_TYPE_EFFECT_CTRL;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -731,21 +737,35 @@ VALIDATOR_EFFECT(goto) {
|
|||
RzILOpArgsGoto *args = &op->op.goto_;
|
||||
VALIDATOR_ASSERT(args->lbl, "Label of goto op is NULL.\n");
|
||||
// So far, no restrictions on goto because labels are dynamically created. This might change in the future.
|
||||
*type_out = RZ_IL_TYPE_EFFECT_CTRL;
|
||||
return true;
|
||||
}
|
||||
|
||||
VALIDATOR_EFFECT(seq) {
|
||||
RzILOpArgsSeq *args = &op->op.seq;
|
||||
VALIDATOR_DESCEND_EFFECT(args->x, ctx, {});
|
||||
VALIDATOR_DESCEND_EFFECT(args->y, ctx, {});
|
||||
RzILTypeEffect tx;
|
||||
VALIDATOR_DESCEND_EFFECT(args->x, &tx, ctx, {});
|
||||
RzILTypeEffect ty;
|
||||
VALIDATOR_DESCEND_EFFECT(args->y, &ty, ctx, {});
|
||||
// Code after a jmp/goto makes no sense because the jmp naturally jumps somewhere else already.
|
||||
// Intuitively, this could be considered just dead code and valid, but because it is not practically useful,
|
||||
// we reject such code completely for now, which gives us more freedom if in the future we do want to define
|
||||
// semantics for code after ctrl in some way.
|
||||
VALIDATOR_ASSERT(!(tx & RZ_IL_TYPE_EFFECT_CTRL) || !ty, "Encountered further effects after a ctrl effect in seq op.");
|
||||
*type_out = tx | ty;
|
||||
return true;
|
||||
}
|
||||
|
||||
VALIDATOR_EFFECT(blk) {
|
||||
RzILOpArgsBlk *args = &op->op.blk;
|
||||
// Semantics of blk are still somewhat undefined in RzIL
|
||||
VALIDATOR_DESCEND_EFFECT(args->data_eff, ctx, {});
|
||||
VALIDATOR_DESCEND_EFFECT(args->ctrl_eff, ctx, {});
|
||||
RzILTypeEffect td;
|
||||
VALIDATOR_DESCEND_EFFECT(args->data_eff, &td, ctx, {});
|
||||
VALIDATOR_ASSERT((td | RZ_IL_TYPE_EFFECT_DATA) == RZ_IL_TYPE_EFFECT_DATA, "Data effect operand of blk op does not only perform data effects.");
|
||||
RzILTypeEffect tc;
|
||||
VALIDATOR_DESCEND_EFFECT(args->ctrl_eff, &tc, ctx, {});
|
||||
VALIDATOR_ASSERT((tc | RZ_IL_TYPE_EFFECT_CTRL) == RZ_IL_TYPE_EFFECT_CTRL, "Control effect operand of blk op does not only perform control effects.");
|
||||
*type_out = td | tc;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -758,9 +778,14 @@ VALIDATOR_EFFECT(repeat) {
|
|||
if (!local_context_copy(&loop_ctx, ctx)) {
|
||||
return false;
|
||||
}
|
||||
VALIDATOR_DESCEND_EFFECT(args->data_eff, ctx, { local_context_fini(&loop_ctx); });
|
||||
RzILTypeEffect t;
|
||||
VALIDATOR_DESCEND_EFFECT(args->data_eff, &t, ctx, { local_context_fini(&loop_ctx); });
|
||||
// Enforce (by overapproximation) that there are no effects after a ctrl effect, like in seq.
|
||||
// In a loop, we just reject ctrl completely. This also matches BAP's `repeat : bool -> data eff -> data eff`.
|
||||
VALIDATOR_ASSERT((t | RZ_IL_TYPE_EFFECT_DATA) == RZ_IL_TYPE_EFFECT_DATA, "Body operand of repeat op does not only perform data effects.");
|
||||
bool val = local_context_meet(ctx, &loop_ctx, report_builder, "repeat");
|
||||
local_context_fini(&loop_ctx);
|
||||
*type_out = t;
|
||||
return val;
|
||||
}
|
||||
|
||||
|
|
@ -773,10 +798,13 @@ VALIDATOR_EFFECT(branch) {
|
|||
if (!local_context_copy(&false_ctx, ctx)) {
|
||||
return false;
|
||||
}
|
||||
VALIDATOR_DESCEND_EFFECT(args->true_eff, ctx, { local_context_fini(&false_ctx); });
|
||||
VALIDATOR_DESCEND_EFFECT(args->false_eff, &false_ctx, { local_context_fini(&false_ctx); });
|
||||
RzILTypeEffect tt;
|
||||
VALIDATOR_DESCEND_EFFECT(args->true_eff, &tt, ctx, { local_context_fini(&false_ctx); });
|
||||
RzILTypeEffect tf;
|
||||
VALIDATOR_DESCEND_EFFECT(args->false_eff, &tf, &false_ctx, { local_context_fini(&false_ctx); });
|
||||
bool val = local_context_meet(ctx, &false_ctx, report_builder, "branch");
|
||||
local_context_fini(&false_ctx);
|
||||
*type_out = tt | tf;
|
||||
return val;
|
||||
}
|
||||
|
||||
|
|
@ -797,7 +825,7 @@ static bool validate_effect(VALIDATOR_EFFECT_ARGS) {
|
|||
VALIDATOR_ASSERT(op, "Encountered NULL for effect op.\n");
|
||||
ValidateEffectFn validator = validate_effect_table[op->code];
|
||||
rz_return_val_if_fail(validator, false);
|
||||
return validator(op, report_builder, ctx);
|
||||
return validator(op, type_out, report_builder, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -805,11 +833,13 @@ static bool validate_effect(VALIDATOR_EFFECT_ARGS) {
|
|||
* \p op the op to be checked. May be null, which will always be reported as invalid.
|
||||
* \p ctx global context, defining available global vars and mems
|
||||
* \p local_var_sorts_out optionally returns a map of local variable names defined in the effect to their sorts
|
||||
* \p type_put optionally returns the type of effects that the ops perform, i.e. ctrl, data, both or none
|
||||
* \p report_out optionally returns a readable report containing details about why the validation failed
|
||||
* \return whether the given op is valid under \p ctx
|
||||
*/
|
||||
RZ_API bool rz_il_validate_effect(RZ_NULLABLE RzILOpEffect *op, RZ_NONNULL RzILValidateGlobalContext *ctx,
|
||||
RZ_NULLABLE RZ_OUT HtPP /* <const char *, RzILSortPure *> */ **local_var_sorts_out,
|
||||
RZ_NULLABLE RZ_OUT RzILTypeEffect *type_out,
|
||||
RZ_NULLABLE RZ_OUT RzILValidateReport *report_out) {
|
||||
LocalContext local_ctx;
|
||||
if (!local_context_init(&local_ctx, ctx)) {
|
||||
|
|
@ -818,14 +848,18 @@ RZ_API bool rz_il_validate_effect(RZ_NULLABLE RzILOpEffect *op, RZ_NONNULL RzILV
|
|||
}
|
||||
return false;
|
||||
}
|
||||
RzILTypeEffect type = RZ_IL_TYPE_EFFECT_NONE;
|
||||
RzStrBuf report_builder;
|
||||
rz_strbuf_init(&report_builder);
|
||||
bool valid = validate_effect(op, &report_builder, &local_ctx);
|
||||
bool valid = validate_effect(op, &type, &report_builder, &local_ctx);
|
||||
if (valid && local_var_sorts_out) {
|
||||
*local_var_sorts_out = local_ctx.local_vars_known;
|
||||
local_ctx.local_vars_known = NULL;
|
||||
}
|
||||
local_context_fini(&local_ctx);
|
||||
if (type_out) {
|
||||
*type_out = type;
|
||||
}
|
||||
if (report_out) {
|
||||
*report_out = rz_strbuf_is_empty(&report_builder) ? NULL : rz_str_trim_tail(rz_strbuf_drain_nofree(&report_builder));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,12 @@ static inline RzILSortPure rz_il_sort_pure_bv(ut32 length) {
|
|||
|
||||
RZ_API RZ_OWN char *rz_il_sort_pure_stringify(RzILSortPure sort);
|
||||
|
||||
typedef enum {
|
||||
RZ_IL_TYPE_EFFECT_NONE = 0, ///< nop
|
||||
RZ_IL_TYPE_EFFECT_DATA = (1 << 0), ///< mutating mems, vars, etc.
|
||||
RZ_IL_TYPE_EFFECT_CTRL = (1 << 1) ///< jmp/goto
|
||||
} RzILTypeEffect;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ RZ_API bool rz_il_validate_pure(RZ_NULLABLE RzILOpPure *op, RZ_NONNULL RzILValid
|
|||
RZ_NULLABLE RZ_OUT RzILSortPure *sort_out, RZ_NULLABLE RZ_OUT RzILValidateReport *report_out);
|
||||
RZ_API bool rz_il_validate_effect(RZ_NULLABLE RzILOpEffect *op, RZ_NONNULL RzILValidateGlobalContext *ctx,
|
||||
RZ_NULLABLE RZ_OUT HtPP /* <const char *, RzILSortPure *> */ **local_var_sorts_out,
|
||||
RZ_NULLABLE RZ_OUT RzILTypeEffect *type_out,
|
||||
RZ_NULLABLE RZ_OUT RzILValidateReport *report_out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ static bool print_and_check_il(RzAsmState *as, RzAnalysisOp *op) {
|
|||
rz_strbuf_fini(&sb);
|
||||
}
|
||||
char *report;
|
||||
if (!rz_il_validate_effect(il_op, ctx, NULL, &report)) {
|
||||
if (!rz_il_validate_effect(il_op, ctx, NULL, NULL, &report)) {
|
||||
ret = false;
|
||||
eprintf("IL Validation failed%c\n", report ? ':' : '.');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,8 +184,10 @@ static bool test_il_validate_pure_var() {
|
|||
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)));
|
||||
val = rz_il_validate_effect(eop, ctx, NULL, &report);
|
||||
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);
|
||||
|
||||
|
|
@ -204,7 +206,7 @@ static bool test_il_validate_pure_var() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -581,7 +583,7 @@ 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, &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");
|
||||
|
||||
|
|
@ -594,8 +596,10 @@ static bool test_il_validate_effect_nop() {
|
|||
|
||||
RzILOpEffect *op = rz_il_op_new_nop();
|
||||
RzILValidateReport report;
|
||||
bool val = rz_il_validate_effect(op, ctx, NULL, &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);
|
||||
|
||||
|
|
@ -611,15 +615,17 @@ static bool test_il_validate_effect_store() {
|
|||
rz_il_op_new_bitv_from_ut64(16, 123),
|
||||
rz_il_op_new_bitv_from_ut64(9, 42));
|
||||
RzILValidateReport report;
|
||||
bool val = rz_il_validate_effect(op, ctx, NULL, &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, &report);
|
||||
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);
|
||||
|
|
@ -627,7 +633,7 @@ static bool test_il_validate_effect_store() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -635,7 +641,7 @@ static bool test_il_validate_effect_store() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -643,7 +649,7 @@ static bool test_il_validate_effect_store() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -651,7 +657,7 @@ static bool test_il_validate_effect_store() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -668,15 +674,17 @@ static bool test_il_validate_effect_storew() {
|
|||
rz_il_op_new_bitv_from_ut64(16, 123),
|
||||
rz_il_op_new_bitv_from_ut64(42, 42));
|
||||
RzILValidateReport report;
|
||||
bool val = rz_il_validate_effect(op, ctx, NULL, &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, &report);
|
||||
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);
|
||||
|
|
@ -684,7 +692,7 @@ static bool test_il_validate_effect_storew() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -692,7 +700,7 @@ static bool test_il_validate_effect_storew() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -700,7 +708,7 @@ static bool test_il_validate_effect_storew() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -716,26 +724,28 @@ static bool test_il_validate_effect_set() {
|
|||
// global
|
||||
RzILOpEffect *op = rz_il_op_new_set("x", false, rz_il_op_new_bitv_from_ut64(42, 0));
|
||||
RzILValidateReport report;
|
||||
bool val = rz_il_validate_effect(op, ctx, NULL, &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, &report);
|
||||
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, &report);
|
||||
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, &report);
|
||||
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);
|
||||
|
|
@ -743,7 +753,7 @@ static bool test_il_validate_effect_set() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -751,7 +761,7 @@ static bool test_il_validate_effect_set() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -765,19 +775,21 @@ static bool test_il_validate_effect_jmp() {
|
|||
|
||||
RzILOpEffect *op = rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(24, 0x1000));
|
||||
RzILValidateReport report;
|
||||
bool val = rz_il_validate_effect(op, ctx, NULL, &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, &report);
|
||||
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, &report);
|
||||
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);
|
||||
|
|
@ -791,8 +803,10 @@ static bool test_il_validate_effect_goto() {
|
|||
|
||||
RzILOpEffect *op = rz_il_op_new_goto("beach");
|
||||
RzILValidateReport report;
|
||||
bool val = rz_il_validate_effect(op, ctx, NULL, &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);
|
||||
|
||||
|
|
@ -805,23 +819,67 @@ static bool test_il_validate_effect_seq() {
|
|||
|
||||
RzILOpEffect *op = rz_il_op_new_seq(rz_il_op_new_nop(), rz_il_op_new_nop());
|
||||
RzILValidateReport report;
|
||||
bool val = rz_il_validate_effect(op, ctx, NULL, &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, &report);
|
||||
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, &report);
|
||||
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;
|
||||
}
|
||||
|
|
@ -831,15 +889,17 @@ static bool test_il_validate_effect_blk() {
|
|||
|
||||
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;
|
||||
bool val = rz_il_validate_effect(op, ctx, NULL, &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, &report);
|
||||
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);
|
||||
|
|
@ -847,11 +907,46 @@ static bool test_il_validate_effect_blk() {
|
|||
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, &report);
|
||||
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;
|
||||
}
|
||||
|
|
@ -861,19 +956,21 @@ static bool test_il_validate_effect_repeat() {
|
|||
|
||||
RzILOpEffect *op = rz_il_op_new_repeat(rz_il_op_new_b0(), rz_il_op_new_nop());
|
||||
RzILValidateReport report;
|
||||
bool val = rz_il_validate_effect(op, ctx, NULL, &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, &report);
|
||||
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, &report);
|
||||
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);
|
||||
|
|
@ -884,8 +981,9 @@ static bool test_il_validate_effect_repeat() {
|
|||
// 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, &report);
|
||||
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");
|
||||
|
|
@ -901,7 +999,7 @@ static bool test_il_validate_effect_repeat() {
|
|||
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, &report);
|
||||
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");
|
||||
|
|
@ -921,7 +1019,7 @@ static bool test_il_validate_effect_repeat() {
|
|||
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, &report);
|
||||
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");
|
||||
|
|
@ -941,7 +1039,7 @@ static bool test_il_validate_effect_repeat() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -951,11 +1049,27 @@ static bool test_il_validate_effect_repeat() {
|
|||
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, &report);
|
||||
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;
|
||||
}
|
||||
|
|
@ -965,25 +1079,27 @@ static bool test_il_validate_effect_branch() {
|
|||
|
||||
RzILOpEffect *op = rz_il_op_new_branch(rz_il_op_new_b0(), rz_il_op_new_nop(), rz_il_op_new_nop());
|
||||
RzILValidateReport report;
|
||||
bool val = rz_il_validate_effect(op, ctx, NULL, &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, &report);
|
||||
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, &report);
|
||||
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, &report);
|
||||
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);
|
||||
|
|
@ -996,7 +1112,7 @@ static bool test_il_validate_effect_branch() {
|
|||
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, &report);
|
||||
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");
|
||||
|
|
@ -1016,8 +1132,9 @@ static bool test_il_validate_effect_branch() {
|
|||
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, &report);
|
||||
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");
|
||||
|
|
@ -1033,7 +1150,7 @@ static bool test_il_validate_effect_branch() {
|
|||
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, &report);
|
||||
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");
|
||||
|
|
@ -1052,7 +1169,7 @@ static bool test_il_validate_effect_branch() {
|
|||
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, &report);
|
||||
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");
|
||||
|
|
@ -1074,7 +1191,7 @@ static bool test_il_validate_effect_branch() {
|
|||
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, &report);
|
||||
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");
|
||||
|
|
@ -1094,7 +1211,7 @@ static bool test_il_validate_effect_branch() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -1103,7 +1220,7 @@ static bool test_il_validate_effect_branch() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -1113,7 +1230,7 @@ static bool test_il_validate_effect_branch() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -1122,7 +1239,7 @@ static bool test_il_validate_effect_branch() {
|
|||
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, &report);
|
||||
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);
|
||||
|
|
@ -1134,12 +1251,52 @@ static bool test_il_validate_effect_branch() {
|
|||
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, &report);
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue