From c460602cbbf80c1b1b3f006ae3dd28528a80c17c Mon Sep 17 00:00:00 2001 From: w0rp Date: Tue, 14 Feb 2017 21:02:49 +0000 Subject: [PATCH] #338 Try and stop ALE from throwing ALEs when run from a sandbox --- autoload/ale.vim | 15 ++++++--- autoload/ale/cursor.vim | 3 +- autoload/ale/engine.vim | 12 ++++++++ autoload/ale/util.vim | 16 ++++++++++ test/test_sandbox_execution.vader | 51 +++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 test/test_sandbox_execution.vader diff --git a/autoload/ale.vim b/autoload/ale.vim index a5251f64..c81a57a6 100644 --- a/autoload/ale.vim +++ b/autoload/ale.vim @@ -4,9 +4,17 @@ let s:lint_timer = -1 +" A function for checking various conditions whereby ALE just shouldn't +" attempt to do anything, say if particular buffer types are open in Vim. +function! ale#ShouldDoNothing() abort + " Do nothing for blacklisted files + " OR if ALE is running in the sandbox + return index(g:ale_filetype_blacklist, &filetype) >= 0 + \ || ale#util#InSandbox() +endfunction + function! ale#Queue(delay) abort - " Do nothing for blacklisted files. - if index(g:ale_filetype_blacklist, &filetype) >= 0 + if ale#ShouldDoNothing() return endif @@ -29,8 +37,7 @@ function! ale#Queue(delay) abort endfunction function! ale#Lint(...) abort - " Do nothing for blacklisted files. - if index(g:ale_filetype_blacklist, &filetype) >= 0 + if ale#ShouldDoNothing() return endif diff --git a/autoload/ale/cursor.vim b/autoload/ale/cursor.vim index 864f6f28..9aaa8e91 100644 --- a/autoload/ale/cursor.vim +++ b/autoload/ale/cursor.vim @@ -73,8 +73,7 @@ let s:cursor_timer = -1 let s:last_pos = [0, 0, 0] function! ale#cursor#EchoCursorWarningWithDelay() abort - " Do nothing for blacklisted files. - if index(g:ale_filetype_blacklist, &filetype) >= 0 + if ale#ShouldDoNothing() return endif diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim index 5337fc2d..d816a96b 100644 --- a/autoload/ale/engine.vim +++ b/autoload/ale/engine.vim @@ -155,6 +155,12 @@ function! ale#engine#RemoveManagedFiles(buffer) abort return endif + " We can't delete anything in a sandbox, so wait until we escape from + " it to delete temporary files and directories. + if ale#util#InSandbox() + return + endif + " Delete files with a call akin to a plan `rm` command. for l:filename in g:ale_buffer_info[a:buffer].temporary_file_list call delete(l:filename) @@ -195,6 +201,12 @@ function! s:HandleExit(job) abort " which just closed. call s:StopPreviousJobs(l:buffer, l:linter) + " Stop here if we land in the handle for a job completing if we're in + " a sandbox. + if ale#util#InSandbox() + return + endif + if l:next_chain_index < len(get(l:linter, 'command_chain', [])) call s:InvokeChain(l:buffer, l:linter, l:next_chain_index, l:output) return diff --git a/autoload/ale/util.vim b/autoload/ale/util.vim index 6367489c..bf00051a 100644 --- a/autoload/ale/util.vim +++ b/autoload/ale/util.vim @@ -118,3 +118,19 @@ function! ale#util#BinarySearch(loclist, line, column) abort endif endwhile endfunction + +" A function for testing if a function is running inside a sandbox. +" See :help sandbox +function! ale#util#InSandbox() abort + try + call setbufvar('%', '', '') + catch /^Vim\%((\a\+)\)\=:E48/ + " E48 is the sandbox error. + return 1 + catch + " If we're not in a sandbox, we'll get another error about an + " invalid buffer variable name. + endtry + + return 0 +endfunction diff --git a/test/test_sandbox_execution.vader b/test/test_sandbox_execution.vader new file mode 100644 index 00000000..a4cd84d6 --- /dev/null +++ b/test/test_sandbox_execution.vader @@ -0,0 +1,51 @@ +Before: + function! TestCallback(buffer, output) + return [ + \ { + \ 'lnum': 1, + \ 'bufnr': 1, + \ 'vcol': 0, + \ 'linter_name': 'testlinter', + \ 'nr': -1, + \ 'type': 'E', + \ 'col': 1, + \ 'text': 'Test Error', + \ }, + \] + endfunction + + call ale#linter#Define('foobar', { + \ 'name': 'testlinter', + \ 'callback': 'TestCallback', + \ 'executable': 'echo', + \ 'command': 'echo', + \}) + + let g:ale_buffer_info = {} + +After: + delfunction TestCallback + call ale#linter#Reset() + let g:ale_buffer_info = {} + +Given foobar (Some imaginary filetype): + foo + bar + baz + +Execute(ALE shouldn't blow up when run from a sandbox): + AssertEqual 'foobar', &filetype + + sandbox call ale#Queue(0) + sandbox call ale#Queue(1) + sandbox call ale#Lint() + +Execute(ALE shouldn't blow up if file cleanup happens in a sandbox): + let g:ale_buffer_info[3] = { + \ 'temporary_file_list': ['/tmp/foo'], + \ 'temporary_directory_list': ['/tmp/bar'], + \} + sandbox call ale#engine#RemoveManagedFiles(3) + + AssertEqual ['/tmp/foo'], g:ale_buffer_info[3].temporary_file_list + AssertEqual ['/tmp/bar'], g:ale_buffer_info[3].temporary_directory_list