Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix SetConsoleWindowInfo being able to crash ConPTY #13212

Merged
2 commits merged into from
Jun 1, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 10 additions & 21 deletions src/host/screenInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2268,30 +2268,19 @@ void SCREEN_INFORMATION::SetViewport(const Viewport& newViewport,
}

// do adjustments on a copy that's easily manipulated.
auto srCorrected = newViewport.ToExclusive();
const til::rect viewportRect{ newViewport.ToExclusive() };
const til::size coordScreenBufferSize{ GetBufferSize().Dimensions() };

if (srCorrected.Left < 0)
{
srCorrected.Right -= srCorrected.Left;
srCorrected.Left = 0;
}
if (srCorrected.Top < 0)
{
srCorrected.Bottom -= srCorrected.Top;
srCorrected.Top = 0;
}
// MSFT-33471786, GH#13193:
// newViewport may reside anywhere outside of the valid coordScreenBufferSize.
// For instance it might be scrolled down more than our text buffer allows to be scrolled.
const auto cx = gsl::narrow_cast<SHORT>(std::clamp(viewportRect.width(), 1, coordScreenBufferSize.width));
const auto cy = gsl::narrow_cast<SHORT>(std::clamp(viewportRect.height(), 1, coordScreenBufferSize.height));
Comment on lines +2277 to +2278
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const auto cx = gsl::narrow_cast<SHORT>(std::clamp(viewportRect.width(), 1, coordScreenBufferSize.width));
const auto cy = gsl::narrow_cast<SHORT>(std::clamp(viewportRect.height(), 1, coordScreenBufferSize.height));
const auto cx = gsl::narrow_cast<SHORT>(std::clamp(viewportRect.width(), 0, coordScreenBufferSize.width));
const auto cy = gsl::narrow_cast<SHORT>(std::clamp(viewportRect.height(), 0, coordScreenBufferSize.height));

curious, why not allow a width/height of 0?

Copy link
Member Author

@lhecker lhecker Jun 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The minimum size the TextBuffer allows is (1,1), so I thought it'd be reasonable if we did the same here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A text buffer with a zero dimension would not be a particularly useful text buffer :)

const auto x = gsl::narrow_cast<SHORT>(std::clamp(viewportRect.left, 0, coordScreenBufferSize.width - cx));
const auto y = gsl::narrow_cast<SHORT>(std::clamp(viewportRect.top, 0, coordScreenBufferSize.height - cy));
Comment on lines +2277 to +2280
Copy link
Member Author

@lhecker lhecker May 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function needs to correct the newViewport argument to be within the valid bounds, while retaining the given size as much as possible. If you pass a newViewport with the top/bottom coordinates -130 and -100, it should still result in a viewport that's 30 high, but with a top/bottom of 0 and 30.

I feel like this change increases the robustness of the code by splitting the viewport into its size (cx/cy) and origin (x/y). That way we can first ensure that the size doesn't exceed our limits (just like the old code seemingly intended) and then adjust the origin to be within the smaller rectangle of valid coordinates.

The gsl::narrow_cast<SHORT>s will be removed once my 32-bit coord PR has been merged, but it shouldn't pose a problem here either, as GetBufferSize().Dimensions() is a COORD which can't exceed a SHORT.


const auto coordScreenBufferSize = GetBufferSize().Dimensions();
if (srCorrected.Right > coordScreenBufferSize.X)
{
srCorrected.Right = coordScreenBufferSize.X;
}
if (srCorrected.Bottom > coordScreenBufferSize.Y)
{
srCorrected.Bottom = coordScreenBufferSize.Y;
}
_viewport = Viewport::FromExclusive({ x, y, x + cx, y + cy });

_viewport = Viewport::FromExclusive(srCorrected);
if (updateBottom)
{
UpdateBottom();
Expand Down