From d0104a596199a41963dbba70338d9ff3c36b185a Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 5 Feb 2020 11:03:49 +0100 Subject: Make llvm::crc32() work also for input sizes larger than 32 bits. The problem was noticed by the Chrome OS toolchain folks (crbug.com/1048445) because llvm-objcopy --add-gnu-debuglink would insert the wrong checksum when processing a binary larger than 4 GB. That use case regressed in 1e1e3ba2526 when we started using llvm::crc32() in more places. Differential revision: https://reviews.llvm.org/D74039 (cherry picked from commit 6c4a8bc0a9f6a466d90d542bef66d69550c1b041) --- llvm/lib/Support/CRC.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'llvm/lib/Support/CRC.cpp') diff --git a/llvm/lib/Support/CRC.cpp b/llvm/lib/Support/CRC.cpp index a3dba1a3aa1..2bc668beed3 100644 --- a/llvm/lib/Support/CRC.cpp +++ b/llvm/lib/Support/CRC.cpp @@ -85,7 +85,15 @@ uint32_t llvm::crc32(uint32_t CRC, ArrayRef Data) { #include uint32_t llvm::crc32(uint32_t CRC, ArrayRef Data) { - return ::crc32(CRC, (const Bytef *)Data.data(), Data.size()); + // Zlib's crc32() only takes a 32-bit length, so we have to iterate for larger + // sizes. One could use crc32_z() instead, but that's a recent (2017) addition + // and may not be available on all systems. + do { + ArrayRef Slice = Data.take_front(UINT32_MAX); + CRC = ::crc32(CRC, (const Bytef *)Slice.data(), (uInt)Slice.size()); + Data = Data.drop_front(Slice.size()); + } while (Data.size() > 0); + return CRC; } #endif -- cgit v1.2.3