diff options
author | Barry Warsaw <barry@python.org> | 2012-02-21 01:42:21 (GMT) |
---|---|---|
committer | Barry Warsaw <barry@python.org> | 2012-02-21 01:42:21 (GMT) |
commit | 1e13eb084f72d5993cbb726e45b36bdb69c83a24 (patch) | |
tree | 1db691c15c5980a870bcc2606a6d2afc77e28bad /Objects | |
parent | f5a5beb33985b4b55480de267084b90d89a5c5c4 (diff) | |
download | cpython-1e13eb084f72d5993cbb726e45b36bdb69c83a24.zip cpython-1e13eb084f72d5993cbb726e45b36bdb69c83a24.tar.gz cpython-1e13eb084f72d5993cbb726e45b36bdb69c83a24.tar.bz2 |
- Issue #13703: oCERT-2011-003: add -R command-line option and PYTHONHASHSEED
environment variable, to provide an opt-in way to protect against denial of
service attacks due to hash collisions within the dict and set types. Patch
by David Malcolm, based on work by Victor Stinner.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/bufferobject.c | 12 | ||||
-rw-r--r-- | Objects/object.c | 2 | ||||
-rw-r--r-- | Objects/stringobject.c | 12 | ||||
-rw-r--r-- | Objects/unicodeobject.c | 12 |
4 files changed, 35 insertions, 3 deletions
diff --git a/Objects/bufferobject.c b/Objects/bufferobject.c index 0f7e763..c52f0bc 100644 --- a/Objects/bufferobject.c +++ b/Objects/bufferobject.c @@ -334,10 +334,20 @@ buffer_hash(PyBufferObject *self) return -1; p = (unsigned char *) ptr; len = size; - x = *p << 7; + /* + We make the hash of the empty buffer be 0, rather than using + (prefix ^ suffix), since this slightly obfuscates the hash secret + */ + if (len == 0) { + self->b_hash = 0; + return 0; + } + x = _Py_HashSecret.prefix; + x ^= *p << 7; while (--len >= 0) x = (1000003*x) ^ *p++; x ^= size; + x ^= _Py_HashSecret.suffix; if (x == -1) x = -2; self->b_hash = x; diff --git a/Objects/object.c b/Objects/object.c index 424f353..9816541 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1101,6 +1101,8 @@ PyObject_HashNotImplemented(PyObject *self) return -1; } +_Py_HashSecret_t _Py_HashSecret; + long PyObject_Hash(PyObject *v) { diff --git a/Objects/stringobject.c b/Objects/stringobject.c index e37b579..9e2673d 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -1212,11 +1212,21 @@ string_hash(PyStringObject *a) if (a->ob_shash != -1) return a->ob_shash; len = Py_SIZE(a); + /* + We make the hash of the empty string be 0, rather than using + (prefix ^ suffix), since this slightly obfuscates the hash secret + */ + if (len == 0) { + a->ob_shash = 0; + return 0; + } p = (unsigned char *) a->ob_sval; - x = *p << 7; + x = _Py_HashSecret.prefix; + x ^= *p << 7; while (--len >= 0) x = (1000003*x) ^ *p++; x ^= Py_SIZE(a); + x ^= _Py_HashSecret.suffix; if (x == -1) x = -2; a->ob_shash = x; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index d8dab67..2f80e59 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -6695,11 +6695,21 @@ unicode_hash(PyUnicodeObject *self) if (self->hash != -1) return self->hash; len = PyUnicode_GET_SIZE(self); + /* + We make the hash of the empty string be 0, rather than using + (prefix ^ suffix), since this slightly obfuscates the hash secret + */ + if (len == 0) { + self->hash = 0; + return 0; + } p = PyUnicode_AS_UNICODE(self); - x = *p << 7; + x = _Py_HashSecret.prefix; + x ^= *p << 7; while (--len >= 0) x = (1000003*x) ^ *p++; x ^= PyUnicode_GET_SIZE(self); + x ^= _Py_HashSecret.suffix; if (x == -1) x = -2; self->hash = x; |