From c479e4e789df355a25508a0ed38791978253a2e3 Mon Sep 17 00:00:00 2001 From: Florian Mayer Date: Wed, 23 Jan 2019 13:35:40 +0000 Subject: [PATCH] Fix crash in libunwindstack. Bug: 122657596 Test: New unit test that crashes without this change. Change-Id: I5d978530a833345def94a58805d7ee93b23382bb --- libunwindstack/Unwinder.cpp | 2 +- libunwindstack/tests/UnwinderTest.cpp | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp index 0dd95cf33..2734cf8d3 100644 --- a/libunwindstack/Unwinder.cpp +++ b/libunwindstack/Unwinder.cpp @@ -247,7 +247,7 @@ void Unwinder::Unwind(const std::vector* initial_map_names_to_skip, // or the pc in the first frame is in a valid map. // This allows for a case where the code jumps into the middle of // nowhere, but there is no other unwind information after that. - if (frames_.size() != 2 || maps_->Find(frames_[0].pc) != nullptr) { + if (frames_.size() > 2 || (frames_.size() > 0 && maps_->Find(frames_[0].pc) != nullptr)) { // Remove the speculative frame. frames_.pop_back(); } diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp index 49aeeb378..d88531f2b 100644 --- a/libunwindstack/tests/UnwinderTest.cpp +++ b/libunwindstack/tests/UnwinderTest.cpp @@ -749,6 +749,23 @@ TEST_F(UnwinderTest, speculative_frame_not_removed_pc_bad) { EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); } +// Verify that a speculative frame does not cause a crash when it wasn't +// really added due to a filter. +TEST_F(UnwinderTest, speculative_frame_check_with_no_frames) { + regs_.set_pc(0x23000); + regs_.set_sp(0x10000); + regs_.FakeSetReturnAddress(0x23100); + regs_.FakeSetReturnAddressValid(true); + + Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); + + std::vector skip_names{"libanother.so"}; + unwinder.Unwind(&skip_names); + EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + + ASSERT_EQ(0U, unwinder.NumFrames()); +} + // Verify that an unwind stops when a frame is in given suffix. TEST_F(UnwinderTest, map_ignore_suffixes) { ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));