fix(marktree): preserve ordering in marktree_move

`marktree_move` is making the tree out of order at:

be10d65bfa/src/nvim/marktree.c (L1188)

Because `key` is at the new position, and `x->key[new_i]` is also at the
new position, this comparison spuriously returns true, which causes
`x->key[i]` to be updated in-place even when it needs to be moved.

This causes crashes down the line, since the ordering of `MTNode.key` is
an invariant that must be preserved.

Fixes: #25157
This commit is contained in:
L Lllvvuu 2023-09-16 01:08:06 -07:00
parent 40bfca744d
commit 34be915f6b
No known key found for this signature in database
GPG Key ID: CFAD5A25056DDD0F

View File

@ -1178,6 +1178,9 @@ void marktree_move(MarkTree *b, MarkTreeIter *itr, int row, int col)
} }
if (internal) { if (internal) {
if (key.pos.row == newpos.row && key.pos.col == newpos.col) {
return;
}
key.pos = newpos; key.pos = newpos;
bool match; bool match;
// tricky: could minimize movement in either direction better // tricky: could minimize movement in either direction better
@ -1185,7 +1188,7 @@ void marktree_move(MarkTree *b, MarkTreeIter *itr, int row, int col)
if (!match) { if (!match) {
new_i++; new_i++;
} }
if (new_i == itr->i || key_cmp(key, x->key[new_i]) == 0) { if (new_i == itr->i) {
x->key[itr->i].pos = newpos; x->key[itr->i].pos = newpos;
} else if (new_i < itr->i) { } else if (new_i < itr->i) {
memmove(&x->key[new_i + 1], &x->key[new_i], sizeof(MTKey) * (size_t)(itr->i - new_i)); memmove(&x->key[new_i + 1], &x->key[new_i], sizeof(MTKey) * (size_t)(itr->i - new_i));