From 4556cb8fa90f96696fc42e7274fed5ee7c8ad8c2 Mon Sep 17 00:00:00 2001 From: Arne Goedeke <el@laramies.com> Date: Fri, 24 Oct 2014 18:40:26 +0200 Subject: [PATCH] hash_value: fix hashing of trampolines Two trampolines are equal if there are the same function and created in the same scope. This patch makes sure hash_svalue is compatible and trampolines can now be reliably used as hash keys. Thanks to Stefan Gluszek <stefang@opera.com> for reporting this issue. --- src/svalue.c | 26 +++++++++++++++++++++----- src/testsuite.in | 17 +++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/svalue.c b/src/svalue.c index 0f960b2e53..40704c8473 100644 --- a/src/svalue.c +++ b/src/svalue.c @@ -408,6 +408,14 @@ PMOD_EXPORT void assign_short_svalue(union anything *to, } } +static INLINE unsigned INT32 hash_ptr(void * ptr) { +#if SIZEOF_CHAR_P > 4 + return DO_NOT_WARN((unsigned INT32)(PTR_TO_INT(ptr) >> 2)); +#else + return DO_NOT_WARN((unsigned INT32)(PTR_TO_INT(ptr))); +#endif +} + PMOD_EXPORT unsigned INT32 hash_svalue(const struct svalue *s) { unsigned INT32 q; @@ -450,11 +458,19 @@ PMOD_EXPORT unsigned INT32 hash_svalue(const struct svalue *s) } /* FALL THROUGH */ default: -#if SIZEOF_CHAR_P > 4 - q=DO_NOT_WARN((unsigned INT32)(PTR_TO_INT(s->u.ptr) >> 2)); -#else - q=DO_NOT_WARN((unsigned INT32)(PTR_TO_INT(s->u.ptr))); -#endif + q = hash_ptr(s->u.ptr); + break; + case T_FUNCTION: + if ((SUBTYPEOF(*s) != FUNCTION_BUILTIN) && s->u.object + && s->u.object->prog == pike_trampoline_program) { + + struct pike_trampoline *tramp = get_storage(s->u.object, pike_trampoline_program); + if (tramp) { + q = (unsigned INT32)tramp->func ^ hash_ptr(tramp->frame); + break; + } + } + q = hash_ptr(s->u.ptr); break; case T_INT: q=(unsigned INT32) s->u.integer; diff --git a/src/testsuite.in b/src/testsuite.in index 2091c40487..74ca4df03c 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -11035,6 +11035,23 @@ test_hash_value(time) test_hash_value(ADT.Stack) dnl test_hash_value(String) test_hash_value(typeof(true)) +test_any([[ + int v = 0; + + void trampoline() { + v = 1; + }; + + int(0..1) check_hash() + { + function f1 = trampoline; + function f2 = trampoline; + return hash_value(f1) == hash_value(f2); + }; + + return check_hash(); +]], 1) + // - indices test_equal(indices("foo"),({0,1,2})) -- GitLab