summaryrefslogtreecommitdiff
path: root/hv_func.h
diff options
context:
space:
mode:
authorYves Orton <demerphq@gmail.com>2012-12-10 08:36:43 +0100
committerYves Orton <demerphq@gmail.com>2013-03-19 00:23:11 +0100
commitb1300a738fa7f7665aa35a1f9347cf71c52a5b6e (patch)
tree557ece3739433518cfb786e53cfe3445caef2b0d /hv_func.h
parent4d3a042da1832ef30203f1ded27917696c9d86a9 (diff)
downloadperl-b1300a738fa7f7665aa35a1f9347cf71c52a5b6e.tar.gz
add a hardened one-at-a-time hash variant
Mix in additional randomness into the final value.
Diffstat (limited to 'hv_func.h')
-rw-r--r--hv_func.h49
1 files changed, 46 insertions, 3 deletions
diff --git a/hv_func.h b/hv_func.h
index fdb4ad8b41..df39808a0a 100644
--- a/hv_func.h
+++ b/hv_func.h
@@ -18,12 +18,13 @@
|| defined(PERL_HASH_FUNC_SUPERFAST) \
|| defined(PERL_HASH_FUNC_MURMUR3) \
|| defined(PERL_HASH_FUNC_ONE_AT_A_TIME) \
+ || defined(PERL_HASH_FUNC_ONE_AT_A_TIME_HARD) \
|| defined(PERL_HASH_FUNC_ONE_AT_A_TIME_OLD) \
)
#ifdef HAS_QUAD
#define PERL_HASH_FUNC_SIPHASH
#else
-#define PERL_HASH_FUNC_ONE_AT_A_TIME
+#define PERL_HASH_FUNC_ONE_AT_A_TIME_HARD
#endif
#endif
@@ -47,6 +48,10 @@
# define PERL_HASH_FUNC "SDBM"
# define PERL_HASH_SEED_BYTES 4
# define PERL_HASH(hash,str,len) (hash)= S_perl_hash_sdbm(PERL_HASH_SEED,(U8*)(str),(len))
+#elif defined(PERL_HASH_FUNC_ONE_AT_A_TIME_HARD)
+# define PERL_HASH_FUNC "ONE_AT_A_TIME_HARD"
+# define PERL_HASH_SEED_BYTES 8
+# define PERL_HASH(hash,str,len) (hash)= S_perl_hash_one_at_a_time_hard(PERL_HASH_SEED,(U8*)(str),(len))
#elif defined(PERL_HASH_FUNC_ONE_AT_A_TIME)
# define PERL_HASH_FUNC "ONE_AT_A_TIME"
# define PERL_HASH_SEED_BYTES 4
@@ -460,9 +465,11 @@ S_perl_hash_sdbm(const unsigned char * const seed, const unsigned char *str, con
}
-/* FYI: This is the "One-at-a-Time" algorithm by Bob Jenkins
+/* This is the "One-at-a-Time" algorithm by Bob Jenkins
* from requirements by Colin Plumb.
- * (http://burtleburtle.net/bob/hash/doobs.html) */
+ * (http://burtleburtle.net/bob/hash/doobs.html)
+ * With seed/len tweak.
+ * */
PERL_STATIC_INLINE U32
S_perl_hash_one_at_a_time(const unsigned char * const seed, const unsigned char *str, const STRLEN len) {
const unsigned char * const end = (const unsigned char *)str + len;
@@ -477,6 +484,42 @@ S_perl_hash_one_at_a_time(const unsigned char * const seed, const unsigned char
return (hash + (hash << 15));
}
+/* Derived from "One-at-a-Time" algorithm by Bob Jenkins */
+PERL_STATIC_INLINE U32
+S_perl_hash_one_at_a_time_hard(const unsigned char * const seed, const unsigned char *str, const STRLEN len) {
+ const unsigned char * const end = (const unsigned char *)str + len;
+ U32 hash = *((U32*)seed) + len;
+
+ while (str < end) {
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ hash += *str++;
+ }
+
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ hash += seed[4];
+
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ hash += seed[5];
+
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ hash += seed[6];
+
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ hash += seed[7];
+
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ return (hash + (hash << 15));
+}
+
PERL_STATIC_INLINE U32
S_perl_hash_old_one_at_a_time(const unsigned char * const seed, const unsigned char *str, const STRLEN len) {
const unsigned char * const end = (const unsigned char *)str + len;