13cab2bb3Spatrick //===-- chunk_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 "chunk.h"
123cab2bb3Spatrick
133cab2bb3Spatrick #include <stdlib.h>
143cab2bb3Spatrick
153cab2bb3Spatrick static constexpr scudo::uptr HeaderSize = scudo::Chunk::getHeaderSize();
163cab2bb3Spatrick static constexpr scudo::u32 Cookie = 0x41424344U;
173cab2bb3Spatrick static constexpr scudo::u32 InvalidCookie = 0x11223344U;
183cab2bb3Spatrick
initChecksum(void)193cab2bb3Spatrick static void initChecksum(void) {
203cab2bb3Spatrick if (&scudo::computeHardwareCRC32 && scudo::hasHardwareCRC32())
213cab2bb3Spatrick scudo::HashAlgorithm = scudo::Checksum::HardwareCRC32;
223cab2bb3Spatrick }
233cab2bb3Spatrick
TEST(ScudoChunkDeathTest,ChunkBasic)24*d89ec533Spatrick TEST(ScudoChunkDeathTest, ChunkBasic) {
253cab2bb3Spatrick initChecksum();
263cab2bb3Spatrick const scudo::uptr Size = 0x100U;
273cab2bb3Spatrick scudo::Chunk::UnpackedHeader Header = {};
283cab2bb3Spatrick void *Block = malloc(HeaderSize + Size);
293cab2bb3Spatrick void *P = reinterpret_cast<void *>(reinterpret_cast<scudo::uptr>(Block) +
303cab2bb3Spatrick HeaderSize);
313cab2bb3Spatrick scudo::Chunk::storeHeader(Cookie, P, &Header);
323cab2bb3Spatrick memset(P, 'A', Size);
333cab2bb3Spatrick scudo::Chunk::loadHeader(Cookie, P, &Header);
343cab2bb3Spatrick EXPECT_TRUE(scudo::Chunk::isValid(Cookie, P, &Header));
353cab2bb3Spatrick EXPECT_FALSE(scudo::Chunk::isValid(InvalidCookie, P, &Header));
363cab2bb3Spatrick EXPECT_DEATH(scudo::Chunk::loadHeader(InvalidCookie, P, &Header), "");
373cab2bb3Spatrick free(Block);
383cab2bb3Spatrick }
393cab2bb3Spatrick
TEST(ScudoChunkTest,ChunkCmpXchg)403cab2bb3Spatrick TEST(ScudoChunkTest, ChunkCmpXchg) {
413cab2bb3Spatrick initChecksum();
423cab2bb3Spatrick const scudo::uptr Size = 0x100U;
433cab2bb3Spatrick scudo::Chunk::UnpackedHeader OldHeader = {};
44*d89ec533Spatrick OldHeader.OriginOrWasZeroed = scudo::Chunk::Origin::Malloc;
453cab2bb3Spatrick OldHeader.ClassId = 0x42U;
463cab2bb3Spatrick OldHeader.SizeOrUnusedBytes = Size;
473cab2bb3Spatrick OldHeader.State = scudo::Chunk::State::Allocated;
483cab2bb3Spatrick void *Block = malloc(HeaderSize + Size);
493cab2bb3Spatrick void *P = reinterpret_cast<void *>(reinterpret_cast<scudo::uptr>(Block) +
503cab2bb3Spatrick HeaderSize);
513cab2bb3Spatrick scudo::Chunk::storeHeader(Cookie, P, &OldHeader);
523cab2bb3Spatrick memset(P, 'A', Size);
533cab2bb3Spatrick scudo::Chunk::UnpackedHeader NewHeader = OldHeader;
543cab2bb3Spatrick NewHeader.State = scudo::Chunk::State::Quarantined;
553cab2bb3Spatrick scudo::Chunk::compareExchangeHeader(Cookie, P, &NewHeader, &OldHeader);
563cab2bb3Spatrick NewHeader = {};
573cab2bb3Spatrick EXPECT_TRUE(scudo::Chunk::isValid(Cookie, P, &NewHeader));
583cab2bb3Spatrick EXPECT_EQ(NewHeader.State, scudo::Chunk::State::Quarantined);
593cab2bb3Spatrick EXPECT_FALSE(scudo::Chunk::isValid(InvalidCookie, P, &NewHeader));
603cab2bb3Spatrick free(Block);
613cab2bb3Spatrick }
623cab2bb3Spatrick
TEST(ScudoChunkDeathTest,CorruptHeader)63*d89ec533Spatrick TEST(ScudoChunkDeathTest, CorruptHeader) {
643cab2bb3Spatrick initChecksum();
653cab2bb3Spatrick const scudo::uptr Size = 0x100U;
663cab2bb3Spatrick scudo::Chunk::UnpackedHeader Header = {};
673cab2bb3Spatrick void *Block = malloc(HeaderSize + Size);
683cab2bb3Spatrick void *P = reinterpret_cast<void *>(reinterpret_cast<scudo::uptr>(Block) +
693cab2bb3Spatrick HeaderSize);
703cab2bb3Spatrick scudo::Chunk::storeHeader(Cookie, P, &Header);
713cab2bb3Spatrick memset(P, 'A', Size);
723cab2bb3Spatrick scudo::Chunk::loadHeader(Cookie, P, &Header);
733cab2bb3Spatrick // Simulate a couple of corrupted bits per byte of header data.
743cab2bb3Spatrick for (scudo::uptr I = 0; I < sizeof(scudo::Chunk::PackedHeader); I++) {
753cab2bb3Spatrick *(reinterpret_cast<scudo::u8 *>(Block) + I) ^= 0x42U;
763cab2bb3Spatrick EXPECT_DEATH(scudo::Chunk::loadHeader(Cookie, P, &Header), "");
773cab2bb3Spatrick *(reinterpret_cast<scudo::u8 *>(Block) + I) ^= 0x42U;
783cab2bb3Spatrick }
793cab2bb3Spatrick free(Block);
803cab2bb3Spatrick }
81