diff --git a/libr/esil/esil.c b/libr/esil/esil.c index 0e59f79a99..c82de1473a 100644 --- a/libr/esil/esil.c +++ b/libr/esil/esil.c @@ -18,7 +18,7 @@ #define IFDBG if (esil && esil->verbose > 1) static inline void free_ornot(void *p) { - R_CONST_FREE (p); + R_TAG_FREE (p); } /* Returns the number that has bits + 1 least significant bits set. */ @@ -54,7 +54,7 @@ static bool r_esil_runpending(REsil *esil, char *pending) { } else if (esil->pending) { char *expr = esil->pending; esil->pending = NULL; - r_esil_parse (esil, R_CONST_UNTAG (expr)); + r_esil_parse (esil, R_TAG_NOP (expr)); free_ornot (expr); return true; } diff --git a/libr/include/r_types_base.h b/libr/include/r_types_base.h index 82134b013a..fb2dd5018f 100644 --- a/libr/include/r_types_base.h +++ b/libr/include/r_types_base.h @@ -263,11 +263,24 @@ typedef struct _utX { #define R_IS_DIRTY(x) (x)->is_dirty #define R_DIRTY_VAR bool is_dirty -#define R_CONST_MAYBE -#define R_CONST_TAG(x) ((x)|1) -#define R_CONST_UNTAG(x) (void*)((((size_t)x)>>1)<<1) -#define R_CONST_FREE(x) do { if (!((size_t)(x)&1)) { R_FREE(x); }} while(0) -#define R_IS_CONST(x) ((size_t)(x)&1)) +#define R_TAG(x) (void*)((size_t)(x)|1) +#define R_UNTAG(x) (void*)((((size_t)(x))&(size_t)-2)) +#define R_TAG_FREE(x) do { if (!((size_t)(x)&1)) { R_FREE(x); }} while(0) +#define R_TAG_NOP(x) untagged_pointer_check(x) +#define R_IS_TAGGED(x) ((size_t)(x)&1) +#define R_TAGGED +#if R_CHECKS_LEVEL == 0 +static inline void *untagged_pointer_check(void *x) { + return x; +} +#else +static inline void *untagged_pointer_check(void *x) { + if (R_IS_TAGGED(x)) { + int *p = (int*)0; *p = 0; + } + return x; +} +#endif #ifdef __cplusplus } diff --git a/test/unit/test_util.c b/test/unit/test_util.c index d5325398f7..83bdaa1b4e 100644 --- a/test/unit/test_util.c +++ b/test/unit/test_util.c @@ -151,11 +151,34 @@ bool test_file_slurp(void) { mu_end; } +R_ALIGNED(4) static const char msg[] = "Hello World"; // const strings can have the lowerbit set +R_TAGGED void *tagged(bool owned) { + if (owned) { + void *res = strdup ("hello world"); + return R_TAG_NOP (res); + } + return R_TAG (msg); +} + +bool test_tagged_pointers(void) { + void *a = tagged (false); + void *b = tagged (true); + // eprintf ("%p %p\n", a, b); + // eprintf ("%d %d\n", (size_t)a&1, (size_t)b&1); + mu_assert_eq (R_IS_TAGGED (a), 1, "tagged"); + char *msg = R_UNTAG (a); + mu_assert_streq (msg, "Hello World", "faileq"); + mu_assert_eq (R_IS_TAGGED (b), 0, "not tagged"); + char *msg2 = R_UNTAG (b); + mu_assert_streq (msg2, "hello world", "faileq"); + R_TAG_FREE (a); + R_TAG_FREE (b); + mu_end; +} + bool test_initial_underscore(void) { Sdb *TDB = setup_sdb (); - char *s; - - s = r_type_func_guess (TDB, "sym._strchr"); + char *s = r_type_func_guess (TDB, "sym._strchr"); mu_assert_notnull (s, "sym._ should be ignored"); mu_assert_streq (s, "strchr", "strchr should be identified"); free (s); @@ -212,6 +235,7 @@ int all_tests() { mu_run_test (test_autonames); mu_run_test (test_file_slurp); mu_run_test (test_initial_underscore); + mu_run_test (test_tagged_pointers); return tests_passed != tests_run; }