summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autoload/ale.vim15
-rw-r--r--autoload/ale/cursor.vim3
-rw-r--r--autoload/ale/engine.vim12
-rw-r--r--autoload/ale/util.vim16
-rw-r--r--test/test_sandbox_execution.vader51
5 files changed, 91 insertions, 6 deletions
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