view src/testdir/test_autochdir.vim @ 33811:06219b3bdaf3 v9.0.2121

patch 9.0.2121: [security]: use-after-free in ex_substitute Commit: https://github.com/vim/vim/commit/26c11c56888d01e298cd8044caf860f3c26f57bb Author: Christian Brabandt <cb@256bit.org> Date: Wed Nov 22 21:26:41 2023 +0100 patch 9.0.2121: [security]: use-after-free in ex_substitute Problem: [security]: use-after-free in ex_substitute Solution: always allocate memory closes: #13552 A recursive :substitute command could cause a heap-use-after free in Vim (CVE-2023-48706). The whole reproducible test is a bit tricky, I can only reproduce this reliably when no previous substitution command has been used yet (which is the reason, the test needs to run as first one in the test_substitute.vim file) and as a combination of the `:~` command together with a :s command that contains the special substitution atom `~\=` which will make use of a sub-replace special atom and calls a vim script function. There was a comment in the existing :s code, that already makes the `sub` variable allocate memory so that a recursive :s call won't be able to cause any issues here, so this was known as a potential problem already. But for the current test-case that one does not work, because the substitution does not start with `\=` but with `~\=` (and since there does not yet exist a previous substitution atom, Vim will simply increment the `sub` pointer (which then was not allocated dynamically) and later one happily use a sub-replace special expression (which could then free the `sub` var). The following commit fixes this, by making the sub var always using allocated memory, which also means we need to free the pointer whenever we leave the function. Since sub is now always an allocated variable, we also do no longer need the sub_copy variable anymore, since this one was used to indicated when sub pointed to allocated memory (and had therefore to be freed on exit) and when not. Github Security Advisory: https://github.com/vim/vim/security/advisories/GHSA-c8qm-x72m-q53q Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Wed, 22 Nov 2023 22:15:05 +0100
parents 0fe61fa4e5d1
children
line wrap: on
line source

" Test 'autochdir' behavior

source check.vim
CheckOption autochdir

func Test_set_filename()
  let cwd = getcwd()
  call test_autochdir()
  set acd

  let s:li = []
  autocmd DirChanged auto call add(s:li, "autocd")
  autocmd DirChanged auto call add(s:li, expand("<afile>"))

  new
  w samples/Xtest
  call assert_equal("Xtest", expand('%'))
  call assert_equal("samples", substitute(getcwd(), '.*/\(\k*\)', '\1', ''))
  call assert_equal(["autocd", getcwd()], s:li)

  bwipe!
  au! DirChanged
  set noacd
  call chdir(cwd)
  call delete('samples/Xtest')
endfunc

func Test_set_filename_other_window()
  let cwd = getcwd()
  call test_autochdir()
  call mkdir('Xa', 'R')
  call mkdir('Xb', 'R')
  call mkdir('Xc', 'R')
  try
    args Xa/aaa.txt Xb/bbb.txt
    set acd
    let winid = win_getid()
    snext
    call assert_equal('Xb', substitute(getcwd(), '.*/\([^/]*\)$', '\1', ''))
    call win_execute(winid, 'file ' .. cwd .. '/Xc/ccc.txt')
    call assert_equal('Xb', substitute(getcwd(), '.*/\([^/]*\)$', '\1', ''))
  finally
    set noacd
    call chdir(cwd)
    bwipe! aaa.txt
    bwipe! bbb.txt
    bwipe! ccc.txt
  endtry
endfunc

func Test_acd_win_execute()
  let cwd = getcwd()
  set acd
  call test_autochdir()

  call mkdir('XacdDir', 'R')
  let winid = win_getid()
  new XacdDir/file
  call assert_match('testdir.XacdDir$', getcwd())
  cd ..
  call assert_match('testdir$', getcwd())
  call win_execute(winid, 'echo')
  call assert_match('testdir$', getcwd())

  bwipe!
  set noacd
  call chdir(cwd)
endfunc

func Test_verbose_pwd()
  let cwd = getcwd()
  call test_autochdir()

  edit global.txt
  call assert_match('\[global\].*testdir$', execute('verbose pwd'))

  call mkdir('Xautodir', 'R')
  split Xautodir/local.txt
  lcd Xautodir
  call assert_match('\[window\].*testdir[/\\]Xautodir', execute('verbose pwd'))

  set acd
  wincmd w
  call assert_match('\[autochdir\].*testdir$', execute('verbose pwd'))
  execute 'tcd' cwd
  call assert_match('\[tabpage\].*testdir$', execute('verbose pwd'))
  execute 'cd' cwd
  call assert_match('\[global\].*testdir$', execute('verbose pwd'))
  execute 'lcd' cwd
  call assert_match('\[window\].*testdir$', execute('verbose pwd'))
  edit
  call assert_match('\[autochdir\].*testdir$', execute('verbose pwd'))
  enew
  wincmd w
  call assert_match('\[autochdir\].*testdir[/\\]Xautodir', execute('verbose pwd'))
  wincmd w
  call assert_match('\[window\].*testdir$', execute('verbose pwd'))
  wincmd w
  call assert_match('\[autochdir\].*testdir[/\\]Xautodir', execute('verbose pwd'))
  set noacd
  call assert_match('\[autochdir\].*testdir[/\\]Xautodir', execute('verbose pwd'))
  wincmd w
  call assert_match('\[window\].*testdir$', execute('verbose pwd'))
  execute 'cd' cwd
  call assert_match('\[global\].*testdir$', execute('verbose pwd'))
  wincmd w
  call assert_match('\[window\].*testdir[/\\]Xautodir', execute('verbose pwd'))

  bwipe!
  call chdir(cwd)
endfunc

func Test_multibyte()
  " using an invalid character should not cause a crash
  set wic
  call assert_fails('tc *', has('win32') ? 'E480:' : 'E344:')
  set nowic
endfunc


" vim: shiftwidth=2 sts=2 expandtab