소스 검색

Remove undefined behavior from the hash function.

Signed integer overflow creates undefined behavior that may lead to unpredictable fails on different platforms.
One known example of the hardware where this code did fail is Apple A6 (32-bit Apple Swift CPU)

16777619, 16777499 - two prime numbers that typically used to get better dispersion.
Eugene Hermann 7 년 전
부모
커밋
72d18e3faa
1개의 변경된 파일7개의 추가작업 그리고 7개의 파일을 삭제
  1. 7 7
      src/google/protobuf/descriptor.cc

+ 7 - 7
src/google/protobuf/descriptor.cc

@@ -406,9 +406,10 @@ typedef std::pair<const EnumDescriptor*, int> EnumIntPair;
 template<typename PairType>
 struct PointerIntegerPairHash {
   size_t operator()(const PairType& p) const {
-    // FIXME(kenton):  What is the best way to compute this hash?  I have
-    // no idea!  This seems a bit better than an XOR.
-    return reinterpret_cast<intptr_t>(p.first) * ((1 << 16) - 1) + p.second;
+    static const size_t prime1 = 16777499;
+    static const size_t prime2 = 16777619;
+    return reinterpret_cast<size_t>(p.first) * prime1 ^
+           static_cast<size_t>(p.second) * prime2;
   }
 
 #ifdef _MSC_VER
@@ -424,11 +425,10 @@ struct PointerIntegerPairHash {
 
 struct PointerStringPairHash {
   size_t operator()(const PointerStringPair& p) const {
-    // FIXME(kenton):  What is the best way to compute this hash?  I have
-    // no idea!  This seems a bit better than an XOR.
+    static const size_t prime = 16777619;
     hash<const char*> cstring_hash;
-    return reinterpret_cast<intptr_t>(p.first) * ((1 << 16) - 1) +
-           cstring_hash(p.second);
+    return reinterpret_cast<size_t>(p.first) * prime ^
+           static_cast<size_t>(cstring_hash(p.second));
   }
 
 #ifdef _MSC_VER