From f7c4c403ebb2460e056bdb80463d75a32174bafa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-Xavier=20Carton?= Date: Sat, 29 Dec 2018 01:11:35 +0100 Subject: [PATCH] Fix CFLAGS parsing Split by space instead of dash. This prevents incorrect parsing where space-separated arguments are merged (in particular, .c or .o files were appended to -I or -D arguments). Handle shell escape: quotes and escaped quotes \" and shell substitutions are recognised. This is done by verifying that no special character (" ' ` ()) has not a matching character. Fixes #2049 --- autoload/ale/c.vim | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/autoload/ale/c.vim b/autoload/ale/c.vim index ce5105b6..617e81f6 100644 --- a/autoload/ale/c.vim +++ b/autoload/ale/c.vim @@ -48,26 +48,38 @@ endfunction function! ale#c#ParseCFlags(path_prefix, cflag_line) abort let l:cflags_list = [] - let l:previous_options = [] + let l:previous_options = '' - let l:split_lines = split(a:cflag_line, '-') + let l:split_lines = split(a:cflag_line, ' ') let l:option_index = 0 while l:option_index < len(l:split_lines) - let l:option = l:split_lines[l:option_index] + let l:option = l:previous_options . l:split_lines[l:option_index] let l:option_index = l:option_index + 1 - call add(l:previous_options, l:option) - " Check if cflag contained a '-' and should not have been splitted - let l:option_list = split(l:option, '\zs') - if len(l:option_list) > 0 && l:option_list[-1] isnot# ' ' && l:option_index < len(l:split_lines) + " Check if cflag contained an unmatched characters and should not have been splitted + let l:option_special = substitute(l:option, '\\"', '', 'g') + let l:option_special = substitute(l:option_special, '[^"''()`]', '', 'g') + let l:option_special = substitute(l:option_special, '""', '', 'g') + let l:option_special = substitute(l:option_special, '''''', '', 'g') + let l:option_special = substitute(l:option_special, '``', '', 'g') + let l:option_special = substitute(l:option_special, '((', '(', 'g') + let l:option_special = substitute(l:option_special, '))', ')', 'g') + let l:option_special = substitute(l:option_special, '()', '', 'g') + + if len(l:option_special) > 0 && l:option_index < len(l:split_lines) + let l:previous_options = l:option . ' ' continue endif - let l:option = join(l:previous_options, '-') - let l:previous_options = [] + " Check if there was spaces after -D/-I and the flag should not have been splitted + if l:option is# '-D' || l:option is# '-I' + let l:previous_options = l:option + continue + endif + + let l:previous_options = '' - let l:option = '-' . substitute(l:option, '^\s*\(.\{-}\)\s*$', '\1', '') " Fix relative paths if needed if stridx(l:option, '-I') >= 0 &&