13cab2bb3Spatrick //===-- checksum_test.cpp ---------------------------------------*- C++ -*-===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick
93cab2bb3Spatrick #include "tests/scudo_unit_test.h"
103cab2bb3Spatrick
113cab2bb3Spatrick #include "checksum.h"
123cab2bb3Spatrick
133cab2bb3Spatrick #include <string.h>
143cab2bb3Spatrick
computeSoftwareChecksum(scudo::u32 Seed,scudo::uptr * Array,scudo::uptr ArraySize)15*810390e3Srobert static scudo::u16 computeSoftwareChecksum(scudo::u32 Seed, scudo::uptr *Array,
163cab2bb3Spatrick scudo::uptr ArraySize) {
173cab2bb3Spatrick scudo::u16 Checksum = static_cast<scudo::u16>(Seed & 0xffff);
183cab2bb3Spatrick for (scudo::uptr I = 0; I < ArraySize; I++)
193cab2bb3Spatrick Checksum = scudo::computeBSDChecksum(Checksum, Array[I]);
203cab2bb3Spatrick return Checksum;
213cab2bb3Spatrick }
223cab2bb3Spatrick
computeHardwareChecksum(scudo::u32 Seed,scudo::uptr * Array,scudo::uptr ArraySize)23*810390e3Srobert static scudo::u16 computeHardwareChecksum(scudo::u32 Seed, scudo::uptr *Array,
243cab2bb3Spatrick scudo::uptr ArraySize) {
253cab2bb3Spatrick scudo::u32 Crc = Seed;
263cab2bb3Spatrick for (scudo::uptr I = 0; I < ArraySize; I++)
273cab2bb3Spatrick Crc = scudo::computeHardwareCRC32(Crc, Array[I]);
283cab2bb3Spatrick return static_cast<scudo::u16>((Crc & 0xffff) ^ (Crc >> 16));
293cab2bb3Spatrick }
303cab2bb3Spatrick
313cab2bb3Spatrick typedef scudo::u16 (*ComputeChecksum)(scudo::u32, scudo::uptr *, scudo::uptr);
323cab2bb3Spatrick
333cab2bb3Spatrick // This verifies that flipping bits in the data being checksummed produces a
343cab2bb3Spatrick // different checksum. We do not use random data to avoid flakyness.
verifyChecksumFunctionBitFlip()35*810390e3Srobert template <ComputeChecksum F> static void verifyChecksumFunctionBitFlip() {
363cab2bb3Spatrick scudo::uptr Array[sizeof(scudo::u64) / sizeof(scudo::uptr)];
373cab2bb3Spatrick const scudo::uptr ArraySize = ARRAY_SIZE(Array);
383cab2bb3Spatrick memset(Array, 0xaa, sizeof(Array));
393cab2bb3Spatrick const scudo::u32 Seed = 0x41424343U;
403cab2bb3Spatrick const scudo::u16 Reference = F(Seed, Array, ArraySize);
413cab2bb3Spatrick scudo::u8 IdenticalChecksums = 0;
423cab2bb3Spatrick for (scudo::uptr I = 0; I < ArraySize; I++) {
433cab2bb3Spatrick for (scudo::uptr J = 0; J < SCUDO_WORDSIZE; J++) {
44d89ec533Spatrick Array[I] ^= scudo::uptr{1} << J;
453cab2bb3Spatrick if (F(Seed, Array, ArraySize) == Reference)
463cab2bb3Spatrick IdenticalChecksums++;
47d89ec533Spatrick Array[I] ^= scudo::uptr{1} << J;
483cab2bb3Spatrick }
493cab2bb3Spatrick }
503cab2bb3Spatrick // Allow for a couple of identical checksums over the whole set of flips.
513cab2bb3Spatrick EXPECT_LE(IdenticalChecksums, 2);
523cab2bb3Spatrick }
533cab2bb3Spatrick
TEST(ScudoChecksumTest,ChecksumFunctions)543cab2bb3Spatrick TEST(ScudoChecksumTest, ChecksumFunctions) {
553cab2bb3Spatrick verifyChecksumFunctionBitFlip<computeSoftwareChecksum>();
563cab2bb3Spatrick if (&scudo::computeHardwareCRC32 && scudo::hasHardwareCRC32())
573cab2bb3Spatrick verifyChecksumFunctionBitFlip<computeHardwareChecksum>();
583cab2bb3Spatrick }
59