• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef Py_INTERNAL_PYHASH_H
2 #define Py_INTERNAL_PYHASH_H
3 
4 #ifndef Py_BUILD_CORE
5 #  error "this header requires Py_BUILD_CORE define"
6 #endif
7 
8 // Similar to Py_HashPointer(), but don't replace -1 with -2.
9 static inline Py_hash_t
_Py_HashPointerRaw(const void * ptr)10 _Py_HashPointerRaw(const void *ptr)
11 {
12     uintptr_t x = (uintptr_t)ptr;
13     Py_BUILD_ASSERT(sizeof(x) == sizeof(ptr));
14 
15     // Bottom 3 or 4 bits are likely to be 0; rotate x by 4 to the right
16     // to avoid excessive hash collisions for dicts and sets.
17     x = (x >> 4) | (x << (8 * sizeof(uintptr_t) - 4));
18 
19     Py_BUILD_ASSERT(sizeof(x) == sizeof(Py_hash_t));
20     return (Py_hash_t)x;
21 }
22 
23 // Export for '_datetime' shared extension
24 PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void*, Py_ssize_t);
25 
26 /* Hash secret
27  *
28  * memory layout on 64 bit systems
29  *   cccccccc cccccccc cccccccc  uc -- unsigned char[24]
30  *   pppppppp ssssssss ........  fnv -- two Py_hash_t
31  *   k0k0k0k0 k1k1k1k1 ........  siphash -- two uint64_t
32  *   ........ ........ ssssssss  djbx33a -- 16 bytes padding + one Py_hash_t
33  *   ........ ........ eeeeeeee  pyexpat XML hash salt
34  *
35  * memory layout on 32 bit systems
36  *   cccccccc cccccccc cccccccc  uc
37  *   ppppssss ........ ........  fnv -- two Py_hash_t
38  *   k0k0k0k0 k1k1k1k1 ........  siphash -- two uint64_t (*)
39  *   ........ ........ ssss....  djbx33a -- 16 bytes padding + one Py_hash_t
40  *   ........ ........ eeee....  pyexpat XML hash salt
41  *
42  * (*) The siphash member may not be available on 32 bit platforms without
43  *     an unsigned int64 data type.
44  */
45 typedef union {
46     /* ensure 24 bytes */
47     unsigned char uc[24];
48     /* two Py_hash_t for FNV */
49     struct {
50         Py_hash_t prefix;
51         Py_hash_t suffix;
52     } fnv;
53     /* two uint64 for SipHash24 */
54     struct {
55         uint64_t k0;
56         uint64_t k1;
57     } siphash;
58     /* a different (!) Py_hash_t for small string optimization */
59     struct {
60         unsigned char padding[16];
61         Py_hash_t suffix;
62     } djbx33a;
63     struct {
64         unsigned char padding[16];
65         Py_hash_t hashsalt;
66     } expat;
67 } _Py_HashSecret_t;
68 
69 // Export for '_elementtree' shared extension
70 PyAPI_DATA(_Py_HashSecret_t) _Py_HashSecret;
71 
72 #ifdef Py_DEBUG
73 extern int _Py_HashSecret_Initialized;
74 #endif
75 
76 
77 struct pyhash_runtime_state {
78     struct {
79 #ifndef MS_WINDOWS
80         int fd;
81         dev_t st_dev;
82         ino_t st_ino;
83 #else
84     // This is a placeholder so the struct isn't empty on Windows.
85     int _not_used;
86 #endif
87     } urandom_cache;
88 };
89 
90 #ifndef MS_WINDOWS
91 # define _py_urandom_cache_INIT \
92     { \
93         .fd = -1, \
94     }
95 #else
96 # define _py_urandom_cache_INIT {0}
97 #endif
98 
99 #define pyhash_state_INIT \
100     { \
101         .urandom_cache = _py_urandom_cache_INIT, \
102     }
103 
104 
105 extern uint64_t _Py_KeyedHash(uint64_t key, const void *src, Py_ssize_t src_sz);
106 
107 #endif  // !Py_INTERNAL_PYHASH_H
108