cache: fix behavior on single-CPU systems On a system with only a single CPU, shard_bits_ would be set to 0. This would then result in calculating 'hash >> (32 - 0)' which is undefined behavior. With optimizations, this would turn into a no-op, and we'd end up using the whole hash as the shard index, instead of 0, causing a crash.
The fix is to widen the hash to uint64_t before shifting. Tested by manually making NumCPUs return 1 and running cache-test. Change-Id: I7809e5697df657a589b2ceae5c6d4edbf161b52a Reviewed-on: http://gerrit.cloudera.org:8080/4535 Tested-by: Kudu Jenkins Reviewed-by: Adar Dembo <a...@cloudera.com> (cherry picked from commit 69e65780843040c085ca34901803b97b59595c0e) Reviewed-on: http://gerrit.cloudera.org:8080/4608 Reviewed-by: Todd Lipcon <t...@apache.org> Project: http://git-wip-us.apache.org/repos/asf/kudu/repo Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/40637ef8 Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/40637ef8 Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/40637ef8 Branch: refs/heads/branch-1.0.x Commit: 40637ef8fc773dc47882334fcee760bbffcd09b4 Parents: 77769ad Author: Todd Lipcon <t...@apache.org> Authored: Sat Sep 24 19:35:43 2016 -0700 Committer: Dan Burkert <d...@cloudera.com> Committed: Mon Oct 3 21:47:53 2016 +0000 ---------------------------------------------------------------------- src/kudu/util/cache.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kudu/blob/40637ef8/src/kudu/util/cache.cc ---------------------------------------------------------------------- diff --git a/src/kudu/util/cache.cc b/src/kudu/util/cache.cc index 964d93c..1ef16a0 100644 --- a/src/kudu/util/cache.cc +++ b/src/kudu/util/cache.cc @@ -395,7 +395,9 @@ class ShardedLRUCache : public Cache { } uint32_t Shard(uint32_t hash) { - return hash >> (32 - shard_bits_); + // Widen to uint64 before shifting, or else on a single CPU, + // we would try to shift a uint32_t by 32 bits, which is undefined. + return static_cast<uint64_t>(hash) >> (32 - shard_bits_); } public: