Stop trying to set selection endpoints when there's no selection (#5855)

It turns out that we weren't really adequately guarding calls to
SetSelectionEnd and friends.

We're clearing the active selection when the window resizes, but we're
doing so by nulling out the std::optional<Selection> it lives in. Later,
though, when we set the selection endpoint we're using "_selection->".

Optional's operator-> has undefined behavior when the optional doesn't
have a value in it.

In our case, it looks like it was returning whatever the value was prior
to it being emptied out. PivotSelection would attempt to access an
out-of-bounds coordinate when the buffer got smaller during a resize.

The solution is to guard both levels of selection endpoint manipulation
in a check for an active selection.

Apparently, this accounts for somewhere between 7% and 14% of our
crashes on 1.0RC1.

Repro was:
Use Win+Arrow to snap the window while in the middle of a selection.
This commit is contained in:
Dustin L. Howett (MSFT)
2020-05-12 11:23:10 -07:00
committed by GitHub
parent e088f73671
commit fcd5bb39f0
2 changed files with 12 additions and 0 deletions

View File

@@ -138,6 +138,13 @@ void Terminal::SetSelectionAnchor(const COORD viewportPos)
// - newExpansionMode: overwrites the _multiClickSelectionMode for this function call. Used for ShiftClick
void Terminal::SetSelectionEnd(const COORD viewportPos, std::optional<SelectionExpansionMode> newExpansionMode)
{
if (!_selection.has_value())
{
// capture a log for spurious endpoint sets without an active selection
LOG_HR(E_ILLEGAL_STATE_CHANGE);
return;
}
const auto textBufferPos = _ConvertToBufferCell(viewportPos);
// if this is a shiftClick action, we need to overwrite the _multiClickSelectionMode value (even if it's the same)