]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1840: [security] use-after-free in do_ecmd v9.0.1840
authorChristian Brabandt <cb@256bit.org>
Sat, 2 Sep 2023 12:40:13 +0000 (14:40 +0200)
committerChristian Brabandt <cb@256bit.org>
Sat, 2 Sep 2023 12:44:47 +0000 (14:44 +0200)
Problem:  use-after-free in do_ecmd
Solution: Verify oldwin pointer after reset_VIsual()

Signed-off-by: Christian Brabandt <cb@256bit.org>
src/ex_cmds.c
src/testdir/Make_all.mak
src/testdir/crash/poc_huaf1 [new file with mode: 0644]
src/testdir/crash/poc_huaf2 [new file with mode: 0644]
src/testdir/crash/poc_huaf3 [new file with mode: 0644]
src/testdir/dumps/Test_crash_01.dump [new file with mode: 0644]
src/testdir/test_crash.vim [new file with mode: 0644]
src/version.c

index 20d4d9a2eaad0061fbf7a10a9416dd40d1fadb40..9348b4edda1579c178f6f721444a4056f8f685c2 100644 (file)
@@ -2646,12 +2646,18 @@ do_ecmd(
        goto theend;
     }
 
-    /*
-     * End Visual mode before switching to another buffer, so the text can be
-     * copied into the GUI selection buffer.
-     */
+    
+     // End Visual mode before switching to another buffer, so the text can be
+     // copied into the GUI selection buffer.
+     // Careful: may trigger ModeChanged() autocommand
+     
+    // Should we block autocommands here?
     reset_VIsual();
 
+    // autocommands freed window :(
+    if (oldwin != NULL && !win_valid(oldwin))
+       oldwin = NULL;
+
 #if defined(FEAT_EVAL)
     if ((command != NULL || newlnum > (linenr_T)0)
            && *get_vim_var_str(VV_SWAPCOMMAND) == NUL)
index e2e29f12d2b3ceb6d1343fcd9067d45ae41a19e7..961718fd699ce1bfc1ffea2112cf90a901e67704 100644 (file)
@@ -105,6 +105,7 @@ NEW_TESTS = \
        test_conceal \
        test_const \
        test_cpoptions \
+       test_crash \
        test_crypt \
        test_cscope \
        test_cursor_func \
@@ -369,6 +370,7 @@ NEW_TESTS_RES = \
        test_conceal.res \
        test_const.res \
        test_cpoptions.res \
+       test_crash.res \
        test_crypt.res \
        test_cscope.res \
        test_cursor_func.res \
diff --git a/src/testdir/crash/poc_huaf1 b/src/testdir/crash/poc_huaf1
new file mode 100644 (file)
index 0000000..0d0ea47
Binary files /dev/null and b/src/testdir/crash/poc_huaf1 differ
diff --git a/src/testdir/crash/poc_huaf2 b/src/testdir/crash/poc_huaf2
new file mode 100644 (file)
index 0000000..4867e0f
Binary files /dev/null and b/src/testdir/crash/poc_huaf2 differ
diff --git a/src/testdir/crash/poc_huaf3 b/src/testdir/crash/poc_huaf3
new file mode 100644 (file)
index 0000000..7e38a9a
Binary files /dev/null and b/src/testdir/crash/poc_huaf3 differ
diff --git a/src/testdir/dumps/Test_crash_01.dump b/src/testdir/dumps/Test_crash_01.dump
new file mode 100644 (file)
index 0000000..1f0fd44
--- /dev/null
@@ -0,0 +1,20 @@
+> +0&#ffffff0@74
+@75
+@75
+@75
+@75
+@75
+@75
+@75
+@75
+@75
+@75
+@75
+@75
+@75
+@75
+@75
+@75
+@75
+@75
+@75
diff --git a/src/testdir/test_crash.vim b/src/testdir/test_crash.vim
new file mode 100644 (file)
index 0000000..0dea3c2
--- /dev/null
@@ -0,0 +1,25 @@
+" Some tests, that used to crash Vim
+source check.vim
+source screendump.vim
+
+CheckScreendump
+
+func Test_crash1()
+  " The following used to crash Vim
+  let opts = #{wait_for_ruler: 0}
+  let args = ' -u NONE -i NONE -n -e -s -S '
+  let buf = RunVimInTerminal(args .. ' crash/poc_huaf1', opts)
+  call VerifyScreenDump(buf, 'Test_crash_01', {})
+  exe buf .. "bw!"
+
+  let buf = RunVimInTerminal(args .. ' crash/poc_huaf2', opts)
+  call VerifyScreenDump(buf, 'Test_crash_01', {})
+  exe buf .. "bw!"
+
+  let buf = RunVimInTerminal(args .. ' crash/poc_huaf3', opts)
+  call VerifyScreenDump(buf, 'Test_crash_01', {})
+  exe buf .. "bw!"
+
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
index 5f6995cc61e0297bb9270a76ce1e0bba88faf741..34878d74929c43b9f9189580fa3c78ff3576f448 100644 (file)
@@ -699,6 +699,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1840,
 /**/
     1839,
 /**/