xref: /aosp_15_r20/external/scudo/standalone/tests/checksum_test.cpp (revision 76559068c068bd27e82aff38fac3bfc865233bca)
1*76559068SAndroid Build Coastguard Worker //===-- checksum_test.cpp ---------------------------------------*- C++ -*-===//
2*76559068SAndroid Build Coastguard Worker //
3*76559068SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*76559068SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*76559068SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*76559068SAndroid Build Coastguard Worker //
7*76559068SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*76559068SAndroid Build Coastguard Worker 
9*76559068SAndroid Build Coastguard Worker #include "tests/scudo_unit_test.h"
10*76559068SAndroid Build Coastguard Worker 
11*76559068SAndroid Build Coastguard Worker #include "checksum.h"
12*76559068SAndroid Build Coastguard Worker 
13*76559068SAndroid Build Coastguard Worker #include <string.h>
14*76559068SAndroid Build Coastguard Worker 
computeSoftwareChecksum(scudo::u32 Seed,scudo::uptr * Array,scudo::uptr ArraySize)15*76559068SAndroid Build Coastguard Worker static scudo::u16 computeSoftwareChecksum(scudo::u32 Seed, scudo::uptr *Array,
16*76559068SAndroid Build Coastguard Worker                                           scudo::uptr ArraySize) {
17*76559068SAndroid Build Coastguard Worker   scudo::u16 Checksum = static_cast<scudo::u16>(Seed & 0xffff);
18*76559068SAndroid Build Coastguard Worker   for (scudo::uptr I = 0; I < ArraySize; I++)
19*76559068SAndroid Build Coastguard Worker     Checksum = scudo::computeBSDChecksum(Checksum, Array[I]);
20*76559068SAndroid Build Coastguard Worker   return Checksum;
21*76559068SAndroid Build Coastguard Worker }
22*76559068SAndroid Build Coastguard Worker 
computeHardwareChecksum(scudo::u32 Seed,scudo::uptr * Array,scudo::uptr ArraySize)23*76559068SAndroid Build Coastguard Worker static scudo::u16 computeHardwareChecksum(scudo::u32 Seed, scudo::uptr *Array,
24*76559068SAndroid Build Coastguard Worker                                           scudo::uptr ArraySize) {
25*76559068SAndroid Build Coastguard Worker   scudo::u32 Crc = Seed;
26*76559068SAndroid Build Coastguard Worker   for (scudo::uptr I = 0; I < ArraySize; I++)
27*76559068SAndroid Build Coastguard Worker     Crc = scudo::computeHardwareCRC32(Crc, Array[I]);
28*76559068SAndroid Build Coastguard Worker   return static_cast<scudo::u16>((Crc & 0xffff) ^ (Crc >> 16));
29*76559068SAndroid Build Coastguard Worker }
30*76559068SAndroid Build Coastguard Worker 
31*76559068SAndroid Build Coastguard Worker typedef scudo::u16 (*ComputeChecksum)(scudo::u32, scudo::uptr *, scudo::uptr);
32*76559068SAndroid Build Coastguard Worker 
33*76559068SAndroid Build Coastguard Worker // This verifies that flipping bits in the data being checksummed produces a
34*76559068SAndroid Build Coastguard Worker // different checksum. We do not use random data to avoid flakyness.
verifyChecksumFunctionBitFlip()35*76559068SAndroid Build Coastguard Worker template <ComputeChecksum F> static void verifyChecksumFunctionBitFlip() {
36*76559068SAndroid Build Coastguard Worker   scudo::uptr Array[sizeof(scudo::u64) / sizeof(scudo::uptr)];
37*76559068SAndroid Build Coastguard Worker   const scudo::uptr ArraySize = ARRAY_SIZE(Array);
38*76559068SAndroid Build Coastguard Worker   memset(Array, 0xaa, sizeof(Array));
39*76559068SAndroid Build Coastguard Worker   const scudo::u32 Seed = 0x41424343U;
40*76559068SAndroid Build Coastguard Worker   const scudo::u16 Reference = F(Seed, Array, ArraySize);
41*76559068SAndroid Build Coastguard Worker   scudo::u8 IdenticalChecksums = 0;
42*76559068SAndroid Build Coastguard Worker   for (scudo::uptr I = 0; I < ArraySize; I++) {
43*76559068SAndroid Build Coastguard Worker     for (scudo::uptr J = 0; J < SCUDO_WORDSIZE; J++) {
44*76559068SAndroid Build Coastguard Worker       Array[I] ^= scudo::uptr{1} << J;
45*76559068SAndroid Build Coastguard Worker       if (F(Seed, Array, ArraySize) == Reference)
46*76559068SAndroid Build Coastguard Worker         IdenticalChecksums++;
47*76559068SAndroid Build Coastguard Worker       Array[I] ^= scudo::uptr{1} << J;
48*76559068SAndroid Build Coastguard Worker     }
49*76559068SAndroid Build Coastguard Worker   }
50*76559068SAndroid Build Coastguard Worker   // Allow for a couple of identical checksums over the whole set of flips.
51*76559068SAndroid Build Coastguard Worker   EXPECT_LE(IdenticalChecksums, 2);
52*76559068SAndroid Build Coastguard Worker }
53*76559068SAndroid Build Coastguard Worker 
TEST(ScudoChecksumTest,ChecksumFunctions)54*76559068SAndroid Build Coastguard Worker TEST(ScudoChecksumTest, ChecksumFunctions) {
55*76559068SAndroid Build Coastguard Worker   verifyChecksumFunctionBitFlip<computeSoftwareChecksum>();
56*76559068SAndroid Build Coastguard Worker   if (&scudo::computeHardwareCRC32 && scudo::hasHardwareCRC32())
57*76559068SAndroid Build Coastguard Worker     verifyChecksumFunctionBitFlip<computeHardwareChecksum>();
58*76559068SAndroid Build Coastguard Worker }
59