From de12cebee17ce9faee2ef09e8dc46cdd0b143589 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Wed, 6 Oct 2021 14:03:45 +0900 Subject: [PATCH 01/18] Use SipHash-1-3 instead of SipHash-2-4. --- Include/pyhash.h | 8 ++++---- Python/pyhash.c | 23 +++++++++++------------ configure.ac | 8 ++++---- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/Include/pyhash.h b/Include/pyhash.h index a314ea907b7fe2..d199241243b074 100644 --- a/Include/pyhash.h +++ b/Include/pyhash.h @@ -114,11 +114,11 @@ PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); /* hash algorithm selection * - * The values for Py_HASH_SIPHASH24 and Py_HASH_FNV are hard-coded in the + * The values for Py_HASH_SIPHASH13 and Py_HASH_FNV are hard-coded in the * configure script. * * - FNV is available on all platforms and architectures. - * - SIPHASH24 only works on platforms that don't require aligned memory for integers. + * - SIPHASH only works on platforms that don't require aligned memory for integers. * - With EXTERNAL embedders can provide an alternative implementation with:: * * PyHash_FuncDef PyHash_Func = {...}; @@ -126,12 +126,12 @@ PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); * XXX: Figure out __declspec() for extern PyHash_FuncDef. */ #define Py_HASH_EXTERNAL 0 -#define Py_HASH_SIPHASH24 1 +#define Py_HASH_SIPHASH 1 #define Py_HASH_FNV 2 #ifndef Py_HASH_ALGORITHM # ifndef HAVE_ALIGNED_REQUIRED -# define Py_HASH_ALGORITHM Py_HASH_SIPHASH24 +# define Py_HASH_ALGORITHM Py_HASH_SIPHASH # else # define Py_HASH_ALGORITHM Py_HASH_FNV # endif /* uint64_t && uint32_t && aligned */ diff --git a/Python/pyhash.c b/Python/pyhash.c index f0c82356f1e26c..60ed73b171052a 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -364,15 +364,13 @@ static PyHash_FuncDef PyHash_Func = {fnv, "fnv", 8 * SIZEOF_PY_HASH_T, d = ROTATE(d, t) ^ c; \ a = ROTATE(a, 32); -#define DOUBLE_ROUND(v0,v1,v2,v3) \ - HALF_ROUND(v0,v1,v2,v3,13,16); \ - HALF_ROUND(v2,v1,v0,v3,17,21); \ +#define SINGLE_ROUND(v0,v1,v2,v3) \ HALF_ROUND(v0,v1,v2,v3,13,16); \ HALF_ROUND(v2,v1,v0,v3,17,21); static uint64_t -siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { +siphash13(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { uint64_t b = (uint64_t)src_sz << 56; const uint8_t *in = (const uint8_t*)src; @@ -391,7 +389,7 @@ siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { in += sizeof(mi); src_sz -= sizeof(mi); v3 ^= mi; - DOUBLE_ROUND(v0,v1,v2,v3); + SINGLE_ROUND(v0,v1,v2,v3); v0 ^= mi; } @@ -409,11 +407,12 @@ siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { b |= _le64toh(t); v3 ^= b; - DOUBLE_ROUND(v0,v1,v2,v3); + SINGLE_ROUND(v0,v1,v2,v3); v0 ^= b; v2 ^= 0xff; - DOUBLE_ROUND(v0,v1,v2,v3); - DOUBLE_ROUND(v0,v1,v2,v3); + SINGLE_ROUND(v0,v1,v2,v3); + SINGLE_ROUND(v0,v1,v2,v3); + SINGLE_ROUND(v0,v1,v2,v3); /* modified */ t = (v0 ^ v1) ^ (v2 ^ v3); @@ -423,19 +422,19 @@ siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { uint64_t _Py_KeyedHash(uint64_t key, const void *src, Py_ssize_t src_sz) { - return siphash24(key, 0, src, src_sz); + return siphash13(key, 0, src, src_sz); } -#if Py_HASH_ALGORITHM == Py_HASH_SIPHASH24 +#if Py_HASH_ALGORITHM == Py_HASH_SIPHASH static Py_hash_t pysiphash(const void *src, Py_ssize_t src_sz) { - return (Py_hash_t)siphash24( + return (Py_hash_t)siphash13( _le64toh(_Py_HashSecret.siphash.k0), _le64toh(_Py_HashSecret.siphash.k1), src, src_sz); } -static PyHash_FuncDef PyHash_Func = {pysiphash, "siphash24", 64, 128}; +static PyHash_FuncDef PyHash_Func = {pysiphash, "siphash13", 64, 128}; #endif #ifdef __cplusplus diff --git a/configure.ac b/configure.ac index 48d86ef79199e1..8964f0dca7e014 100644 --- a/configure.ac +++ b/configure.ac @@ -3036,17 +3036,17 @@ fi # str, bytes and memoryview hash algorithm AH_TEMPLATE(Py_HASH_ALGORITHM, [Define hash algorithm for str, bytes and memoryview. - SipHash24: 1, FNV: 2, externally defined: 0]) + SipHash: 1, FNV: 2, externally defined: 0]) AC_MSG_CHECKING(for --with-hash-algorithm) dnl quadrigraphs "@<:@" and "@:>@" produce "[" and "]" in the output AC_ARG_WITH(hash_algorithm, - AS_HELP_STRING([--with-hash-algorithm=@<:@fnv|siphash24@:>@], - [select hash algorithm for use in Python/pyhash.c (default is SipHash24)]), + AS_HELP_STRING([--with-hash-algorithm=@<:@fnv|siphash@:>@], + [select hash algorithm for use in Python/pyhash.c (default is SipHash)]), [ AC_MSG_RESULT($withval) case "$withval" in - siphash24) + siphash) AC_DEFINE(Py_HASH_ALGORITHM, 1) ;; fnv) From 196d5a640b635bfd663076f0179283e761e2b19c Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Wed, 6 Oct 2021 17:57:44 +0900 Subject: [PATCH 02/18] fix tests --- Lib/test/test_hash.py | 12 ++++++------ Lib/test/test_imp.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_hash.py b/Lib/test/test_hash.py index c68e0d8f815377..c5e75b848f5816 100644 --- a/Lib/test/test_hash.py +++ b/Lib/test/test_hash.py @@ -206,18 +206,18 @@ class StringlikeHashRandomizationTests(HashRandomizationTests): # seed 42, 'abc' [-678966196, 573763426263223372, -820489388, -4282905804826039665], ], - 'siphash24': [ + 'siphash': [ # NOTE: PyUCS2 layout depends on endianness # seed 0, 'abc' - [1198583518, 4596069200710135518, 1198583518, 4596069200710135518], + [1198583518, 4596069200710135518, 1198583518, -4594863902769663758], # seed 42, 'abc' - [273876886, -4501618152524544106, 273876886, -4501618152524544106], + [273876886, -4501618152524544106, 273876886, 3869580338025362921], # seed 42, 'abcdefghijk' - [-1745215313, 4436719588892876975, -1745215313, 4436719588892876975], + [-1745215313, 4436719588892876975, -1745215313, 7764564197781545852], # seed 0, 'äú∑ℇ' - [493570806, 5749986484189612790, -1006381564, -5915111450199468540], + [493570806, 5749986484189612790, -1006381564, -2810468059467891395], # seed 42, 'äú∑ℇ' - [-1677110816, -2947981342227738144, -1860207793, -4296699217652516017], + [-1677110816, -2947981342227738144, -1860207793, -2845126246016066802], ], 'fnv': [ # seed 0, 'abc' diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py index 99312cc1625c42..1a21025fe6eaff 100644 --- a/Lib/test/test_imp.py +++ b/Lib/test/test_imp.py @@ -351,8 +351,8 @@ def test_issue_35321(self): self.assertEqual(_frozen_importlib.__spec__.origin, "frozen") def test_source_hash(self): - self.assertEqual(_imp.source_hash(42, b'hi'), b'\xc6\xe7Z\r\x03:}\xab') - self.assertEqual(_imp.source_hash(43, b'hi'), b'\x85\x9765\xf8\x9a\x8b9') + self.assertEqual(_imp.source_hash(42, b'hi'), b'\xfb\xd9G\x05\xaf$\x9b~') + self.assertEqual(_imp.source_hash(43, b'hi'), b'\xd0/\x87C\xccC\xff\xe2') def test_pyc_invalidation_mode_from_cmdline(self): cases = [ From b121503b9dfb1f97182466f7d6f521e8f86cded3 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Thu, 7 Oct 2021 17:10:43 +0900 Subject: [PATCH 03/18] Update Lib/test/test_hash.py Co-authored-by: Erlend Egeberg Aasland --- Lib/test/test_hash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_hash.py b/Lib/test/test_hash.py index c5e75b848f5816..626086415482f1 100644 --- a/Lib/test/test_hash.py +++ b/Lib/test/test_hash.py @@ -206,7 +206,7 @@ class StringlikeHashRandomizationTests(HashRandomizationTests): # seed 42, 'abc' [-678966196, 573763426263223372, -820489388, -4282905804826039665], ], - 'siphash': [ + 'siphash13': [ # NOTE: PyUCS2 layout depends on endianness # seed 0, 'abc' [1198583518, 4596069200710135518, 1198583518, -4594863902769663758], From 381253bf4b247386dcfcacb4cbefe157a5084a33 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Thu, 7 Oct 2021 19:04:23 +0900 Subject: [PATCH 04/18] Add Py_HASH_SIPHASH24 and --with-hash-algorithm=siphash24. They is just alias for siphash13. --- Include/pyhash.h | 5 +++-- Python/pyhash.c | 2 +- configure | 10 ++++++++-- configure.ac | 12 ++++++++---- pyconfig.h.in | 8 ++++---- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/Include/pyhash.h b/Include/pyhash.h index d199241243b074..dc3bf70a2527d9 100644 --- a/Include/pyhash.h +++ b/Include/pyhash.h @@ -126,12 +126,13 @@ PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); * XXX: Figure out __declspec() for extern PyHash_FuncDef. */ #define Py_HASH_EXTERNAL 0 -#define Py_HASH_SIPHASH 1 +#define Py_HASH_SIPHASH13 1 +#define Py_HASH_SIPHASH24 1 /* deprecated */ #define Py_HASH_FNV 2 #ifndef Py_HASH_ALGORITHM # ifndef HAVE_ALIGNED_REQUIRED -# define Py_HASH_ALGORITHM Py_HASH_SIPHASH +# define Py_HASH_ALGORITHM Py_HASH_SIPHASH13 # else # define Py_HASH_ALGORITHM Py_HASH_FNV # endif /* uint64_t && uint32_t && aligned */ diff --git a/Python/pyhash.c b/Python/pyhash.c index 60ed73b171052a..7f4ebea1b44689 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -426,7 +426,7 @@ _Py_KeyedHash(uint64_t key, const void *src, Py_ssize_t src_sz) } -#if Py_HASH_ALGORITHM == Py_HASH_SIPHASH +#if Py_HASH_ALGORITHM == Py_HASH_SIPHASH13 static Py_hash_t pysiphash(const void *src, Py_ssize_t src_sz) { return (Py_hash_t)siphash13( diff --git a/configure b/configure index 4acf91f22107f4..d46eee9e1b62d6 100755 --- a/configure +++ b/configure @@ -1556,9 +1556,9 @@ Optional Packages: --with-undefined-behavior-sanitizer enable UndefinedBehaviorSanitizer undefined behaviour detector, 'ubsan' (default is no) - --with-hash-algorithm=[fnv|siphash24] + --with-hash-algorithm=[fnv|siphash13] select hash algorithm for use in Python/pyhash.c - (default is SipHash24) + (default is SipHash13) --with-tzpath= Select the default time zone search path for zoneinfo.TZPATH @@ -10420,7 +10420,13 @@ if test "${with_hash_algorithm+set}" = set; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: $withval" >&5 $as_echo "$withval" >&6; } case "$withval" in + siphash13) + $as_echo "#define Py_HASH_ALGORITHM 1" >>confdefs.h + + ;; siphash24) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-hash-algorithm=siphash24 is deprecated. Use siphash13" >&5 +$as_echo "$as_me: WARNING: --with-hash-algorithm=siphash24 is deprecated. Use siphash13" >&2;} $as_echo "#define Py_HASH_ALGORITHM 1" >>confdefs.h ;; diff --git a/configure.ac b/configure.ac index 8964f0dca7e014..3101176a23eeee 100644 --- a/configure.ac +++ b/configure.ac @@ -3036,17 +3036,21 @@ fi # str, bytes and memoryview hash algorithm AH_TEMPLATE(Py_HASH_ALGORITHM, [Define hash algorithm for str, bytes and memoryview. - SipHash: 1, FNV: 2, externally defined: 0]) + SipHash13: 1, FNV: 2, externally defined: 0]) AC_MSG_CHECKING(for --with-hash-algorithm) dnl quadrigraphs "@<:@" and "@:>@" produce "[" and "]" in the output AC_ARG_WITH(hash_algorithm, - AS_HELP_STRING([--with-hash-algorithm=@<:@fnv|siphash@:>@], - [select hash algorithm for use in Python/pyhash.c (default is SipHash)]), + AS_HELP_STRING([--with-hash-algorithm=@<:@fnv|siphash13@:>@], + [select hash algorithm for use in Python/pyhash.c (default is SipHash13)]), [ AC_MSG_RESULT($withval) case "$withval" in - siphash) + siphash13) + AC_DEFINE(Py_HASH_ALGORITHM, 1) + ;; + siphash24) + AC_MSG_WARN([--with-hash-algorithm=siphash24 is deprecated. Use siphash13]) AC_DEFINE(Py_HASH_ALGORITHM, 1) ;; fnv) diff --git a/pyconfig.h.in b/pyconfig.h.in index 23d7111b9f77e7..1c1f83ac34493b 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -136,15 +136,15 @@ /* Define to 1 if you have the `clock' function. */ #undef HAVE_CLOCK -/* Define to 1 if you have the `clock_nanosleep' function. */ -#undef HAVE_CLOCK_NANOSLEEP - /* Define to 1 if you have the `clock_getres' function. */ #undef HAVE_CLOCK_GETRES /* Define to 1 if you have the `clock_gettime' function. */ #undef HAVE_CLOCK_GETTIME +/* Define to 1 if you have the `clock_nanosleep' function. */ +#undef HAVE_CLOCK_NANOSLEEP + /* Define to 1 if you have the `clock_settime' function. */ #undef HAVE_CLOCK_SETTIME @@ -1435,7 +1435,7 @@ /* Defined if Python is built as a shared library. */ #undef Py_ENABLE_SHARED -/* Define hash algorithm for str, bytes and memoryview. SipHash24: 1, FNV: 2, +/* Define hash algorithm for str, bytes and memoryview. SipHash13: 1, FNV: 2, externally defined: 0 */ #undef Py_HASH_ALGORITHM From 996313514873ecb7a6e4432934d59c72d34d80d8 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Thu, 7 Oct 2021 19:09:23 +0900 Subject: [PATCH 05/18] Update doc, add NEWS and What's New entry. --- Doc/using/configure.rst | 8 ++++++-- Doc/whatsnew/3.11.rst | 2 ++ .../2021-10-07-19-09-12.bpo-29410.bg5SYp.rst | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-10-07-19-09-12.bpo-29410.bg5SYp.rst diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index a545d5a9372ac0..2b20410bd282d8 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -416,15 +416,19 @@ Libraries options Security Options ---------------- -.. cmdoption:: --with-hash-algorithm=[fnv|siphash24] +.. cmdoption:: --with-hash-algorithm=[fnv|siphash13] Select hash algorithm for use in ``Python/pyhash.c``: - * ``siphash24`` (default). + * ``siphash13`` (default). * ``fnv``; .. versionadded:: 3.4 + .. versionchanged:: 3.11 + ``siphash24`` is replaced with ``siphash13``. ``siphash13`` is faster and + safe enough. + .. cmdoption:: --with-builtin-hashlib-hashes=md5,sha1,sha256,sha512,sha3,blake2 Built-in hash modules: diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index d01d2e263199ad..4cb2c2ccf98ed3 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -175,6 +175,8 @@ Other CPython Implementation Changes support :class:`typing.SupportsComplex` and :class:`typing.SupportsBytes` protocols. (Contributed by Mark Dickinson and Dong-hee Na in :issue:`24234`.) +* Hash algorithm for strings is changed from SipHash24 to SipHash13. + (Contributed by Inada Naoki in :issue:`29410`.) New Modules =========== diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-07-19-09-12.bpo-29410.bg5SYp.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-07-19-09-12.bpo-29410.bg5SYp.rst new file mode 100644 index 00000000000000..13cf9ec8c52f7d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-10-07-19-09-12.bpo-29410.bg5SYp.rst @@ -0,0 +1 @@ +Hash algorithm for strings is changed from SipHash24 to SipHash13. From add336e5e4ad1a2bf6d8d41f56b9ec59847c0774 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 8 Oct 2021 12:00:56 +0900 Subject: [PATCH 06/18] Apply suggestions from code review Co-authored-by: Christian Heimes --- Include/pyhash.h | 4 ++-- configure.ac | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Include/pyhash.h b/Include/pyhash.h index dc3bf70a2527d9..3ca7b252e452f1 100644 --- a/Include/pyhash.h +++ b/Include/pyhash.h @@ -114,7 +114,7 @@ PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); /* hash algorithm selection * - * The values for Py_HASH_SIPHASH13 and Py_HASH_FNV are hard-coded in the + * The values for Py_HASH_* are hard-coded in the * configure script. * * - FNV is available on all platforms and architectures. @@ -126,9 +126,9 @@ PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); * XXX: Figure out __declspec() for extern PyHash_FuncDef. */ #define Py_HASH_EXTERNAL 0 -#define Py_HASH_SIPHASH13 1 #define Py_HASH_SIPHASH24 1 /* deprecated */ #define Py_HASH_FNV 2 +#define Py_HASH_SIPHASH13 3 #ifndef Py_HASH_ALGORITHM # ifndef HAVE_ALIGNED_REQUIRED diff --git a/configure.ac b/configure.ac index 3101176a23eeee..3474b38f7d86d5 100644 --- a/configure.ac +++ b/configure.ac @@ -3036,18 +3036,18 @@ fi # str, bytes and memoryview hash algorithm AH_TEMPLATE(Py_HASH_ALGORITHM, [Define hash algorithm for str, bytes and memoryview. - SipHash13: 1, FNV: 2, externally defined: 0]) + SipHash24: 1, FNV: 2, SipHash13: 3, externally defined: 0]) AC_MSG_CHECKING(for --with-hash-algorithm) dnl quadrigraphs "@<:@" and "@:>@" produce "[" and "]" in the output AC_ARG_WITH(hash_algorithm, - AS_HELP_STRING([--with-hash-algorithm=@<:@fnv|siphash13@:>@], + AS_HELP_STRING([--with-hash-algorithm=@<:@fnv|siphash13|siphash24@:>@], [select hash algorithm for use in Python/pyhash.c (default is SipHash13)]), [ AC_MSG_RESULT($withval) case "$withval" in siphash13) - AC_DEFINE(Py_HASH_ALGORITHM, 1) + AC_DEFINE(Py_HASH_ALGORITHM, 3) ;; siphash24) AC_MSG_WARN([--with-hash-algorithm=siphash24 is deprecated. Use siphash13]) From b8c6f69f21b23965333ab6d4d17b0c9b85857611 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 8 Oct 2021 12:02:28 +0900 Subject: [PATCH 07/18] Back siphash24 --- Doc/using/configure.rst | 12 ++++++------ Doc/whatsnew/3.11.rst | 3 ++- configure.ac | 1 - 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 2b20410bd282d8..1d1f04fb89d76c 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -416,18 +416,18 @@ Libraries options Security Options ---------------- -.. cmdoption:: --with-hash-algorithm=[fnv|siphash13] +.. cmdoption:: --with-hash-algorithm=[fnv|siphash13|siphash24] Select hash algorithm for use in ``Python/pyhash.c``: - * ``siphash13`` (default). - * ``fnv``; + * ``siphash13`` (default); + * ``siphash24``; + * ``fnv``. .. versionadded:: 3.4 - .. versionchanged:: 3.11 - ``siphash24`` is replaced with ``siphash13``. ``siphash13`` is faster and - safe enough. + .. versionadded:: 3.11 + ``siphash13`` is added and it is the new default. .. cmdoption:: --with-builtin-hashlib-hashes=md5,sha1,sha256,sha512,sha3,blake2 diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 4cb2c2ccf98ed3..0600dfa3421cce 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -175,7 +175,8 @@ Other CPython Implementation Changes support :class:`typing.SupportsComplex` and :class:`typing.SupportsBytes` protocols. (Contributed by Mark Dickinson and Dong-hee Na in :issue:`24234`.) -* Hash algorithm for strings is changed from SipHash24 to SipHash13. +* ``siphash13`` is added as a new internal hash algorithm for strings, and the default + algorithm is changed from ``siphash24`` to ``siphash13``. (Contributed by Inada Naoki in :issue:`29410`.) New Modules diff --git a/configure.ac b/configure.ac index 3474b38f7d86d5..9c8ac8a2a8eebd 100644 --- a/configure.ac +++ b/configure.ac @@ -3050,7 +3050,6 @@ case "$withval" in AC_DEFINE(Py_HASH_ALGORITHM, 3) ;; siphash24) - AC_MSG_WARN([--with-hash-algorithm=siphash24 is deprecated. Use siphash13]) AC_DEFINE(Py_HASH_ALGORITHM, 1) ;; fnv) From b83e3f0aeb7395c36eb8b60f48dd3c6972ed4150 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 8 Oct 2021 12:04:31 +0900 Subject: [PATCH 08/18] Add siphash24 again --- Lib/test/test_hash.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_hash.py b/Lib/test/test_hash.py index 626086415482f1..baf7e745e457e8 100644 --- a/Lib/test/test_hash.py +++ b/Lib/test/test_hash.py @@ -42,8 +42,8 @@ def pysiphash(uint64): def skip_unless_internalhash(test): """Skip decorator for tests that depend on SipHash24 or FNV""" - ok = sys.hash_info.algorithm in {"fnv", "siphash24"} - msg = "Requires SipHash24 or FNV" + ok = sys.hash_info.algorithm in {"fnv", "siphash13", "siphash24"} + msg = "Requires SipHash13, SipHash24 or FNV" return test if ok else unittest.skip(msg)(test) @@ -219,6 +219,19 @@ class StringlikeHashRandomizationTests(HashRandomizationTests): # seed 42, 'äú∑ℇ' [-1677110816, -2947981342227738144, -1860207793, -2845126246016066802], ], + 'siphash24': [ + # NOTE: PyUCS2 layout depends on endianness + # seed 0, 'abc' + [1198583518, 4596069200710135518, 1198583518, 4596069200710135518], + # seed 42, 'abc' + [273876886, -4501618152524544106, 273876886, -4501618152524544106], + # seed 42, 'abcdefghijk' + [-1745215313, 4436719588892876975, -1745215313, 4436719588892876975], + # seed 0, 'äú∑ℇ' + [493570806, 5749986484189612790, -1006381564, -5915111450199468540], + # seed 42, 'äú∑ℇ' + [-1677110816, -2947981342227738144, -1860207793, -4296699217652516017], + ], 'fnv': [ # seed 0, 'abc' [-1600925533, 1453079729188098211, -1600925533, From ac6e8ecb1237c26d4e0d8f9ed1b4e37432c77d30 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 8 Oct 2021 12:06:00 +0900 Subject: [PATCH 09/18] autoreconf --- configure | 6 ++---- pyconfig.h.in | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/configure b/configure index d46eee9e1b62d6..c8c3d742b62acc 100755 --- a/configure +++ b/configure @@ -1556,7 +1556,7 @@ Optional Packages: --with-undefined-behavior-sanitizer enable UndefinedBehaviorSanitizer undefined behaviour detector, 'ubsan' (default is no) - --with-hash-algorithm=[fnv|siphash13] + --with-hash-algorithm=[fnv|siphash13|siphash24] select hash algorithm for use in Python/pyhash.c (default is SipHash13) --with-tzpath= @@ -10421,12 +10421,10 @@ if test "${with_hash_algorithm+set}" = set; then : $as_echo "$withval" >&6; } case "$withval" in siphash13) - $as_echo "#define Py_HASH_ALGORITHM 1" >>confdefs.h + $as_echo "#define Py_HASH_ALGORITHM 3" >>confdefs.h ;; siphash24) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-hash-algorithm=siphash24 is deprecated. Use siphash13" >&5 -$as_echo "$as_me: WARNING: --with-hash-algorithm=siphash24 is deprecated. Use siphash13" >&2;} $as_echo "#define Py_HASH_ALGORITHM 1" >>confdefs.h ;; diff --git a/pyconfig.h.in b/pyconfig.h.in index 1c1f83ac34493b..bd3083bb72ca3a 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1435,8 +1435,8 @@ /* Defined if Python is built as a shared library. */ #undef Py_ENABLE_SHARED -/* Define hash algorithm for str, bytes and memoryview. SipHash13: 1, FNV: 2, - externally defined: 0 */ +/* Define hash algorithm for str, bytes and memoryview. SipHash24: 1, FNV: 2, + SipHash13: 3, externally defined: 0 */ #undef Py_HASH_ALGORITHM /* Define if you want to enable tracing references for debugging purpose */ From 5e7a4ad54261f65a35f6a888cef00967e72d2548 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 8 Oct 2021 12:06:40 +0900 Subject: [PATCH 10/18] Undeprecate siphash24 --- Include/pyhash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/pyhash.h b/Include/pyhash.h index 3ca7b252e452f1..0185ae947fb156 100644 --- a/Include/pyhash.h +++ b/Include/pyhash.h @@ -126,7 +126,7 @@ PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); * XXX: Figure out __declspec() for extern PyHash_FuncDef. */ #define Py_HASH_EXTERNAL 0 -#define Py_HASH_SIPHASH24 1 /* deprecated */ +#define Py_HASH_SIPHASH24 1 #define Py_HASH_FNV 2 #define Py_HASH_SIPHASH13 3 From 5d2e6f224800a7394a95da696f22ff7e3d7919fa Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 8 Oct 2021 12:14:31 +0900 Subject: [PATCH 11/18] Add siphash24() again. --- Python/pyhash.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/Python/pyhash.c b/Python/pyhash.c index 7f4ebea1b44689..b866cec3f87371 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -358,16 +358,20 @@ static PyHash_FuncDef PyHash_Func = {fnv, "fnv", 8 * SIZEOF_PY_HASH_T, # define ROTATE(x, b) (uint64_t)( ((x) << (b)) | ( (x) >> (64 - (b))) ) #endif -#define HALF_ROUND(a,b,c,d,s,t) \ - a += b; c += d; \ +#define HALF_ROUND(a,b,c,d,s,t) \ + a += b; c += d; \ b = ROTATE(b, s) ^ a; \ d = ROTATE(d, t) ^ c; \ a = ROTATE(a, 32); -#define SINGLE_ROUND(v0,v1,v2,v3) \ - HALF_ROUND(v0,v1,v2,v3,13,16); \ +#define SINGLE_ROUND(v0,v1,v2,v3) \ + HALF_ROUND(v0,v1,v2,v3,13,16); \ HALF_ROUND(v2,v1,v0,v3,17,21); +#define DOUBLE_ROUND(v0,v1,v2,v3) \ + SINGLE_ROUND(v0,v1,v2,v3); \ + SINGLE_ROUND(v0,v1,v2,v3); + static uint64_t siphash13(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { @@ -419,6 +423,55 @@ siphash13(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { return t; } +static uint64_t +siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { + uint64_t b = (uint64_t)src_sz << 56; + const uint8_t *in = (const uint8_t*)src; + + uint64_t v0 = k0 ^ 0x736f6d6570736575ULL; + uint64_t v1 = k1 ^ 0x646f72616e646f6dULL; + uint64_t v2 = k0 ^ 0x6c7967656e657261ULL; + uint64_t v3 = k1 ^ 0x7465646279746573ULL; + + uint64_t t; + uint8_t *pt; + + while (src_sz >= 8) { + uint64_t mi; + memcpy(&mi, in, sizeof(mi)); + mi = _le64toh(mi); + in += sizeof(mi); + src_sz -= sizeof(mi); + v3 ^= mi; + DOUBLE_ROUND(v0,v1,v2,v3); + v0 ^= mi; + } + + t = 0; + pt = (uint8_t *)&t; + switch (src_sz) { + case 7: pt[6] = in[6]; /* fall through */ + case 6: pt[5] = in[5]; /* fall through */ + case 5: pt[4] = in[4]; /* fall through */ + case 4: memcpy(pt, in, sizeof(uint32_t)); break; + case 3: pt[2] = in[2]; /* fall through */ + case 2: pt[1] = in[1]; /* fall through */ + case 1: pt[0] = in[0]; /* fall through */ + } + b |= _le64toh(t); + + v3 ^= b; + DOUBLE_ROUND(v0,v1,v2,v3); + v0 ^= b; + v2 ^= 0xff; + DOUBLE_ROUND(v0,v1,v2,v3); + DOUBLE_ROUND(v0,v1,v2,v3); + + /* modified */ + t = (v0 ^ v1) ^ (v2 ^ v3); + return t; +} + uint64_t _Py_KeyedHash(uint64_t key, const void *src, Py_ssize_t src_sz) { @@ -437,6 +490,17 @@ pysiphash(const void *src, Py_ssize_t src_sz) { static PyHash_FuncDef PyHash_Func = {pysiphash, "siphash13", 64, 128}; #endif +#if Py_HASH_ALGORITHM == Py_HASH_SIPHASH24 +static Py_hash_t +pysiphash(const void *src, Py_ssize_t src_sz) { + return (Py_hash_t)siphash24( + _le64toh(_Py_HashSecret.siphash.k0), _le64toh(_Py_HashSecret.siphash.k1), + src, src_sz); +} + +static PyHash_FuncDef PyHash_Func = {pysiphash, "siphash24", 64, 128}; +#endif + #ifdef __cplusplus } #endif From 69c9d12c2b7e2aa4a622e1b83355ba7fc75e0bb1 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 8 Oct 2021 13:38:09 +0900 Subject: [PATCH 12/18] test_hash: fix known hash --- Lib/test/test_hash.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_hash.py b/Lib/test/test_hash.py index baf7e745e457e8..cf9db66a29ae11 100644 --- a/Lib/test/test_hash.py +++ b/Lib/test/test_hash.py @@ -209,15 +209,15 @@ class StringlikeHashRandomizationTests(HashRandomizationTests): 'siphash13': [ # NOTE: PyUCS2 layout depends on endianness # seed 0, 'abc' - [1198583518, 4596069200710135518, 1198583518, -4594863902769663758], + [69611762, -4594863902769663758, 69611762, -4594863902769663758], # seed 42, 'abc' - [273876886, -4501618152524544106, 273876886, 3869580338025362921], + [-975800855, 3869580338025362921, -975800855, 3869580338025362921], # seed 42, 'abcdefghijk' - [-1745215313, 4436719588892876975, -1745215313, 7764564197781545852], + [-595844228, 7764564197781545852, -595844228, 7764564197781545852], # seed 0, 'äú∑ℇ' - [493570806, 5749986484189612790, -1006381564, -2810468059467891395], + [-1093288643, -2810468059467891395, -1041341092, 4925090034378237276], # seed 42, 'äú∑ℇ' - [-1677110816, -2947981342227738144, -1860207793, -2845126246016066802], + [-585999602, -2845126246016066802, -817336969, -2219421378907968137], ], 'siphash24': [ # NOTE: PyUCS2 layout depends on endianness From 0dce1e791925fec133267acf0a2a1d8ae4a5ef68 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 8 Oct 2021 14:48:21 +0900 Subject: [PATCH 13/18] Suppress warning --- Python/pyhash.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Python/pyhash.c b/Python/pyhash.c index b866cec3f87371..d5ac9f83be61cc 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -423,6 +423,7 @@ siphash13(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { return t; } +#if Py_HASH_ALGORITHM == Py_HASH_SIPHASH24 static uint64_t siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { uint64_t b = (uint64_t)src_sz << 56; @@ -471,6 +472,7 @@ siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { t = (v0 ^ v1) ^ (v2 ^ v3); return t; } +#endif uint64_t _Py_KeyedHash(uint64_t key, const void *src, Py_ssize_t src_sz) From 23d06e16c2455e718b70ea27dbdd50c0460c9620 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 8 Oct 2021 14:50:17 +0900 Subject: [PATCH 14/18] update NEWS entry --- .../Core and Builtins/2021-10-07-19-09-12.bpo-29410.bg5SYp.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-07-19-09-12.bpo-29410.bg5SYp.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-07-19-09-12.bpo-29410.bg5SYp.rst index 13cf9ec8c52f7d..b08999e78d84ae 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-07-19-09-12.bpo-29410.bg5SYp.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2021-10-07-19-09-12.bpo-29410.bg5SYp.rst @@ -1 +1 @@ -Hash algorithm for strings is changed from SipHash24 to SipHash13. +Add SipHash13 for string hash algorithm and use it by default. From 2de4af1dc16bded9bb9178277b2c7df5d417eda1 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 8 Oct 2021 14:57:35 +0900 Subject: [PATCH 15/18] fix test_sys --- Lib/test/test_sys.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 3b80904b28d3e2..72a8176297f107 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -508,7 +508,7 @@ def test_attributes(self): self.assertIsInstance(sys.hash_info.nan, int) self.assertIsInstance(sys.hash_info.imag, int) algo = sysconfig.get_config_var("Py_HASH_ALGORITHM") - if sys.hash_info.algorithm in {"fnv", "siphash24"}: + if sys.hash_info.algorithm in {"fnv", "siphash13", "siphash24"}: self.assertIn(sys.hash_info.hash_bits, {32, 64}) self.assertIn(sys.hash_info.seed_bits, {32, 64, 128}) @@ -516,8 +516,10 @@ def test_attributes(self): self.assertEqual(sys.hash_info.algorithm, "siphash24") elif algo == 2: self.assertEqual(sys.hash_info.algorithm, "fnv") + elif algo == 3: + self.assertEqual(sys.hash_info.algorithm, "siphash13") else: - self.assertIn(sys.hash_info.algorithm, {"fnv", "siphash24"}) + self.assertIn(sys.hash_info.algorithm, {"fnv", "siphash13", "siphash24"}) else: # PY_HASH_EXTERNAL self.assertEqual(algo, 0) From cfa006035db165d55b02c6ec7da3eb7b178c09c4 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 8 Oct 2021 17:53:58 +0900 Subject: [PATCH 16/18] Fix comment --- Include/pyhash.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Include/pyhash.h b/Include/pyhash.h index 0185ae947fb156..182d223fab1cac 100644 --- a/Include/pyhash.h +++ b/Include/pyhash.h @@ -117,8 +117,7 @@ PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); * The values for Py_HASH_* are hard-coded in the * configure script. * - * - FNV is available on all platforms and architectures. - * - SIPHASH only works on platforms that don't require aligned memory for integers. + * - FNV and SIPHASH* are available on all platforms and architectures. * - With EXTERNAL embedders can provide an alternative implementation with:: * * PyHash_FuncDef PyHash_Func = {...}; From a096bca02b7bb1ce2ba2096d6a66328c6be905d4 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Sat, 9 Oct 2021 11:48:11 +0900 Subject: [PATCH 17/18] Use suggested doc. --- Doc/whatsnew/3.11.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 0600dfa3421cce..97df1fe83747d9 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -175,8 +175,9 @@ Other CPython Implementation Changes support :class:`typing.SupportsComplex` and :class:`typing.SupportsBytes` protocols. (Contributed by Mark Dickinson and Dong-hee Na in :issue:`24234`.) -* ``siphash13`` is added as a new internal hash algorithm for strings, and the default - algorithm is changed from ``siphash24`` to ``siphash13``. +* ``siphash13`` is added as a new internal hashing algorithms. It's has similar security + properties as ``siphash24`` but it is slightly faster for long inputs. ``str``, ``bytes``, + and some other types now use it as default algorithm for ``hash()``. (Contributed by Inada Naoki in :issue:`29410`.) New Modules From 86cf6c60e5b5a8696136f47512318951766d4080 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Sun, 10 Oct 2021 11:30:12 +0900 Subject: [PATCH 18/18] Update Doc/whatsnew/3.11.rst Co-authored-by: Christian Heimes --- Doc/whatsnew/3.11.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 97df1fe83747d9..8106d47022a5c5 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -177,7 +177,8 @@ Other CPython Implementation Changes * ``siphash13`` is added as a new internal hashing algorithms. It's has similar security properties as ``siphash24`` but it is slightly faster for long inputs. ``str``, ``bytes``, - and some other types now use it as default algorithm for ``hash()``. + and some other types now use it as default algorithm for ``hash()``. :pep:`552` + hash-based pyc files now use ``siphash13``, too. (Contributed by Inada Naoki in :issue:`29410`.) New Modules