Fix the internals of our hash functions to used unsigned values during hash

computation as the overflow behavior of signed integers is undefined.

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.
This commit is contained in:
Gregory P. Smith 2012-12-10 18:15:46 -08:00
parent 90555d0f0d
commit 27cbcd6241
5 changed files with 14 additions and 14 deletions

View File

@ -145,7 +145,7 @@ Used in: PY_LONG_LONG
#endif #endif
/* Prime multiplier used in string and various other hashes. */ /* 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 /* Parameters used for the numeric hash implementation. See notes for
_PyHash_Double in Objects/object.c. Numeric hashes are based on _PyHash_Double in Objects/object.c. Numeric hashes are based on

View File

@ -873,7 +873,7 @@ bytes_hash(PyBytesObject *a)
{ {
register Py_ssize_t len; register Py_ssize_t len;
register unsigned char *p; register unsigned char *p;
register Py_hash_t x; register Py_uhash_t x; /* Unsigned for defined overflow behavior. */
#ifdef Py_DEBUG #ifdef Py_DEBUG
assert(_Py_HashSecret_Initialized); assert(_Py_HashSecret_Initialized);

View File

@ -77,7 +77,7 @@ NULL if the rich comparison returns an error.
static setentry * static setentry *
set_lookkey(PySetObject *so, PyObject *key, register Py_hash_t hash) set_lookkey(PySetObject *so, PyObject *key, register Py_hash_t hash)
{ {
register Py_ssize_t i; register size_t i; /* Unsigned for defined overflow behavior. */
register size_t perturb; register size_t perturb;
register setentry *freeslot; register setentry *freeslot;
register size_t mask = so->mask; register size_t mask = so->mask;
@ -159,7 +159,7 @@ set_lookkey(PySetObject *so, PyObject *key, register Py_hash_t hash)
static setentry * static setentry *
set_lookkey_unicode(PySetObject *so, PyObject *key, register Py_hash_t hash) set_lookkey_unicode(PySetObject *so, PyObject *key, register Py_hash_t hash)
{ {
register Py_ssize_t i; register size_t i; /* Unsigned for defined overflow behavior. */
register size_t perturb; register size_t perturb;
register setentry *freeslot; register setentry *freeslot;
register size_t mask = so->mask; register size_t mask = so->mask;
@ -768,7 +768,7 @@ static Py_hash_t
frozenset_hash(PyObject *self) frozenset_hash(PyObject *self)
{ {
PySetObject *so = (PySetObject *)self; PySetObject *so = (PySetObject *)self;
Py_hash_t h, hash = 1927868237L; Py_uhash_t h, hash = 1927868237UL;
setentry *entry; setentry *entry;
Py_ssize_t pos = 0; Py_ssize_t pos = 0;
@ -783,11 +783,11 @@ frozenset_hash(PyObject *self)
hashes so that many distinct combinations collapse to only hashes so that many distinct combinations collapse to only
a handful of distinct hash values. */ a handful of distinct hash values. */
h = entry->hash; h = entry->hash;
hash ^= (h ^ (h << 16) ^ 89869747L) * 3644798167u; hash ^= (h ^ (h << 16) ^ 89869747UL) * 3644798167UL;
} }
hash = hash * 69069L + 907133923L; hash = hash * 69069UL + 907133923UL;
if (hash == -1) if (hash == -1)
hash = 590923713L; hash = 590923713UL;
so->hash = hash; so->hash = hash;
return hash; return hash;
} }

View File

@ -315,11 +315,11 @@ error:
static Py_hash_t static Py_hash_t
tuplehash(PyTupleObject *v) tuplehash(PyTupleObject *v)
{ {
register Py_hash_t x, y; register Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
register Py_ssize_t len = Py_SIZE(v); register Py_ssize_t len = Py_SIZE(v);
register PyObject **p; register PyObject **p;
Py_hash_t mult = _PyHASH_MULTIPLIER; Py_uhash_t mult = _PyHASH_MULTIPLIER;
x = 0x345678L; x = 0x345678UL;
p = v->ob_item; p = v->ob_item;
while (--len >= 0) { while (--len >= 0) {
y = PyObject_Hash(*p++); y = PyObject_Hash(*p++);
@ -327,9 +327,9 @@ tuplehash(PyTupleObject *v)
return -1; return -1;
x = (x ^ y) * mult; x = (x ^ y) * mult;
/* the cast might truncate len; that doesn't change hash stability */ /* 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);
} }
x += 97531L; x += 97531UL;
if (x == -1) if (x == -1)
x = -2; x = -2;
return x; return x;

View File

@ -7686,7 +7686,7 @@ unicode_hash(PyUnicodeObject *self)
{ {
Py_ssize_t len; Py_ssize_t len;
Py_UNICODE *p; Py_UNICODE *p;
Py_hash_t x; Py_uhash_t x; /* Unsigned for defined overflow behavior. */
#ifdef Py_DEBUG #ifdef Py_DEBUG
assert(_Py_HashSecret_Initialized); assert(_Py_HashSecret_Initialized);