mirror of
https://github.com/yuzu-emu/breakpad
synced 2024-11-26 10:07:52 +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) {
|
bool stack_scan_allowed) {
|
||||||
StackFrame::FrameTrust trust = StackFrame::FRAME_TRUST_NONE;
|
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());
|
StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
|
||||||
|
|
||||||
// Save the stack walking info we found, in case we need it later to
|
// 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;
|
uint32_t last_frame_callee_parameter_size = 0;
|
||||||
int frames_already_walked = frames.size();
|
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
|
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
|
WindowsFrameInfo* last_frame_callee_info
|
||||||
= last_frame_callee->windows_frame_info;
|
= last_frame_callee->windows_frame_info;
|
||||||
if (last_frame_callee_info &&
|
if (last_frame_callee_info &&
|
||||||
|
@ -516,6 +525,9 @@ StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo(
|
||||||
StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo(
|
StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo(
|
||||||
const vector<StackFrame*>& frames,
|
const vector<StackFrame*>& frames,
|
||||||
CFIFrameInfo* cfi_frame_info) {
|
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());
|
StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
|
||||||
last_frame->cfi_frame_info = cfi_frame_info;
|
last_frame->cfi_frame_info = cfi_frame_info;
|
||||||
|
|
||||||
|
@ -542,6 +554,9 @@ StackFrameX86* StackwalkerX86::GetCallerByEBPAtBase(
|
||||||
const vector<StackFrame*>& frames,
|
const vector<StackFrame*>& frames,
|
||||||
bool stack_scan_allowed) {
|
bool stack_scan_allowed) {
|
||||||
StackFrame::FrameTrust trust;
|
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());
|
StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
|
||||||
uint32_t last_esp = last_frame->context.esp;
|
uint32_t last_esp = last_frame->context.esp;
|
||||||
uint32_t last_ebp = last_frame->context.ebp;
|
uint32_t last_ebp = last_frame->context.ebp;
|
||||||
|
@ -634,6 +649,9 @@ StackFrame* StackwalkerX86::GetCallerFrame(const CallStack* stack,
|
||||||
|
|
||||||
const vector<StackFrame*>& frames = *stack->frames();
|
const vector<StackFrame*>& frames = *stack->frames();
|
||||||
StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
|
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;
|
scoped_ptr<StackFrameX86> new_frame;
|
||||||
|
|
||||||
// If the resolver has Windows stack walking information, use that.
|
// If the resolver has Windows stack walking information, use that.
|
||||||
|
|
Loading…
Reference in a new issue