From ec02889e9cca36e5e77ad4bccfddcb239093a0f9 Mon Sep 17 00:00:00 2001 From: Rot127 <45763064+Rot127@users.noreply.github.com> Date: Fri, 27 Feb 2026 11:51:35 +0000 Subject: [PATCH] RzIL: Hash Pure variable names to make them more suitable as hash table keys. (#5971) * Pre-compute DJB2 hash of VAR name for internal hash map key usage. * IL VARS hash: Hash variable name. * Add tests --- librz/il/il_opcodes.c | 5 +++++ librz/include/rz_il/rz_il_opcodes.h | 3 +++ test/unit/test_il_validate.c | 3 +++ 3 files changed, 11 insertions(+) diff --git a/librz/il/il_opcodes.c b/librz/il/il_opcodes.c index d4005bbf1e..59da677c86 100644 --- a/librz/il/il_opcodes.c +++ b/librz/il/il_opcodes.c @@ -66,6 +66,7 @@ RZ_API RZ_OWN RzILOpPure *rz_il_op_new_var(RZ_NONNULL const char *v, RzILVarKind rz_return_val_if_fail(v, NULL); RzILOpPure *ret; rz_il_op_new_2(Pure, RZ_IL_OP_VAR, RzILOpArgsVar, var, v, kind); + ret->op.var.hash = rz_str_djb2_hash(v); return ret; } @@ -76,6 +77,7 @@ RZ_API RZ_OWN RzILOpPure *rz_il_op_new_let(RZ_NONNULL const char *name, RZ_NONNU rz_return_val_if_fail(name && exp && body, NULL); RzILOpPure *ret; rz_il_op_new_3(Pure, RZ_IL_OP_LET, RzILOpArgsLet, let, name, exp, body); + ret->op.let.hash = rz_str_djb2_hash(name); return ret; } @@ -578,6 +580,7 @@ RZ_API RZ_OWN RzILOpEffect *rz_il_op_new_set(RZ_NONNULL const char *v, bool is_l rz_return_val_if_fail(v && x, NULL); RzILOpEffect *ret; rz_il_op_new_3(Effect, RZ_IL_OP_SET, RzILOpArgsSet, set, v, is_local, x); + ret->op.set.hash = rz_str_djb2_hash(v); return ret; } @@ -1090,6 +1093,7 @@ RZ_API RzILOpPure *rz_il_op_pure_dup(RZ_NONNULL RzILOpPure *op) { switch (op->code) { case RZ_IL_OP_VAR: r->op.var.v = op->op.var.v; + r->op.var.hash = op->op.var.hash; r->op.var.kind = op->op.var.kind; break; case RZ_IL_OP_ITE: @@ -1097,6 +1101,7 @@ RZ_API RzILOpPure *rz_il_op_pure_dup(RZ_NONNULL RzILOpPure *op) { break; case RZ_IL_OP_LET: r->op.let.name = op->op.let.name; + r->op.let.hash = op->op.let.hash; DUP_OP2(let, exp, body); break; case RZ_IL_OP_B0: diff --git a/librz/include/rz_il/rz_il_opcodes.h b/librz/include/rz_il/rz_il_opcodes.h index cb4fc81d3e..1d9522a468 100644 --- a/librz/include/rz_il/rz_il_opcodes.h +++ b/librz/include/rz_il/rz_il_opcodes.h @@ -167,6 +167,7 @@ typedef struct rz_il_op_args_shift_t RzILOpArgsShiftRight; */ typedef struct rz_il_op_args_set_t { const char *v; ///< name of variable, const one + ut64 hash; ///< DJB2 hash of variable name bool is_local; ///< whether a global variable should be set or a local optionally created and set RzILOpPure *x; ///< value to set the variable to } RzILOpArgsSet; @@ -178,6 +179,7 @@ typedef struct rz_il_op_args_set_t { */ typedef struct rz_il_op_args_let_t { const char *name; ///< name of variable + ut64 hash; ///< DJB2 hash of variable name RzILOpPure *exp; ///< value/expression to bind the variable to RzILOpPure *body; ///< body in which the variable will be bound and that produces the result } RzILOpArgsLet; @@ -260,6 +262,7 @@ typedef struct rz_il_op_args_ite_t { */ typedef struct rz_il_op_args_var_t { const char *v; ///< name of variable, const one + ut64 hash; ///< The DJB2 hash of the name. RzILVarKind kind; ///< set of variables to pick from } RzILOpArgsVar; diff --git a/test/unit/test_il_validate.c b/test/unit/test_il_validate.c index c119755f46..ab8fe41610 100644 --- a/test/unit/test_il_validate.c +++ b/test/unit/test_il_validate.c @@ -103,6 +103,7 @@ static bool test_il_validate_pure_let() { RzILSortPure sort; RzILValidateReport report; bool val = rz_il_validate_pure(op, ctx, &sort, &report); + mu_assert_eq(op->op.let.hash, rz_str_djb2_hash("x"), "Hash mismatch"); 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"); @@ -179,6 +180,7 @@ static bool test_il_validate_pure_var() { 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"); + mu_assert_eq(op->op.var.hash, rz_str_djb2_hash("y"), "Hash mismatch"); rz_il_op_pure_free(op); RzILOpEffect *eop = rz_il_op_new_seq( @@ -195,6 +197,7 @@ static bool test_il_validate_pure_var() { 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"); + mu_assert_eq(op->op.var.hash, rz_str_djb2_hash("x"), "Hash mismatch"); rz_il_op_pure_free(op); op = rz_il_op_new_var("x", RZ_IL_VAR_KIND_LOCAL);