1 //===-- chunk_test.cpp ------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "tests/scudo_unit_test.h" 10 11 #include "chunk.h" 12 13 #include <stdlib.h> 14 15 static constexpr scudo::uptr HeaderSize = scudo::Chunk::getHeaderSize(); 16 static constexpr scudo::u32 Cookie = 0x41424344U; 17 static constexpr scudo::u32 InvalidCookie = 0x11223344U; 18 19 static void initChecksum(void) { 20 if (&scudo::computeHardwareCRC32 && scudo::hasHardwareCRC32()) 21 scudo::HashAlgorithm = scudo::Checksum::HardwareCRC32; 22 } 23 24 TEST(ScudoChunkDeathTest, ChunkBasic) { 25 initChecksum(); 26 const scudo::uptr Size = 0x100U; 27 scudo::Chunk::UnpackedHeader Header = {}; 28 void *Block = malloc(HeaderSize + Size); 29 void *P = reinterpret_cast<void *>(reinterpret_cast<scudo::uptr>(Block) + 30 HeaderSize); 31 scudo::Chunk::storeHeader(Cookie, P, &Header); 32 memset(P, 'A', Size); 33 scudo::Chunk::loadHeader(Cookie, P, &Header); 34 EXPECT_TRUE(scudo::Chunk::isValid(Cookie, P, &Header)); 35 EXPECT_FALSE(scudo::Chunk::isValid(InvalidCookie, P, &Header)); 36 EXPECT_DEATH(scudo::Chunk::loadHeader(InvalidCookie, P, &Header), ""); 37 free(Block); 38 } 39 40 TEST(ScudoChunkTest, ChunkCmpXchg) { 41 initChecksum(); 42 const scudo::uptr Size = 0x100U; 43 scudo::Chunk::UnpackedHeader OldHeader = {}; 44 OldHeader.OriginOrWasZeroed = scudo::Chunk::Origin::Malloc; 45 OldHeader.ClassId = 0x42U; 46 OldHeader.SizeOrUnusedBytes = Size; 47 OldHeader.State = scudo::Chunk::State::Allocated; 48 void *Block = malloc(HeaderSize + Size); 49 void *P = reinterpret_cast<void *>(reinterpret_cast<scudo::uptr>(Block) + 50 HeaderSize); 51 scudo::Chunk::storeHeader(Cookie, P, &OldHeader); 52 memset(P, 'A', Size); 53 scudo::Chunk::UnpackedHeader NewHeader = OldHeader; 54 NewHeader.State = scudo::Chunk::State::Quarantined; 55 scudo::Chunk::compareExchangeHeader(Cookie, P, &NewHeader, &OldHeader); 56 NewHeader = {}; 57 EXPECT_TRUE(scudo::Chunk::isValid(Cookie, P, &NewHeader)); 58 EXPECT_EQ(NewHeader.State, scudo::Chunk::State::Quarantined); 59 EXPECT_FALSE(scudo::Chunk::isValid(InvalidCookie, P, &NewHeader)); 60 free(Block); 61 } 62 63 TEST(ScudoChunkDeathTest, CorruptHeader) { 64 initChecksum(); 65 const scudo::uptr Size = 0x100U; 66 scudo::Chunk::UnpackedHeader Header = {}; 67 void *Block = malloc(HeaderSize + Size); 68 void *P = reinterpret_cast<void *>(reinterpret_cast<scudo::uptr>(Block) + 69 HeaderSize); 70 scudo::Chunk::storeHeader(Cookie, P, &Header); 71 memset(P, 'A', Size); 72 scudo::Chunk::loadHeader(Cookie, P, &Header); 73 // Simulate a couple of corrupted bits per byte of header data. 74 for (scudo::uptr I = 0; I < sizeof(scudo::Chunk::PackedHeader); I++) { 75 *(reinterpret_cast<scudo::u8 *>(Block) + I) ^= 0x42U; 76 EXPECT_DEATH(scudo::Chunk::loadHeader(Cookie, P, &Header), ""); 77 *(reinterpret_cast<scudo::u8 *>(Block) + I) ^= 0x42U; 78 } 79 free(Block); 80 } 81