Skip to content

Commit 0c25fee

Browse files
committed
Teach fasthash_accum to use platform endianness for bytewise loads
This function previously used a mix of word-wise loads and bytewise loads. The bytewise loads happened to be little-endian regardless of platform. This in itself is not a problem. However, a future commit will require the same result whether A) the input is loaded as a word with the relevent bytes masked-off, or B) the input is loaded one byte at a time. While at it, improve debuggability of the internal hash state. Discussion: https://postgr.es/m/CANWCAZZpuV1mES1mtSpAq8tWJewbrv4gEz6R_k4gzNG8GZ5gag%40mail.gmail.com
1 parent 98f320e commit 0c25fee

File tree

1 file changed

+39
-5
lines changed

1 file changed

+39
-5
lines changed

src/include/common/hashfn_unstable.h

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,6 @@ fasthash_combine(fasthash_state *hs)
131131
{
132132
hs->hash ^= fasthash_mix(hs->accum, 0);
133133
hs->hash *= 0x880355f21e6d1965;
134-
135-
/* reset hash state for next input */
136-
hs->accum = 0;
137134
}
138135

139136
/* accumulate up to 8 bytes of input and combine it into the hash */
@@ -142,9 +139,44 @@ fasthash_accum(fasthash_state *hs, const char *k, size_t len)
142139
{
143140
uint32 lower_four;
144141

145-
Assert(hs->accum == 0);
146142
Assert(len <= FH_SIZEOF_ACCUM);
143+
hs->accum = 0;
147144

145+
/*
146+
* For consistency, bytewise loads must match the platform's endianness.
147+
*/
148+
#ifdef WORDS_BIGENDIAN
149+
switch (len)
150+
{
151+
case 8:
152+
memcpy(&hs->accum, k, 8);
153+
break;
154+
case 7:
155+
hs->accum |= (uint64) k[6] << 8;
156+
/* FALLTHROUGH */
157+
case 6:
158+
hs->accum |= (uint64) k[5] << 16;
159+
/* FALLTHROUGH */
160+
case 5:
161+
hs->accum |= (uint64) k[4] << 24;
162+
/* FALLTHROUGH */
163+
case 4:
164+
memcpy(&lower_four, k, sizeof(lower_four));
165+
hs->accum |= (uint64) lower_four << 32;
166+
break;
167+
case 3:
168+
hs->accum |= (uint64) k[2] << 40;
169+
/* FALLTHROUGH */
170+
case 2:
171+
hs->accum |= (uint64) k[1] << 48;
172+
/* FALLTHROUGH */
173+
case 1:
174+
hs->accum |= (uint64) k[0] << 56;
175+
break;
176+
case 0:
177+
return;
178+
}
179+
#else
148180
switch (len)
149181
{
150182
case 8:
@@ -175,6 +207,7 @@ fasthash_accum(fasthash_state *hs, const char *k, size_t len)
175207
case 0:
176208
return;
177209
}
210+
#endif
178211

179212
fasthash_combine(hs);
180213
}
@@ -288,7 +321,8 @@ fasthash_accum_cstring(fasthash_state *hs, const char *str)
288321
if (PointerIsAligned(str, uint64))
289322
{
290323
len = fasthash_accum_cstring_aligned(hs, str);
291-
Assert(hs_check.hash == hs->hash && len_check == len);
324+
Assert(len_check == len);
325+
Assert(hs_check.hash == hs->hash);
292326
return len;
293327
}
294328
#endif /* SIZEOF_VOID_P */

0 commit comments

Comments
 (0)