| 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 = 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 = {}; |
| 28 | void *Block = malloc(size: HeaderSize + Size); |
| 29 | void *P = reinterpret_cast<void *>(reinterpret_cast<scudo::uptr>(Block) + |
| 30 | HeaderSize); |
| 31 | scudo::Chunk::storeHeader(Cookie, Ptr: P, NewUnpackedHeader: &Header); |
| 32 | memset(s: P, c: 'A', n: Size); |
| 33 | scudo::Chunk::loadHeader(Cookie, Ptr: P, NewUnpackedHeader: &Header); |
| 34 | EXPECT_TRUE(scudo::Chunk::isValid(Cookie, Ptr: P, NewUnpackedHeader: &Header)); |
| 35 | EXPECT_FALSE(scudo::Chunk::isValid(Cookie: InvalidCookie, Ptr: P, NewUnpackedHeader: &Header)); |
| 36 | EXPECT_DEATH(scudo::Chunk::loadHeader(InvalidCookie, P, &Header), "" ); |
| 37 | free(ptr: Block); |
| 38 | } |
| 39 | |
| 40 | TEST(ScudoChunkDeathTest, CorruptHeader) { |
| 41 | initChecksum(); |
| 42 | const scudo::uptr Size = 0x100U; |
| 43 | scudo::Chunk::UnpackedHeader = {}; |
| 44 | void *Block = malloc(size: HeaderSize + Size); |
| 45 | void *P = reinterpret_cast<void *>(reinterpret_cast<scudo::uptr>(Block) + |
| 46 | HeaderSize); |
| 47 | scudo::Chunk::storeHeader(Cookie, Ptr: P, NewUnpackedHeader: &Header); |
| 48 | memset(s: P, c: 'A', n: Size); |
| 49 | scudo::Chunk::loadHeader(Cookie, Ptr: P, NewUnpackedHeader: &Header); |
| 50 | // Simulate a couple of corrupted bits per byte of header data. |
| 51 | for (scudo::uptr I = 0; I < sizeof(scudo::Chunk::PackedHeader); I++) { |
| 52 | *(reinterpret_cast<scudo::u8 *>(Block) + I) ^= 0x42U; |
| 53 | EXPECT_DEATH(scudo::Chunk::loadHeader(Cookie, P, &Header), "" ); |
| 54 | *(reinterpret_cast<scudo::u8 *>(Block) + I) ^= 0x42U; |
| 55 | } |
| 56 | free(ptr: Block); |
| 57 | } |
| 58 | |