Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit afbed690 authored by Christopher Ferris's avatar Christopher Ferris
Browse files

Fix nullptr dereference.

A previous cl missed adding a return in the new path which could result
in a crash if the map info is null. Add the return back.

Added a new test to catch this case.

Bug: 166188440

Test: Unit tests pass. Verified the new test crashes on the old code.
Change-Id: I9420b47dae0f880493c0e6a60d97bb3468ff2906
parent e27781db
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ void Unwinder::FillInDexFrame() {
  } else {
    frame->rel_pc = dex_pc;
    warnings_ |= WARNING_DEX_PC_NOT_IN_MAP;
    return;
  }

  if (!resolve_names_) {
+65 −1
Original line number Diff line number Diff line
@@ -57,6 +57,9 @@ class UnwinderTest : public ::testing::Test {
  static void SetUpTestSuite() {
    maps_.reset(new Maps);

    memory_ = new MemoryFake;
    process_memory_.reset(memory_);

    ElfFake* elf = new ElfFake(new MemoryFake);
    ElfInterfaceFake* interface_fake = new ElfInterfaceFake(nullptr);
    interface_fake->FakeSetBuildID("FAKE");
@@ -136,7 +139,19 @@ class UnwinderTest : public ::testing::Test {
    const auto& info7 = *--maps_->end();
    info7->load_bias = 0;

    process_memory_.reset(new MemoryFake);
    elf = new ElfFake(new MemoryFake);
    interface = new ElfInterfaceFake(nullptr);
    elf->FakeSetInterface(interface);
    interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x1800);
    interface->FakeSetDataOffset(0x1000);
    interface->FakeSetDataVaddrStart(0x1000);
    interface->FakeSetDataVaddrEnd(0x3000);
    AddMapInfo(0xf0000, 0xf1000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/global.so", elf);
    AddMapInfo(0xf1000, 0xf9000, 0x1000, PROT_READ | PROT_WRITE, "/fake/global.so");
    memory_->SetData32(0xf180c, 0xf3000);
    memory_->SetData32(0xf3000, 0xf4000);
    memory_->SetData32(0xf3004, 0xf4000);
    memory_->SetData32(0xf3008, 0xf5000);
  }

  void SetUp() override {
@@ -147,11 +162,13 @@ class UnwinderTest : public ::testing::Test {

  static std::unique_ptr<Maps> maps_;
  static RegsFake regs_;
  static MemoryFake* memory_;
  static std::shared_ptr<Memory> process_memory_;
};

std::unique_ptr<Maps> UnwinderTest::maps_;
RegsFake UnwinderTest::regs_(5);
MemoryFake* UnwinderTest::memory_;
std::shared_ptr<Memory> UnwinderTest::process_memory_(nullptr);

TEST_F(UnwinderTest, multiple_frames) {
@@ -1129,6 +1146,53 @@ TEST_F(UnwinderTest, dex_pc_not_in_map) {
  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
}

TEST_F(UnwinderTest, dex_pc_not_in_map_valid_dex_files) {
  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
  regs_.set_pc(0x1000);
  regs_.set_sp(0x10000);
  regs_.FakeSetDexPc(0x50000);

  DexFiles dex_files(process_memory_);
  Unwinder unwinder(64, maps_.get(), &regs_, process_memory_);
  unwinder.SetDexFiles(&dex_files, ARCH_ARM);
  unwinder.Unwind();
  EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
  EXPECT_EQ(WARNING_DEX_PC_NOT_IN_MAP, unwinder.warnings());
  EXPECT_FALSE(unwinder.elf_from_memory_not_file());

  ASSERT_EQ(2U, unwinder.NumFrames());

  auto* frame = &unwinder.frames()[0];
  EXPECT_EQ(0U, frame->num);
  EXPECT_EQ(0x50000U, frame->rel_pc);
  EXPECT_EQ(0x50000U, frame->pc);
  EXPECT_EQ(0x10000U, frame->sp);
  EXPECT_EQ("", frame->function_name);
  EXPECT_EQ(0U, frame->function_offset);
  EXPECT_EQ("", frame->map_name);
  EXPECT_EQ(0U, frame->map_elf_start_offset);
  EXPECT_EQ(0U, frame->map_exact_offset);
  EXPECT_EQ(0U, frame->map_start);
  EXPECT_EQ(0U, frame->map_end);
  EXPECT_EQ(0U, frame->map_load_bias);
  EXPECT_EQ(0, frame->map_flags);

  frame = &unwinder.frames()[1];
  EXPECT_EQ(1U, frame->num);
  EXPECT_EQ(0U, frame->rel_pc);
  EXPECT_EQ(0x1000U, frame->pc);
  EXPECT_EQ(0x10000U, frame->sp);
  EXPECT_EQ("Frame0", frame->function_name);
  EXPECT_EQ(0U, frame->function_offset);
  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
  EXPECT_EQ(0U, frame->map_elf_start_offset);
  EXPECT_EQ(0U, frame->map_exact_offset);
  EXPECT_EQ(0x1000U, frame->map_start);
  EXPECT_EQ(0x8000U, frame->map_end);
  EXPECT_EQ(0U, frame->map_load_bias);
  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
}

TEST_F(UnwinderTest, dex_pc_multiple_frames) {
  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));