]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Fix the internals of our hash functions to used unsigned values during hash
authorGregory P. Smith <greg@krypto.org>
Tue, 11 Dec 2012 02:32:53 +0000 (18:32 -0800)
committerGregory P. Smith <greg@krypto.org>
Tue, 11 Dec 2012 02:32:53 +0000 (18:32 -0800)
computation as the overflow behavior of signed integers is undefined.

NOTE: This change is smaller compared to 3.2 as much of this cleanup had
already been done.  I added the comment that my change in 3.2 added so that the
code would match up.  Otherwise this just adds or synchronizes appropriate UL
designations on some constants to be pedantic.

In practice we require compiling everything with -fwrapv which forces overflow
to be defined as twos compliment but this keeps the code cleaner for checkers
or in the case where someone has compiled it without -fwrapv or their
compiler's equivalent.

Found by Clang trunk's Undefined Behavior Sanitizer (UBSan).

Cleanup only - no functionality or hash values change.

1  2 
Include/pyport.h
Objects/setobject.c
Objects/tupleobject.c
Objects/unicodeobject.c

index 41d9d42e639af43cc50424c980da1d6f26820b3e,c74ff9c7a4b4628746d4c9ced50a95c3580351bd..e4e3601d7bd04fa523bf27934dff993668397fa7
@@@ -145,10 -145,10 +145,10 @@@ Used in:  PY_LONG_LON
  #endif
  
  /* Prime multiplier used in string and various other hashes. */
- #define _PyHASH_MULTIPLIER 1000003  /* 0xf4243 */
+ #define _PyHASH_MULTIPLIER 1000003UL  /* 0xf4243 */
  
  /* Parameters used for the numeric hash implementation.  See notes for
 -   _PyHash_Double in Objects/object.c.  Numeric hashes are based on
 +   _Py_HashDouble in Objects/object.c.  Numeric hashes are based on
     reduction modulo the prime 2**_PyHASH_BITS - 1. */
  
  #if SIZEOF_VOID_P >= 8
index 723679a7e6ef33b5c6a40e38eb30585124e6fb07,d8401f4ae746cc722249bbcacb26cc55a93c7644..c484dce41389e78493ac979633f4aeb33665b622
@@@ -775,11 -783,11 +775,11 @@@ frozenset_hash(PyObject *self
             hashes so that many distinct combinations collapse to only
             a handful of distinct hash values. */
          h = entry->hash;
-         hash ^= (h ^ (h << 16) ^ 89869747U)  * 3644798167U;
+         hash ^= (h ^ (h << 16) ^ 89869747UL)  * 3644798167UL;
      }
-     hash = hash * 69069U + 907133923U;
 -    hash = hash * 69069UL + 907133923UL;
++    hash = hash * 69069U + 907133923UL;
      if (hash == -1)
-         hash = 590923713U;
+         hash = 590923713UL;
      so->hash = hash;
      return hash;
  }
index 9c843fa9814a3e8017fe542400c47c4222f8964d,c725227979bc09d12107459f79e0edacad8981f3..ec3f91b2c65f8faa7f8e9f313d29bc2ecbe95b28
@@@ -327,8 -315,7 +327,8 @@@ error
  static Py_hash_t
  tuplehash(PyTupleObject *v)
  {
-     register Py_uhash_t x;
 -    register Py_uhash_t x, y;  /* Unsigned for defined overflow behavior. */
++    register Py_uhash_t x;  /* Unsigned for defined overflow behavior. */
 +    register Py_hash_t y;
      register Py_ssize_t len = Py_SIZE(v);
      register PyObject **p;
      Py_uhash_t mult = _PyHASH_MULTIPLIER;
              return -1;
          x = (x ^ y) * mult;
          /* the cast might truncate len; that doesn't change hash stability */
-         mult += (Py_hash_t)(82520L + len + len);
 -        mult += (Py_uhash_t)(82520UL + len + len);
++        mult += (Py_hash_t)(82520UL + len + len);
      }
-     x += 97531L;
+     x += 97531UL;
 -    if (x == -1)
 +    if (x == (Py_uhash_t)-1)
          x = -2;
      return x;
  }
index 60a74d620087ce18de649140b4a14ea79eaa666a,bb45b20b90cd46a1a10f25d78dc25c9304d48840..0b9d65291f70245b25d8fded825609620a478401
@@@ -11003,12 -7680,13 +11003,12 @@@ unicode_getitem(PyObject *self, Py_ssiz
  }
  
  /* Believe it or not, this produces the same value for ASCII strings
 -   as string_hash(). */
 +   as bytes_hash(). */
  static Py_hash_t
 -unicode_hash(PyUnicodeObject *self)
 +unicode_hash(PyObject *self)
  {
      Py_ssize_t len;
-     Py_uhash_t x;
 -    Py_UNICODE *p;
+     Py_uhash_t x;  /* Unsigned for defined overflow behavior. */
  
  #ifdef Py_DEBUG
      assert(_Py_HashSecret_Initialized);