SC2248: Warn about unquoted variables without special chars
This commit is contained in:
parent
c860b74505
commit
b76c0a8221
|
@ -4,6 +4,7 @@
|
||||||
- Files containing Bats tests can now be checked
|
- Files containing Bats tests can now be checked
|
||||||
- Directory wide directives can now be placed in a `.shellcheckrc`
|
- Directory wide directives can now be placed in a `.shellcheckrc`
|
||||||
- Verbose mode: Use `-S verbose` for especially pedantic suggestions
|
- Verbose mode: Use `-S verbose` for especially pedantic suggestions
|
||||||
|
- SC2248: Warn about unquoted variables without special chars (verbose)
|
||||||
- SC2247: Warn about $"(cmd)" and $"{var}"
|
- SC2247: Warn about $"(cmd)" and $"{var}"
|
||||||
- SC2246: Warn if a shebang's interpreter ends with /
|
- SC2246: Warn if a shebang's interpreter ends with /
|
||||||
- SC2245: Warn that Ksh ignores all but the first glob result in `[`
|
- SC2245: Warn that Ksh ignores all but the first glob result in `[`
|
||||||
|
|
|
@ -53,7 +53,7 @@ treeChecks = [
|
||||||
(\p t -> (mapM_ ((\ f -> f t) . (\ f -> f p))
|
(\p t -> (mapM_ ((\ f -> f t) . (\ f -> f p))
|
||||||
nodeChecks))
|
nodeChecks))
|
||||||
,subshellAssignmentCheck
|
,subshellAssignmentCheck
|
||||||
,checkSpacefulness
|
,checkVerboseSpacefulness
|
||||||
,checkQuotesInLiterals
|
,checkQuotesInLiterals
|
||||||
,checkShebangParameters
|
,checkShebangParameters
|
||||||
,checkFunctionsUsedExternally
|
,checkFunctionsUsedExternally
|
||||||
|
@ -1639,10 +1639,12 @@ prop_checkSpacefulness2 = verifyNotTree checkSpacefulness "a='cow moo'; [[ $a ]]
|
||||||
prop_checkSpacefulness3 = verifyNotTree checkSpacefulness "a='cow*.mp3'; echo \"$a\""
|
prop_checkSpacefulness3 = verifyNotTree checkSpacefulness "a='cow*.mp3'; echo \"$a\""
|
||||||
prop_checkSpacefulness4 = verifyTree checkSpacefulness "for f in *.mp3; do echo $f; done"
|
prop_checkSpacefulness4 = verifyTree checkSpacefulness "for f in *.mp3; do echo $f; done"
|
||||||
prop_checkSpacefulness4a= verifyNotTree checkSpacefulness "foo=3; foo=$(echo $foo)"
|
prop_checkSpacefulness4a= verifyNotTree checkSpacefulness "foo=3; foo=$(echo $foo)"
|
||||||
|
prop_checkSpacefulness4v= verifyTree checkVerboseSpacefulness "foo=3; foo=$(echo $foo)"
|
||||||
prop_checkSpacefulness5 = verifyTree checkSpacefulness "a='*'; b=$a; c=lol${b//foo/bar}; echo $c"
|
prop_checkSpacefulness5 = verifyTree checkSpacefulness "a='*'; b=$a; c=lol${b//foo/bar}; echo $c"
|
||||||
prop_checkSpacefulness6 = verifyTree checkSpacefulness "a=foo$(lol); echo $a"
|
prop_checkSpacefulness6 = verifyTree checkSpacefulness "a=foo$(lol); echo $a"
|
||||||
prop_checkSpacefulness7 = verifyTree checkSpacefulness "a=foo\\ bar; rm $a"
|
prop_checkSpacefulness7 = verifyTree checkSpacefulness "a=foo\\ bar; rm $a"
|
||||||
prop_checkSpacefulness8 = verifyNotTree checkSpacefulness "a=foo\\ bar; a=foo; rm $a"
|
prop_checkSpacefulness8 = verifyNotTree checkSpacefulness "a=foo\\ bar; a=foo; rm $a"
|
||||||
|
prop_checkSpacefulness8v= verifyTree checkVerboseSpacefulness "a=foo\\ bar; a=foo; rm $a"
|
||||||
prop_checkSpacefulness10= verifyTree checkSpacefulness "rm $1"
|
prop_checkSpacefulness10= verifyTree checkSpacefulness "rm $1"
|
||||||
prop_checkSpacefulness11= verifyTree checkSpacefulness "rm ${10//foo/bar}"
|
prop_checkSpacefulness11= verifyTree checkSpacefulness "rm ${10//foo/bar}"
|
||||||
prop_checkSpacefulness12= verifyNotTree checkSpacefulness "(( $1 + 3 ))"
|
prop_checkSpacefulness12= verifyNotTree checkSpacefulness "(( $1 + 3 ))"
|
||||||
|
@ -1662,6 +1664,7 @@ prop_checkSpacefulness25= verifyTree checkSpacefulness "a='s/[0-9]//g'; sed $a"
|
||||||
prop_checkSpacefulness26= verifyTree checkSpacefulness "a='foo bar'; echo {1,2,$a}"
|
prop_checkSpacefulness26= verifyTree checkSpacefulness "a='foo bar'; echo {1,2,$a}"
|
||||||
prop_checkSpacefulness27= verifyNotTree checkSpacefulness "echo ${a:+'foo'}"
|
prop_checkSpacefulness27= verifyNotTree checkSpacefulness "echo ${a:+'foo'}"
|
||||||
prop_checkSpacefulness28= verifyNotTree checkSpacefulness "exec {n}>&1; echo $n"
|
prop_checkSpacefulness28= verifyNotTree checkSpacefulness "exec {n}>&1; echo $n"
|
||||||
|
prop_checkSpacefulness28v = verifyTree checkVerboseSpacefulness "exec {n}>&1; echo $n"
|
||||||
prop_checkSpacefulness29= verifyNotTree checkSpacefulness "n=$(stuff); exec {n}>&-;"
|
prop_checkSpacefulness29= verifyNotTree checkSpacefulness "n=$(stuff); exec {n}>&-;"
|
||||||
prop_checkSpacefulness30= verifyTree checkSpacefulness "file='foo bar'; echo foo > $file;"
|
prop_checkSpacefulness30= verifyTree checkSpacefulness "file='foo bar'; echo foo > $file;"
|
||||||
prop_checkSpacefulness31= verifyNotTree checkSpacefulness "echo \"`echo \\\"$1\\\"`\""
|
prop_checkSpacefulness31= verifyNotTree checkSpacefulness "echo \"`echo \\\"$1\\\"`\""
|
||||||
|
@ -1670,9 +1673,15 @@ prop_checkSpacefulness33= verifyTree checkSpacefulness "for file; do echo $file;
|
||||||
prop_checkSpacefulness34= verifyTree checkSpacefulness "declare foo$n=$1"
|
prop_checkSpacefulness34= verifyTree checkSpacefulness "declare foo$n=$1"
|
||||||
prop_checkSpacefulness35= verifyNotTree checkSpacefulness "echo ${1+\"$1\"}"
|
prop_checkSpacefulness35= verifyNotTree checkSpacefulness "echo ${1+\"$1\"}"
|
||||||
prop_checkSpacefulness36= verifyNotTree checkSpacefulness "arg=$#; echo $arg"
|
prop_checkSpacefulness36= verifyNotTree checkSpacefulness "arg=$#; echo $arg"
|
||||||
|
prop_checkSpacefulness36v = verifyTree checkVerboseSpacefulness "arg=$#; echo $arg"
|
||||||
prop_checkSpacefulness37= verifyNotTree checkSpacefulness "@test 'status' {\n [ $status -eq 0 ]\n}"
|
prop_checkSpacefulness37= verifyNotTree checkSpacefulness "@test 'status' {\n [ $status -eq 0 ]\n}"
|
||||||
|
prop_checkSpacefulness37v = verifyTree checkVerboseSpacefulness "@test 'status' {\n [ $status -eq 0 ]\n}"
|
||||||
|
|
||||||
checkSpacefulness params t =
|
-- This is slightly awkward because we want the tests to
|
||||||
|
-- discriminate between normal and verbose output.
|
||||||
|
checkSpacefulness params t = checkSpacefulness' False params t
|
||||||
|
checkVerboseSpacefulness params t = checkSpacefulness' True params t
|
||||||
|
checkSpacefulness' alsoVerbose params t =
|
||||||
doVariableFlowAnalysis readF writeF (Map.fromList defaults) (variableFlow params)
|
doVariableFlowAnalysis readF writeF (Map.fromList defaults) (variableFlow params)
|
||||||
where
|
where
|
||||||
defaults = zip variablesWithoutSpaces (repeat False)
|
defaults = zip variablesWithoutSpaces (repeat False)
|
||||||
|
@ -1686,23 +1695,33 @@ checkSpacefulness params t =
|
||||||
|
|
||||||
readF _ token name = do
|
readF _ token name = do
|
||||||
spaces <- hasSpaces name
|
spaces <- hasSpaces name
|
||||||
return [warning |
|
let needsQuoting =
|
||||||
isExpansion token && spaces
|
isExpansion token
|
||||||
&& not (isArrayExpansion token) -- There's another warning for this
|
&& not (isArrayExpansion token) -- There's another warning for this
|
||||||
&& not (isCountingReference token)
|
&& not (isCountingReference token)
|
||||||
&& not (isQuoteFree parents token)
|
&& not (isQuoteFree parents token)
|
||||||
&& not (isQuotedAlternativeReference token)
|
&& not (isQuotedAlternativeReference token)
|
||||||
&& not (usedAsCommandName parents token)]
|
&& not (usedAsCommandName parents token)
|
||||||
where
|
|
||||||
warning =
|
return . execWriter $ when needsQuoting $
|
||||||
|
if spaces
|
||||||
|
then
|
||||||
if isDefaultAssignment (parentMap params) token
|
if isDefaultAssignment (parentMap params) token
|
||||||
then
|
then
|
||||||
makeComment InfoC (getId token) 2223
|
emit $ makeComment InfoC (getId token) 2223
|
||||||
"This default assignment may cause DoS due to globbing. Quote it."
|
"This default assignment may cause DoS due to globbing. Quote it."
|
||||||
else
|
else
|
||||||
makeCommentWithFix InfoC (getId token) 2086
|
emit $ makeCommentWithFix InfoC (getId token) 2086
|
||||||
"Double quote to prevent globbing and word splitting."
|
"Double quote to prevent globbing and word splitting."
|
||||||
(surroundWidth (getId token) params "\"")
|
(fixFor token)
|
||||||
|
else
|
||||||
|
when (alsoVerbose && name `notElem` specialVariablesWithoutSpaces) $
|
||||||
|
emit $ makeCommentWithFix VerboseC (getId token) 2248
|
||||||
|
"Prefer double quoting even when variables don't contain special characters."
|
||||||
|
(fixFor token)
|
||||||
|
where
|
||||||
|
fixFor token = (surroundWidth (getId token) params "\"")
|
||||||
|
emit x = tell [x]
|
||||||
|
|
||||||
writeF _ _ name (DataString SourceExternal) = setSpaces name True >> return []
|
writeF _ _ name (DataString SourceExternal) = setSpaces name True >> return []
|
||||||
writeF _ _ name (DataString SourceInteger) = setSpaces name False >> return []
|
writeF _ _ name (DataString SourceInteger) = setSpaces name False >> return []
|
||||||
|
|
|
@ -38,8 +38,10 @@ internalVariables = [
|
||||||
, ".sh.version"
|
, ".sh.version"
|
||||||
]
|
]
|
||||||
|
|
||||||
variablesWithoutSpaces = [
|
specialVariablesWithoutSpaces = [
|
||||||
"$", "-", "?", "!", "#",
|
"$", "-", "?", "!", "#"
|
||||||
|
]
|
||||||
|
variablesWithoutSpaces = specialVariablesWithoutSpaces ++ [
|
||||||
"BASHPID", "BASH_ARGC", "BASH_LINENO", "BASH_SUBSHELL", "EUID", "LINENO",
|
"BASHPID", "BASH_ARGC", "BASH_LINENO", "BASH_SUBSHELL", "EUID", "LINENO",
|
||||||
"OPTIND", "PPID", "RANDOM", "SECONDS", "SHELLOPTS", "SHLVL", "UID",
|
"OPTIND", "PPID", "RANDOM", "SECONDS", "SHELLOPTS", "SHLVL", "UID",
|
||||||
"COLUMNS", "HISTFILESIZE", "HISTSIZE", "LINES"
|
"COLUMNS", "HISTFILESIZE", "HISTSIZE", "LINES"
|
||||||
|
|
Loading…
Reference in New Issue