signs: fix crash in buf_addsign #10091

buf_signcols sorting breaks signlist structure.

Remove sorting in buf_signcols, because signlist is already kept
sorted and it did not correctly update the double linked list.

Fixes #10078
This commit is contained in:
Andrej Zieger 2019-06-01 12:03:59 +02:00 committed by Justin M. Keyes
parent ef33500e17
commit 95ece7d046
2 changed files with 16 additions and 78 deletions

View File

@ -5256,92 +5256,28 @@ bool find_win_for_buf(buf_T *buf, win_T **wp, tabpage_T **tp)
return false; return false;
} }
static int sign_compare(const void *a1, const void *a2)
{
const signlist_T *s1 = *(const signlist_T **)a1;
const signlist_T *s2 = *(const signlist_T **)a2;
// Sort by line number, priority and id
if (s1->lnum > s2->lnum) {
return 1;
}
if (s1->lnum < s2->lnum) {
return -1;
}
if (s1->priority > s2->priority) {
return -1;
}
if (s1->priority < s2->priority) {
return 1;
}
if (s1->id > s2->id) {
return -1;
}
if (s1->id < s2->id) {
return 1;
}
return 0;
}
int buf_signcols(buf_T *buf) int buf_signcols(buf_T *buf)
{ {
if (buf->b_signcols_max == -1) { if (buf->b_signcols_max == -1) {
signlist_T *sign; // a sign in the signlist signlist_T *sign; // a sign in the signlist
signlist_T **signs_array;
signlist_T **prev_sign;
int nr_signs = 0, i = 0, same;
// Count the number of signs
for (sign = buf->b_signlist; sign != NULL; sign = sign->next) {
nr_signs++;
}
// Make an array of all the signs
signs_array = xcalloc((size_t)nr_signs, sizeof(*sign));
for (sign = buf->b_signlist; sign != NULL; sign = sign->next) {
signs_array[i] = sign;
i++;
}
// Sort the array
qsort(signs_array, (size_t)nr_signs, sizeof(signlist_T *),
sign_compare);
// Find the maximum amount of signs existing in a single line
buf->b_signcols_max = 0; buf->b_signcols_max = 0;
int linesum = 0;
linenr_T curline = 0;
same = 1; FOR_ALL_SIGNS_IN_BUF(buf, sign) {
for (i = 1; i < nr_signs; i++) { if (sign->lnum > curline) {
if (signs_array[i - 1]->lnum != signs_array[i]->lnum) { if (linesum > buf->b_signcols_max) {
if (buf->b_signcols_max < same) { buf->b_signcols_max = linesum;
buf->b_signcols_max = same;
}
same = 1;
} else {
same++;
} }
curline = sign->lnum;
linesum = 0;
}
linesum++;
} }
if (linesum > buf->b_signcols_max) {
if (nr_signs > 0 && buf->b_signcols_max < same) { buf->b_signcols_max = linesum;
buf->b_signcols_max = same;
} }
// Recreate the linked list with the sorted order of the array
buf->b_signlist = NULL;
prev_sign = &buf->b_signlist;
for (i = 0; i < nr_signs; i++) {
sign = signs_array[i];
sign->next = NULL;
*prev_sign = sign;
prev_sign = &sign->next;
}
xfree(signs_array);
// Check if we need to redraw // Check if we need to redraw
if (buf->b_signcols_max != buf->b_signcols) { if (buf->b_signcols_max != buf->b_signcols) {
buf->b_signcols = buf->b_signcols_max; buf->b_signcols = buf->b_signcols_max;

View File

@ -231,9 +231,11 @@ static void insert_sign_by_lnum_prio(
{ {
signlist_T *sign; signlist_T *sign;
// keep signs sorted by lnum and by priority: insert new sign at // keep signs sorted by lnum, priority and id: insert new sign at
// the proper position in the list for this lnum. // the proper position in the list for this lnum.
while (prev != NULL && prev->lnum == lnum && prev->priority <= prio) { while (prev != NULL && prev->lnum == lnum
&& (prev->priority < prio
|| (prev->priority == prio && prev->id <= id))) {
prev = prev->prev; prev = prev->prev;
} }
if (prev == NULL) { if (prev == NULL) {