Loading libunwindstack/DexFile.cpp +22 −2 Original line number Diff line number Diff line Loading @@ -50,6 +50,22 @@ static bool HasDexSupport() { std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory, MapInfo* info) { if (UNLIKELY(!HasDexSupport())) { return nullptr; } size_t max_size = info->end - dex_file_offset_in_memory; if (memory->IsLocal()) { size_t size = max_size; std::string err_msg; std::unique_ptr<art_api::dex::DexFile> art_dex_file = DexFile::OpenFromMemory( reinterpret_cast<void const*>(dex_file_offset_in_memory), &size, info->name, &err_msg); if (art_dex_file != nullptr && size <= max_size) { return std::unique_ptr<DexFile>(new DexFile(art_dex_file)); } } if (!info->name.empty()) { std::unique_ptr<DexFile> dex_file = DexFileFromFile::Create(dex_file_offset_in_memory - info->start + info->offset, info->name); Loading @@ -57,7 +73,7 @@ std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Mem return dex_file; } } return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name); return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name, max_size); } bool DexFile::GetMethodInformation(uint64_t dex_offset, std::string* method_name, Loading Loading @@ -94,7 +110,8 @@ std::unique_ptr<DexFileFromFile> DexFileFromFile::Create(uint64_t dex_file_offse std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory, Memory* memory, const std::string& name) { const std::string& name, size_t max_size) { if (UNLIKELY(!HasDexSupport())) { return nullptr; } Loading @@ -105,6 +122,9 @@ std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_o std::string error_msg; std::unique_ptr<art_api::dex::DexFile> art_dex_file = OpenFromMemory(backing_memory.data(), &size, name, &error_msg); if (size > max_size) { return nullptr; } if (art_dex_file != nullptr) { return std::unique_ptr<DexFileFromMemory>( Loading libunwindstack/DexFile.h +2 −1 Original line number Diff line number Diff line Loading @@ -55,7 +55,8 @@ class DexFileFromFile : public DexFile { class DexFileFromMemory : public DexFile { public: static std::unique_ptr<DexFileFromMemory> Create(uint64_t dex_file_offset_in_memory, Memory* memory, const std::string& name); Memory* memory, const std::string& name, size_t max_size); private: DexFileFromMemory(std::unique_ptr<art_api::dex::DexFile>& art_dex_file, Loading libunwindstack/MemoryLocal.h +2 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ class MemoryLocal : public Memory { MemoryLocal() = default; virtual ~MemoryLocal() = default; bool IsLocal() const override { return true; } size_t Read(uint64_t addr, void* dst, size_t size) override; }; Loading libunwindstack/include/unwindstack/Memory.h +2 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,8 @@ class Memory { virtual void Clear() {} virtual bool IsLocal() const { return false; } virtual size_t Read(uint64_t addr, void* dst, size_t size) = 0; bool ReadFully(uint64_t addr, void* dst, size_t size); Loading libunwindstack/tests/DexFileTest.cpp +42 −4 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <unordered_map> #include <MemoryLocal.h> #include <android-base/file.h> #include <gtest/gtest.h> #include <unwindstack/MapInfo.h> Loading Loading @@ -109,7 +110,7 @@ TEST(DexFileTest, from_memory_fail_too_small_for_header) { memory.SetMemory(0x1000, kDexData, 10); EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr); EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr); } TEST(DexFileTest, from_memory_fail_too_small_for_data) { Loading @@ -117,7 +118,7 @@ TEST(DexFileTest, from_memory_fail_too_small_for_data) { memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2); EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr); EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr); } TEST(DexFileTest, from_memory_open) { Loading @@ -125,7 +126,7 @@ TEST(DexFileTest, from_memory_open) { memory.SetMemory(0x1000, kDexData, sizeof(kDexData)); EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr); EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr); } TEST(DexFileTest, from_memory_no_leak) { Loading @@ -136,7 +137,7 @@ TEST(DexFileTest, from_memory_no_leak) { size_t first_allocated_bytes = 0; size_t last_allocated_bytes = 0; for (size_t i = 0; i < kNumLeakLoops; i++) { EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr); EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr); ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes)); } } Loading Loading @@ -213,6 +214,43 @@ TEST(DexFileTest, create_using_memory_file_is_malformed) { EXPECT_TRUE(dex_file == nullptr); } TEST(DexFileTest, create_using_memory_size_too_small) { MemoryFake memory; memory.SetMemory(0x4000, kDexData, sizeof(kDexData)); MapInfo info(nullptr, nullptr, 0x100, sizeof(kDexData) - 2, 0x200, 0x5, "/does/not/exist"); EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr); } class MemoryLocalFake : public MemoryLocal { public: MemoryLocalFake(size_t memory_size) : backing_(memory_size) {} virtual ~MemoryLocalFake() = default; void* Data() { return backing_.data(); } private: std::vector<void*> backing_; }; TEST(DexFileTest, create_using_local_memory) { MemoryLocalFake memory(sizeof(kDexData)); memcpy(memory.Data(), kDexData, sizeof(kDexData)); uint64_t start = reinterpret_cast<uint64_t>(memory.Data()); MapInfo info(nullptr, nullptr, start, start + 0x1000, 0x200, 0x5, "/does/not/exist"); EXPECT_TRUE(DexFile::Create(start, &memory, &info) != nullptr); } TEST(DexFileTest, create_using_local_memory_size_too_small) { MemoryLocalFake memory(sizeof(kDexData)); memcpy(memory.Data(), kDexData, sizeof(kDexData)); uint64_t start = reinterpret_cast<uint64_t>(memory.Data()); MapInfo info(nullptr, nullptr, start, start + sizeof(kDexData) - 2, 0x200, 0x5, "/does/not/exist"); EXPECT_TRUE(DexFile::Create(start, &memory, &info) == nullptr); } TEST(DexFileTest, get_method) { MemoryFake memory; memory.SetMemory(0x4000, kDexData, sizeof(kDexData)); Loading Loading
libunwindstack/DexFile.cpp +22 −2 Original line number Diff line number Diff line Loading @@ -50,6 +50,22 @@ static bool HasDexSupport() { std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory, MapInfo* info) { if (UNLIKELY(!HasDexSupport())) { return nullptr; } size_t max_size = info->end - dex_file_offset_in_memory; if (memory->IsLocal()) { size_t size = max_size; std::string err_msg; std::unique_ptr<art_api::dex::DexFile> art_dex_file = DexFile::OpenFromMemory( reinterpret_cast<void const*>(dex_file_offset_in_memory), &size, info->name, &err_msg); if (art_dex_file != nullptr && size <= max_size) { return std::unique_ptr<DexFile>(new DexFile(art_dex_file)); } } if (!info->name.empty()) { std::unique_ptr<DexFile> dex_file = DexFileFromFile::Create(dex_file_offset_in_memory - info->start + info->offset, info->name); Loading @@ -57,7 +73,7 @@ std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Mem return dex_file; } } return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name); return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name, max_size); } bool DexFile::GetMethodInformation(uint64_t dex_offset, std::string* method_name, Loading Loading @@ -94,7 +110,8 @@ std::unique_ptr<DexFileFromFile> DexFileFromFile::Create(uint64_t dex_file_offse std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory, Memory* memory, const std::string& name) { const std::string& name, size_t max_size) { if (UNLIKELY(!HasDexSupport())) { return nullptr; } Loading @@ -105,6 +122,9 @@ std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_o std::string error_msg; std::unique_ptr<art_api::dex::DexFile> art_dex_file = OpenFromMemory(backing_memory.data(), &size, name, &error_msg); if (size > max_size) { return nullptr; } if (art_dex_file != nullptr) { return std::unique_ptr<DexFileFromMemory>( Loading
libunwindstack/DexFile.h +2 −1 Original line number Diff line number Diff line Loading @@ -55,7 +55,8 @@ class DexFileFromFile : public DexFile { class DexFileFromMemory : public DexFile { public: static std::unique_ptr<DexFileFromMemory> Create(uint64_t dex_file_offset_in_memory, Memory* memory, const std::string& name); Memory* memory, const std::string& name, size_t max_size); private: DexFileFromMemory(std::unique_ptr<art_api::dex::DexFile>& art_dex_file, Loading
libunwindstack/MemoryLocal.h +2 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ class MemoryLocal : public Memory { MemoryLocal() = default; virtual ~MemoryLocal() = default; bool IsLocal() const override { return true; } size_t Read(uint64_t addr, void* dst, size_t size) override; }; Loading
libunwindstack/include/unwindstack/Memory.h +2 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,8 @@ class Memory { virtual void Clear() {} virtual bool IsLocal() const { return false; } virtual size_t Read(uint64_t addr, void* dst, size_t size) = 0; bool ReadFully(uint64_t addr, void* dst, size_t size); Loading
libunwindstack/tests/DexFileTest.cpp +42 −4 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <unordered_map> #include <MemoryLocal.h> #include <android-base/file.h> #include <gtest/gtest.h> #include <unwindstack/MapInfo.h> Loading Loading @@ -109,7 +110,7 @@ TEST(DexFileTest, from_memory_fail_too_small_for_header) { memory.SetMemory(0x1000, kDexData, 10); EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr); EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr); } TEST(DexFileTest, from_memory_fail_too_small_for_data) { Loading @@ -117,7 +118,7 @@ TEST(DexFileTest, from_memory_fail_too_small_for_data) { memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2); EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr); EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr); } TEST(DexFileTest, from_memory_open) { Loading @@ -125,7 +126,7 @@ TEST(DexFileTest, from_memory_open) { memory.SetMemory(0x1000, kDexData, sizeof(kDexData)); EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr); EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr); } TEST(DexFileTest, from_memory_no_leak) { Loading @@ -136,7 +137,7 @@ TEST(DexFileTest, from_memory_no_leak) { size_t first_allocated_bytes = 0; size_t last_allocated_bytes = 0; for (size_t i = 0; i < kNumLeakLoops; i++) { EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr); EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr); ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes)); } } Loading Loading @@ -213,6 +214,43 @@ TEST(DexFileTest, create_using_memory_file_is_malformed) { EXPECT_TRUE(dex_file == nullptr); } TEST(DexFileTest, create_using_memory_size_too_small) { MemoryFake memory; memory.SetMemory(0x4000, kDexData, sizeof(kDexData)); MapInfo info(nullptr, nullptr, 0x100, sizeof(kDexData) - 2, 0x200, 0x5, "/does/not/exist"); EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr); } class MemoryLocalFake : public MemoryLocal { public: MemoryLocalFake(size_t memory_size) : backing_(memory_size) {} virtual ~MemoryLocalFake() = default; void* Data() { return backing_.data(); } private: std::vector<void*> backing_; }; TEST(DexFileTest, create_using_local_memory) { MemoryLocalFake memory(sizeof(kDexData)); memcpy(memory.Data(), kDexData, sizeof(kDexData)); uint64_t start = reinterpret_cast<uint64_t>(memory.Data()); MapInfo info(nullptr, nullptr, start, start + 0x1000, 0x200, 0x5, "/does/not/exist"); EXPECT_TRUE(DexFile::Create(start, &memory, &info) != nullptr); } TEST(DexFileTest, create_using_local_memory_size_too_small) { MemoryLocalFake memory(sizeof(kDexData)); memcpy(memory.Data(), kDexData, sizeof(kDexData)); uint64_t start = reinterpret_cast<uint64_t>(memory.Data()); MapInfo info(nullptr, nullptr, start, start + sizeof(kDexData) - 2, 0x200, 0x5, "/does/not/exist"); EXPECT_TRUE(DexFile::Create(start, &memory, &info) == nullptr); } TEST(DexFileTest, get_method) { MemoryFake memory; memory.SetMemory(0x4000, kDexData, sizeof(kDexData)); Loading