mirror of
https://github.com/yuzu-emu/breakpad
synced 2024-11-22 11:03:38 +00:00
The X86 stack walker was doing an illegal down cast from base-class (StackFrame) to derived-class (StackFrameX86).
Inline frames are always of the base-class type (StackFrame). Treating them as derived-class and accessing members was causing heap buffer overflows. Change-Id: Id4122ab6a31f016933038a1cb63d45d5c38481f5 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/3425445 Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
08bd844599
commit
8205b6edb8
1 changed files with 20 additions and 2 deletions
|
@ -141,6 +141,9 @@ StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo(
|
|||
bool stack_scan_allowed) {
|
||||
StackFrame::FrameTrust trust = StackFrame::FRAME_TRUST_NONE;
|
||||
|
||||
// The last frame can never be inline. A sequence of inline frames always
|
||||
// finishes with a conventional frame.
|
||||
assert(frames.back()->trust != StackFrame::FRAME_TRUST_INLINE);
|
||||
StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
|
||||
|
||||
// Save the stack walking info we found, in case we need it later to
|
||||
|
@ -187,9 +190,15 @@ StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo(
|
|||
|
||||
uint32_t last_frame_callee_parameter_size = 0;
|
||||
int frames_already_walked = frames.size();
|
||||
if (frames_already_walked >= 2) {
|
||||
for (int last_frame_callee_id = frames_already_walked - 2;
|
||||
last_frame_callee_id >= 0; last_frame_callee_id--) {
|
||||
// Searching for a real callee frame. Skipping inline frames since they
|
||||
// cannot be downcasted to StackFrameX86.
|
||||
if (frames[last_frame_callee_id]->trust == StackFrame::FRAME_TRUST_INLINE) {
|
||||
continue;
|
||||
}
|
||||
const StackFrameX86* last_frame_callee
|
||||
= static_cast<StackFrameX86*>(frames[frames_already_walked - 2]);
|
||||
= static_cast<StackFrameX86*>(frames[last_frame_callee_id]);
|
||||
WindowsFrameInfo* last_frame_callee_info
|
||||
= last_frame_callee->windows_frame_info;
|
||||
if (last_frame_callee_info &&
|
||||
|
@ -516,6 +525,9 @@ StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo(
|
|||
StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo(
|
||||
const vector<StackFrame*>& frames,
|
||||
CFIFrameInfo* cfi_frame_info) {
|
||||
// The last frame can never be inline. A sequence of inline frames always
|
||||
// finishes with a conventional frame.
|
||||
assert(frames.back()->trust != StackFrame::FRAME_TRUST_INLINE);
|
||||
StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
|
||||
last_frame->cfi_frame_info = cfi_frame_info;
|
||||
|
||||
|
@ -542,6 +554,9 @@ StackFrameX86* StackwalkerX86::GetCallerByEBPAtBase(
|
|||
const vector<StackFrame*>& frames,
|
||||
bool stack_scan_allowed) {
|
||||
StackFrame::FrameTrust trust;
|
||||
// The last frame can never be inline. A sequence of inline frames always
|
||||
// finishes with a conventional frame.
|
||||
assert(frames.back()->trust != StackFrame::FRAME_TRUST_INLINE);
|
||||
StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
|
||||
uint32_t last_esp = last_frame->context.esp;
|
||||
uint32_t last_ebp = last_frame->context.ebp;
|
||||
|
@ -634,6 +649,9 @@ StackFrame* StackwalkerX86::GetCallerFrame(const CallStack* stack,
|
|||
|
||||
const vector<StackFrame*>& frames = *stack->frames();
|
||||
StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
|
||||
// The last frame can never be inline. A sequence of inline frames always
|
||||
// finishes with a conventional frame.
|
||||
assert(last_frame->trust != StackFrame::FRAME_TRUST_INLINE);
|
||||
scoped_ptr<StackFrameX86> new_frame;
|
||||
|
||||
// If the resolver has Windows stack walking information, use that.
|
||||
|
|
Loading…
Reference in a new issue