From a4e5433660228dae47530518bfb6fc49723f8882 Mon Sep 17 00:00:00 2001 From: Nick Kralevich Date: Thu, 4 Apr 2019 14:19:43 -0700 Subject: [PATCH] zip_archive.cc: fix ubsan false positive std::hash returns a 64 bit value, which is truncated to a 32 bit value in ComputeHash. ubsan's implicit-unsigned-integer-truncation doesn't like this implicit truncation and crashes the program. Explicitly strip off the top order bits after computing the hash. Remove the windows specific version of the hash computation. The windows compile now uses clang, so this code is obsolete. This also avoids us having to add __attribute__((no_sanitize("integer"))) to the windows code. This is needed to support Android booting with ubsan's implicit-unsigned-integer-truncation option enabled. Test: compiles and boots Bug: 122975762 Change-Id: I2f05fbf5ffee8e90a66a6fda32e80de9cca246c0 --- libziparchive/zip_archive.cc | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc index 0710d0add..96dbba1b8 100644 --- a/libziparchive/zip_archive.cc +++ b/libziparchive/zip_archive.cc @@ -102,21 +102,9 @@ static uint32_t RoundUpPower2(uint32_t val) { } static uint32_t ComputeHash(const ZipString& name) { -#if !defined(_WIN32) return std::hash{}( - std::string_view(reinterpret_cast(name.name), name.name_length)); -#else - // Remove this code path once the windows compiler knows how to compile the above statement. - uint32_t hash = 0; - uint16_t len = name.name_length; - const uint8_t* str = name.name; - - while (len--) { - hash = hash * 31 + *str++; - } - - return hash; -#endif + std::string_view(reinterpret_cast(name.name), name.name_length)) & + UINT32_MAX; } static bool isZipStringEqual(const uint8_t* start, const ZipString& zip_string,