From 63525c8d6cef5654080664ab9ecded86c219e4b0 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Tue, 4 Aug 2020 13:58:43 -0700 Subject: [PATCH] Fix fuzzer so it doesn't add overlapping maps. The fuzzer was creating individual maps that overlapped with other maps. Since this is not possible in the real world unless the kernel is broken, do not let the fuzzer do this. This resulted in memory leaks, because some parts of the code have this assumption baked in. Bug: 160895854 Test: Ran fuzzer test case that leaked memory and verified it no longer does. Change-Id: I9f3c1e28781093b041b747e1566fb51d40d2bf71 --- .../tests/fuzz/UnwinderComponentCreator.cpp | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/libunwindstack/tests/fuzz/UnwinderComponentCreator.cpp b/libunwindstack/tests/fuzz/UnwinderComponentCreator.cpp index 94f5a73cd..0415ef684 100644 --- a/libunwindstack/tests/fuzz/UnwinderComponentCreator.cpp +++ b/libunwindstack/tests/fuzz/UnwinderComponentCreator.cpp @@ -16,6 +16,11 @@ #include "UnwinderComponentCreator.h" +#include +#include +#include +#include + std::unique_ptr GetRegisters(ArchEnum arch) { switch (arch) { case unwindstack::ARCH_ARM: { @@ -109,13 +114,28 @@ ElfFake* PopulateElfFake(FuzzedDataProvider* data_provider) { return elf; } +static constexpr size_t kPageSize = 4096; + +static constexpr uint64_t AlignToPage(uint64_t address) { + return (address + kPageSize - 1) & ~(kPageSize - 1); +} + std::unique_ptr GetMaps(FuzzedDataProvider* data_provider) { std::unique_ptr maps = std::make_unique(); + std::map map_ends; uint8_t entry_count = data_provider->ConsumeIntegralInRange(0, kMaxMapEntryCount); for (uint8_t i = 0; i < entry_count; i++) { - uint64_t start = data_provider->ConsumeIntegral(); - uint64_t end = data_provider->ConsumeIntegralInRange(start, UINT64_MAX); - uint64_t offset = data_provider->ConsumeIntegral(); + uint64_t start = AlignToPage(data_provider->ConsumeIntegral()); + uint64_t end = AlignToPage(data_provider->ConsumeIntegralInRange(start, UINT64_MAX)); + // Make sure not to add overlapping maps, that is not something that can + // happen in the real world. + auto entry = map_ends.upper_bound(start); + if (entry != map_ends.end() && end > entry->second) { + continue; + } + map_ends[end] = start; + + uint64_t offset = AlignToPage(data_provider->ConsumeIntegral()); std::string map_info_name = data_provider->ConsumeRandomLengthString(kMaxMapInfoNameLen); uint8_t flags = PROT_READ | PROT_WRITE;