mirror of https://github.com/python/cpython
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:
parent
90555d0f0d
commit
27cbcd6241
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue