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

Commit 6dbc28ec authored by Christopher Ferris's avatar Christopher Ferris
Browse files

Fix null pointer dereference in RegsArm.

Fix RegsArm::GetPcAdjustment to check for an invalid elf before trying
to read memory.
Modify the tests for this so it crashes without this change.

Also modify the GetPcAdjustment for all different architectures so
that unless the relative pc is too small, it will return the minimum
amount that should be adjusted. This is to handle cases where we still
want to adjust the pc but it's in an invalid elf. Mostly this is for
handling cases when the pc is in jit gdb debug code so that we use the
right unwind information.

Bug: 77233204

Test: Passes unit tests for libbacktrace/libunwindstack.
Change-Id: Id73609adaf3b80a583584441de228156fec3afa7
parent c41ff1b3
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -51,14 +51,24 @@ void RegsArm::set_sp(uint64_t sp) {
}

uint64_t RegsArm::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
  if (!elf->valid()) {
    return 2;
  }

  uint64_t load_bias = elf->GetLoadBias();
  if (rel_pc < load_bias) {
    if (rel_pc < 2) {
      return 0;
    }
    return 2;
  }
  uint64_t adjusted_rel_pc = rel_pc - load_bias;
  if (adjusted_rel_pc < 5) {
    if (adjusted_rel_pc < 2) {
      return 0;
    }
    return 2;
  }

  if (adjusted_rel_pc & 1) {
    // This is a thumb instruction, it could be 2 or 4 bytes.
+2 −2
Original line number Diff line number Diff line
@@ -51,8 +51,8 @@ void RegsArm64::set_sp(uint64_t sp) {
  regs_[ARM64_REG_SP] = sp;
}

uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
  if (!elf->valid() || rel_pc < 4) {
uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf*) {
  if (rel_pc < 4) {
    return 0;
  }
  return 4;
+2 −2
Original line number Diff line number Diff line
@@ -51,8 +51,8 @@ void RegsMips::set_sp(uint64_t sp) {
  regs_[MIPS_REG_SP] = static_cast<uint32_t>(sp);
}

uint64_t RegsMips::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
  if (!elf->valid() || rel_pc < 8) {
uint64_t RegsMips::GetPcAdjustment(uint64_t rel_pc, Elf*) {
  if (rel_pc < 8) {
    return 0;
  }
  // For now, just assume no compact branches
+2 −2
Original line number Diff line number Diff line
@@ -51,8 +51,8 @@ void RegsMips64::set_sp(uint64_t sp) {
  regs_[MIPS64_REG_SP] = sp;
}

uint64_t RegsMips64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
  if (!elf->valid() || rel_pc < 8) {
uint64_t RegsMips64::GetPcAdjustment(uint64_t rel_pc, Elf*) {
  if (rel_pc < 8) {
    return 0;
  }
  // For now, just assume no compact branches
+2 −2
Original line number Diff line number Diff line
@@ -50,8 +50,8 @@ void RegsX86::set_sp(uint64_t sp) {
  regs_[X86_REG_SP] = static_cast<uint32_t>(sp);
}

uint64_t RegsX86::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
  if (!elf->valid() || rel_pc == 0) {
uint64_t RegsX86::GetPcAdjustment(uint64_t rel_pc, Elf*) {
  if (rel_pc == 0) {
    return 0;
  }
  return 1;
Loading