diff options
author | Florian Mayer <fmayer@google.com> | 2019-01-23 13:35:40 +0000 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2019-01-24 16:29:36 -0800 |
commit | 32fa1932b0e528d994776202768fbc9f2510c656 (patch) | |
tree | 00d4030c774be51f3a57a54c94d4827ae61b79d9 | |
parent | 9b208890c132f10abfdfa64025b90b5e210311bb (diff) | |
download | unwinding-32fa1932b0e528d994776202768fbc9f2510c656.tar.gz |
Fix crash in libunwindstack.
Bug: 122657596
Test: New unit test that crashes without this change.
Change-Id: I5d978530a833345def94a58805d7ee93b23382bb
-rw-r--r-- | libunwindstack/Unwinder.cpp | 2 | ||||
-rw-r--r-- | libunwindstack/tests/UnwinderTest.cpp | 17 |
2 files changed, 18 insertions, 1 deletions
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp index 0dd95cf..2734cf8 100644 --- a/libunwindstack/Unwinder.cpp +++ b/libunwindstack/Unwinder.cpp @@ -247,7 +247,7 @@ void Unwinder::Unwind(const std::vector<std::string>* 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 49aeeb3..d88531f 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<std::string> 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)); |