search: fix crash when searching the scrollback history

search_update_selection() was changed in 1.4.x to *first* update the
selection, *then* move the viewport.

This leads to a crash if the new match (selection) is outside the
current viewport; the selection code assumes the updated selection
endpoint is in the visible viewport.

Changing back to *first* move the viewport, *then* update the
selection solves this.
This commit is contained in:
Daniel Eklöf 2020-07-25 11:23:54 +02:00
parent 057ff3ba21
commit 9f82cbaa49
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 56 additions and 48 deletions

View file

@ -40,6 +40,10 @@
### Deprecated ### Deprecated
### Removed ### Removed
### Fixed ### Fixed
* Crash in scrollback search
### Security ### Security

View file

@ -104,47 +104,20 @@ search_update_selection(struct terminal *term,
int start_row, int start_col, int start_row, int start_col,
int end_row, int end_col) int end_row, int end_col)
{ {
/* Selection endpoint is inclusive */ bool move_viewport = true;
if (--end_col < 0) {
end_col = term->cols - 1;
end_row--;
}
/* Begin a new selection if the start coords changed */
if (start_row != term->search.match.row ||
start_col != term->search.match.col)
{
int selection_row = start_row - term->grid->view;
while (selection_row < 0)
selection_row += term->grid->num_rows;
assert(selection_row >= 0 &&
selection_row < term->grid->num_rows);
selection_start(term, start_col, selection_row, SELECTION_NORMAL);
}
/* Update selection endpoint */
{
int selection_row = end_row - term->grid->view;
while (selection_row < 0)
selection_row += term->grid->num_rows;
assert(selection_row >= 0 &&
selection_row < term->grid->num_rows);
selection_update(term, end_col, selection_row);
}
int view_end = (term->grid->view + term->rows - 1) & (term->grid->num_rows - 1); int view_end = (term->grid->view + term->rows - 1) & (term->grid->num_rows - 1);
if (view_end >= term->grid->view) { if (view_end >= term->grid->view) {
/* Viewport does *not* wrap around */ /* Viewport does *not* wrap around */
if (start_row >= term->grid->view && end_row <= view_end) if (start_row >= term->grid->view && end_row <= view_end)
return; move_viewport = false;
} else { } else {
/* Viewport wraps */ /* Viewport wraps */
if (start_row >= term->grid->view || end_row <= view_end) if (start_row >= term->grid->view || end_row <= view_end)
return; move_viewport = false;
} }
if (move_viewport) {
int old_view = term->grid->view; int old_view = term->grid->view;
int new_view = start_row - term->rows / 2; int new_view = start_row - term->rows / 2;
@ -181,6 +154,37 @@ search_update_selection(struct terminal *term,
term->grid->view = new_view; term->grid->view = new_view;
if (new_view != old_view) if (new_view != old_view)
term_damage_view(term); term_damage_view(term);
}
/* Selection endpoint is inclusive */
if (--end_col < 0) {
end_col = term->cols - 1;
end_row--;
}
/* Begin a new selection if the start coords changed */
if (start_row != term->search.match.row ||
start_col != term->search.match.col)
{
int selection_row = start_row - term->grid->view;
while (selection_row < 0)
selection_row += term->grid->num_rows;
assert(selection_row >= 0 &&
selection_row < term->grid->num_rows);
selection_start(term, start_col, selection_row, SELECTION_NORMAL);
}
/* Update selection endpoint */
{
int selection_row = end_row - term->grid->view;
while (selection_row < 0)
selection_row += term->grid->num_rows;
assert(selection_row >= 0 &&
selection_row < term->grid->num_rows);
selection_update(term, end_col, selection_row);
}
} }
static void static void