libunwindstack: don't save pseudoregisters while evaluating Dwarf
Currently, while evaluating a Dwarf section, even pseudoregisters are
saved in regs_info. Since pseudoregisters are stored separately from
ordinary registers, trying to read them the usual way will result in
an out-of-bounds read. There's no memory corruption as regs_info is
big enough to store all existing pseudoregisters.
With this patch, pseudoregisters are simply not saved in regs_info.
Added new unit tests to cover the pseudo register cases.
Test: libunwindstack_test
Change-Id: If21b2a79f2fcca85644eec430f3d22e354b001ec
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 9e2a3cd..bf86e6e 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -465,13 +465,9 @@
eval_info->return_address_undefined = true;
}
break;
- case DWARF_LOCATION_PSEUDO_REGISTER: {
- if (!eval_info->regs_info.regs->SetPseudoRegister(reg, loc->values[0])) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
- break;
- }
+ case DWARF_LOCATION_PSEUDO_REGISTER:
+ last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
+ return false;
default:
break;
}
@@ -543,11 +539,15 @@
// Skip this unknown register.
continue;
}
- }
-
- reg_ptr = eval_info.regs_info.Save(reg);
- if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
- return false;
+ if (!eval_info.regs_info.regs->SetPseudoRegister(reg, entry.second.values[0])) {
+ last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
+ return false;
+ }
+ } else {
+ reg_ptr = eval_info.regs_info.Save(reg);
+ if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
+ return false;
+ }
}
}