Skip to content

Commit a44f3ed

Browse files
committed
Warn about eval'ing arrays
1 parent e33146d commit a44f3ed

File tree

3 files changed

+24
-0
lines changed

3 files changed

+24
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
- SC2289: Warn when command name contains tabs or linefeeds
55
- SC2291: Warn about repeated unquoted spaces between words in echo
66
- SC2292: Suggest [[ over [ in Bash/Ksh scripts (optional)
7+
- SC2293/SC2294: Warn when calling `eval` with arrays
78

89
### Fixed
910
- SC2102 about repetitions in ranges no longer triggers on [[ -v arr[xx] ]]

src/ShellCheck/AnalyzerLib.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,8 @@ getBracedReference s = fromMaybe s $
872872
prop_getBracedModifier1 = getBracedModifier "foo:bar:baz" == ":bar:baz"
873873
prop_getBracedModifier2 = getBracedModifier "!var:-foo" == ":-foo"
874874
prop_getBracedModifier3 = getBracedModifier "foo[bar]" == "[bar]"
875+
prop_getBracedModifier4 = getBracedModifier "foo[@]@Q" == "[@]@Q"
876+
prop_getBracedModifier5 = getBracedModifier "@@Q" == "@Q"
875877
getBracedModifier s = headOrDefault "" $ do
876878
let var = getBracedReference s
877879
a <- dropModifier s

src/ShellCheck/Checks/Commands.hs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ commandChecks = [
9696
,checkChmodDashr
9797
,checkXargsDashi
9898
,checkUnquotedEchoSpaces
99+
,checkEvalArray
99100
]
100101
++ map checkArgComparison declaringCommands
101102
++ map checkMaskedReturns declaringCommands
@@ -1258,5 +1259,25 @@ checkUnquotedEchoSpaces = CommandCheck (Basename "echo") check
12581259
&& not (any (\x -> b < x && x < c) redirs)
12591260

12601261

1262+
prop_checkEvalArray1 = verify checkEvalArray "eval $@"
1263+
prop_checkEvalArray2 = verify checkEvalArray "eval \"${args[@]}\""
1264+
prop_checkEvalArray3 = verify checkEvalArray "eval \"${args[@]@Q}\""
1265+
prop_checkEvalArray4 = verifyNot checkEvalArray "eval \"${args[*]@Q}\""
1266+
prop_checkEvalArray5 = verifyNot checkEvalArray "eval \"$*\""
1267+
checkEvalArray = CommandCheck (Exactly "eval") (mapM_ check . concatMap getWordParts . arguments)
1268+
where
1269+
check t =
1270+
when (isArrayExpansion t) $
1271+
if isEscaped t
1272+
then style (getId t) 2293 "When eval'ing @Q-quoted words, use * rather than @ as the index."
1273+
else warn (getId t) 2294 "eval negates the benefit of arrays. Drop eval to preserve whitespace/symbols (or eval as string)."
1274+
1275+
isEscaped q =
1276+
case q of
1277+
-- Match ${arr[@]@Q} and ${@@Q} and such
1278+
T_DollarBraced _ _ l -> 'Q' `elem` getBracedModifier (concat $ oversimplify l)
1279+
_ -> False
1280+
1281+
12611282
return []
12621283
runTests = $( [| $(forAllProperties) (quickCheckWithResult (stdArgs { maxSuccess = 1 }) ) |])

0 commit comments

Comments
 (0)