From 5e3f5a6bbecb6a83bd1995621bd4e8131943e8a7 Mon Sep 17 00:00:00 2001 From: Inderjeet Singh Date: Thu, 15 Mar 2012 22:27:55 +0000 Subject: [PATCH] Ensuring that the hash is unpredictable and well distributed. We achieve this by using the same algorithm as the Perl version, but this implementation is being written from scratch for license compliance. --- .../com/google/gson/internal/StringMap.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/gson/src/main/java/com/google/gson/internal/StringMap.java b/gson/src/main/java/com/google/gson/internal/StringMap.java index 9c8f17ee..e917542d 100644 --- a/gson/src/main/java/com/google/gson/internal/StringMap.java +++ b/gson/src/main/java/com/google/gson/internal/StringMap.java @@ -25,6 +25,7 @@ import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Random; import java.util.Set; /** @@ -481,12 +482,24 @@ public final class StringMap extends AbstractMap { } } + private static final int seed = new Random().nextInt(); private static int hash(String key) { - // TODO: use an unpredictable hash function - - int h = 0; - for (int i = 0; i < key.length(); i++) { - h = 31 * h + key.charAt(i); + // Ensuring that the hash is unpredictable and well distributed. + // + // Finding unpredictable hash functions is a bit of a dark art as we need to balance + // good unpredictability (to avoid DoS) and good distribution (for performance). + // + // We achieve this by using the same algorithm as the Perl version, but this implementation + // is being written from scratch by inder who has never seen the + // Perl version (for license compliance). + // + // TODO: investigate http://code.google.com/p/cityhash/ and http://code.google.com/p/smhasher/ + // both of which may have better distribution and/or unpredictability. + int h = seed; + for (int i = 0; i < key.length(); ++i) { + int h2 = h + key.charAt(i); + int h3 = h2 + h2 << 10; // h2 * 1024 + h = h3 ^ (h3 >>> 6); // h3 / 64 } /* @@ -496,4 +509,4 @@ public final class StringMap extends AbstractMap { h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); } -} \ No newline at end of file +}