summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Mayer <fmayer@google.com>2019-01-23 13:35:40 +0000
committerChristopher Ferris <cferris@google.com>2019-01-24 16:29:36 -0800
commit32fa1932b0e528d994776202768fbc9f2510c656 (patch)
tree00d4030c774be51f3a57a54c94d4827ae61b79d9
parent9b208890c132f10abfdfa64025b90b5e210311bb (diff)
downloadunwinding-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.cpp2
-rw-r--r--libunwindstack/tests/UnwinderTest.cpp17
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(), &regs_, 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));