Skip to content

Commit

Permalink
Fix a sixel crash when the buffer is reflowed (#17951)
Browse files Browse the repository at this point in the history
## Summary of the Pull Request

The sixel parser has an internal buffer that holds the indexed-color
representation of the image, prior to it being translated to RGB. This
buffer only retains the section of the image that is within the visible
viewport, so we're continually erasing segments from the top of it when
the image is large enough to trigger a scroll.

But there is a problem that arises if the window or font is resized so
that the buffer needs to reflow, because that can result in the image
being pushed entirely offscreen. At that point the segment we're trying
to erase is actually larger than the buffer itself, which can end up
causing the terminal to crash

To fix this, we just need to check for an oversized erase attempt and
simply clear the buffer instead.

## Validation Steps Performed

I could easily reproduce this crash in Windows Terminal by resizing the
font while viewing an animated gif with img2sixel. With this PR applied
the crash no longer occurs.

## PR Checklist
- [x] Closes #17947

(cherry picked from commit fc586e2)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmQzgTTKv4
Service-Version: 1.22
  • Loading branch information
j4james authored and DHowett committed Sep 24, 2024
1 parent a2d7742 commit 145babe
Showing 1 changed file with 10 additions and 2 deletions.
12 changes: 10 additions & 2 deletions src/terminal/adapter/SixelParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -715,8 +715,16 @@ void SixelParser::_eraseImageBufferRows(const int rowCount, const til::CoordType
const auto pixelCount = rowCount * _cellSize.height;
const auto bufferOffset = rowOffset * _cellSize.height * _imageMaxWidth;
const auto bufferOffsetEnd = bufferOffset + pixelCount * _imageMaxWidth;
_imageBuffer.erase(_imageBuffer.begin() + bufferOffset, _imageBuffer.begin() + bufferOffsetEnd);
_imageCursor.y -= pixelCount;
if (static_cast<size_t>(bufferOffsetEnd) >= _imageBuffer.size()) [[unlikely]]
{
_imageBuffer.clear();
_imageCursor.y = 0;
}
else
{
_imageBuffer.erase(_imageBuffer.begin() + bufferOffset, _imageBuffer.begin() + bufferOffsetEnd);
_imageCursor.y -= pixelCount;
}
}

void SixelParser::_maybeFlushImageBuffer(const bool endOfSequence)
Expand Down

0 comments on commit 145babe

Please sign in to comment.