Skip to content

Commit

Permalink
BugFix: try and prevent crashing during highlighting
Browse files Browse the repository at this point in the history
It seems that one of the tests in `(void) TTextEdit::highlightSelection()`
was being done too late - with the result that out of range indexing was
being attempted on the `(std::deque<std::deque<TChar>) TBuffer::buffer`
member. Specifically the test for `currentY >= totaly` should have been
done before `currentY` was used to select one from the outer `std::deque`
container so as to establish the size of it (to be stored as `maxX`).

The revised code replaces both the highlight and un-highlight code nested
loops with components that are more conventionally used, i.e. with the
test being based on a less than condition only with the limit being
determined within the top parts of the for loops and no additional tests
to break from the loop within the body thereof...

Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
  • Loading branch information
SlySven committed Jul 27, 2020
1 parent f4afc37 commit 1edc59d
Showing 1 changed file with 34 additions and 34 deletions.
68 changes: 34 additions & 34 deletions src/TTextEdit.cpp
Expand Up @@ -645,28 +645,27 @@ void TTextEdit::highlightSelection()

mSelectedRegion = mSelectedRegion.subtracted(newRegion);

int startY = mPA.y();
auto totalY = static_cast<int>(mpBuffer->buffer.size());
for (int currentY = startY, total = mPB.y(); currentY <= total; ++currentY) {
int currentX = 0;
int maxX = static_cast<int>(mpBuffer->buffer.at(currentY).size());
if (currentY == startY) {
currentX = mPA.x();
}

if (currentY >= totalY) {
break;
}

for (; currentX < maxX; ++currentX) {
if ((currentY == mPB.y()) && (currentX > mPB.x())) {
break;
}
if (!(mpBuffer->buffer.at(currentY).at(currentX).isSelected())) {
mpBuffer->buffer.at(currentY).at(currentX).select();
}
// mpA represents the first (zero-based) line/row (y) and position/column
// (x) that IS to be selected, mpB represents the last (zero-based) line and
// column that IS to be selected - which means that in the traditional 'for'
// loop construct where the test is a '<' based one, the test limit is
// mpB.y() + 1 for the row and mpB.x() + 1 for the column:
// clang-format off
for (int y = std::max(0, mPA.y()), endY = std::min((mPB.y() + 1), static_cast<int>(mpBuffer->buffer.size()));
y < endY;
++y) {

for (int x = (y == mPA.y()) ? std::max(0, mPA.x()) : 0,
endX = (y == (mPB.y()))
? std::min((mPB.x() + 1), static_cast<int>(mpBuffer->buffer.at(y).size()))
: static_cast<int>(mpBuffer->buffer.at(y).size());
x < endX;
++x) {

mpBuffer->buffer.at(y).at(x).select();
}
}
// clang-format on

update(mSelectedRegion.boundingRect());
update(newRegion);
Expand All @@ -676,23 +675,24 @@ void TTextEdit::highlightSelection()
void TTextEdit::unHighlight()
{
normaliseSelection();
int y1 = mPA.y();

if (y1 < 0) {
return;
}
for (int y = y1, total = mPB.y(); y <= total; ++y) {
int x = 0;

if (y >= static_cast<int>(mpBuffer->buffer.size())) {
break;
// clang-format off
for (int y = std::max(0, mPA.y()), endY = std::min((mPB.y() + 1), static_cast<int>(mpBuffer->buffer.size()));
y < endY;
++y) {

for (int x = (y == mPA.y()) ? std::max(0, mPA.x()) : 0,
endX = (y == (mPB.y()))
? std::min((mPB.x() + 1), static_cast<int>(mpBuffer->buffer.at(y).size()))
: static_cast<int>(mpBuffer->buffer.at(y).size());
x < endX;
++x) {

mpBuffer->buffer.at(y).at(x).deselect();
}

for (; x < static_cast<int>(mpBuffer->buffer.at(y).size()); ++x)
if (mpBuffer->buffer.at(y).at(x).isSelected()) {
mpBuffer->buffer.at(y).at(x).deselect();
}
}
// clang-format on

forceUpdate();
}

Expand Down

0 comments on commit 1edc59d

Please sign in to comment.