aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/diff.c
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-07-29 06:53:32 +0800
committerGitHub <noreply@github.com>2022-07-29 06:53:32 +0800
commit352a177dae5b602f5685faa3ce4ad841d3ddbc15 (patch)
treea8eb685f44f2ade850d2536ad2c98d480196bbc7 /src/nvim/diff.c
parentb25abbf4b8a08899bba87809124c882928d99e21 (diff)
downloadrneovim-352a177dae5b602f5685faa3ce4ad841d3ddbc15.tar.gz
rneovim-352a177dae5b602f5685faa3ce4ad841d3ddbc15.tar.bz2
rneovim-352a177dae5b602f5685faa3ce4ad841d3ddbc15.zip
vim-patch:9.0.0026: accessing freed memory with diff put (#19564)
Problem: Accessing freed memory with diff put. Solution: Bail out when diff pointer is no longer valid. https://github.com/vim/vim/commit/c5274dd12224421f2430b30c53b881b9403d649e
Diffstat (limited to 'src/nvim/diff.c')
-rw-r--r--src/nvim/diff.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 4ade6072e6..59a1ce9932 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -2487,6 +2487,17 @@ void nv_diffgetput(bool put, size_t count)
ex_diffgetput(&ea);
}
+/// Return true if "diff" appears in the list of diff blocks of the current tab.
+static bool valid_diff(diff_T *diff)
+{
+ for (diff_T *dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) {
+ if (dp == diff) {
+ return true;
+ }
+ }
+ return false;
+}
+
/// ":diffget" and ":diffput"
///
/// @param eap
@@ -2744,10 +2755,9 @@ void ex_diffgetput(exarg_T *eap)
}
}
- // Adjust marks. This will change the following entries!
if (added != 0) {
- mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, added,
- kExtmarkUndo);
+ // Adjust marks. This will change the following entries!
+ mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, added, kExtmarkUndo);
if (curwin->w_cursor.lnum >= lnum) {
// Adjust the cursor position if it's in/after the changed
// lines.
@@ -2764,7 +2774,15 @@ void ex_diffgetput(exarg_T *eap)
// Diff is deleted, update folds in other windows.
diff_fold_update(dfree, idx_to);
xfree(dfree);
- } else {
+ }
+
+ // mark_adjust() may have made "dp" invalid. We don't know where
+ // to continue then, bail out.
+ if (added != 0 && !valid_diff(dp)) {
+ break;
+ }
+
+ if (dfree == NULL) {
// mark_adjust() may have changed the count in a wrong way
dp->df_count[idx_to] = new_count;
}