Bug#731330: libstdc++6: functions labelled FNV-1a in /usr/include/c++/4.7/tr1/functional_hash.h are not FNV-1a
Package: libstdc++6
Version: 4.7.2-5
Severity: minor
As far as I know, the FNV and FNV-1a algorithms process octects, i.e. unsigned
chars. (see e.g. http://tools.ietf.org/html/draft-eastlake-fnv-03#section-2 )
The implementations in /usr/include/c++/4.7/tr1/functional_hash.h work
on chars, instead, and their output is wrong (in architectures where char is
signed) when the input byte sequence includes bytes with the MSB set.
For example
std::tr1::_Fnv_hash_base<4>::hash("\x80", 1)
returns 83079839, instead of the correct value 2232128415.
The problem resides in the type cast:
template<>
struct _Fnv_hash_base<4>
{
template<typename _Tp>
static size_t
hash(const _Tp* __ptr, size_t __clength)
{
size_t __result = static_cast<size_t>(2166136261UL);
>>> const char* __cptr = reinterpret_cast<const char*>(__ptr); <<<
for (; __clength; --__clength)
{
__result ^= static_cast<size_t>(*__cptr++);
__result *= static_cast<size_t>(16777619UL);
}
return __result;
}
};
The highlighed line should read:
const unsigned char* __cptr = reinterpret_cast<const unsigned char*>(__ptr);
Since the FNV primes were carefully chosen in order to minimize
collision rates and maximize dispersion, there might be consequences in
the performance of data structures that build on tr1::hash template,
perhaps tr1::unordered_map and tr1::unordered_set.
Best regards,
g
-- System Information:
Debian Release: 7.2
APT prefers stable-updates
APT policy: (500, 'stable-updates'), (500, 'stable')
Architecture: i386 (i686)
Kernel: Linux 3.2.0-4-686-pae (SMP w/2 CPU cores)
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
Shell: /bin/sh linked to /bin/dash
Versions of packages libstdc++6 depends on:
ii gcc-4.7-base 4.7.2-5
ii libc6 2.13-38
ii libgcc1 1:4.7.2-5
ii multiarch-support 2.13-38
libstdc++6 recommends no packages.
libstdc++6 suggests no packages.
-- no debconf information
Reply to: