From a839a6657be04629fdc2bcd8a66e471e5f3807a8 Mon Sep 17 00:00:00 2001 From: Vidar Holen Date: Mon, 3 Jul 2017 12:06:59 -0700 Subject: [PATCH] Warn when commands start with dashes (#938) --- ShellCheck/ASTLib.hs | 12 ++++++++++++ ShellCheck/Analytics.hs | 18 ++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/ShellCheck/ASTLib.hs b/ShellCheck/ASTLib.hs index 702a98b..c883fd6 100644 --- a/ShellCheck/ASTLib.hs +++ b/ShellCheck/ASTLib.hs @@ -125,6 +125,11 @@ isFlag token = T_Literal _ ('-':_) : _ -> True _ -> False +-- Is this token a flag where the - is unquoted? +isUnquotedFlag token = fromMaybe False $ do + str <- getLeadingUnquotedString token + return $ "-" `isPrefixOf` str + -- Given a T_DollarBraced, return a simplified version of the string contents. bracedString (T_DollarBraced _ l) = concat $ oversimplify l bracedString _ = error "Internal shellcheck error, please report! (bracedString on non-variable)" @@ -194,6 +199,13 @@ getTrailingUnquotedLiteral t = T_Literal {} -> return t _ -> Nothing +-- Get the leading, unquoted, literal string of a token (if any). +getLeadingUnquotedString :: Token -> Maybe String +getLeadingUnquotedString t = + case t of + T_NormalWord _ ((T_Literal _ s) : _) -> return s + _ -> Nothing + -- Maybe get the literal string of this token and any globs in it. getGlobOrLiteralString = getLiteralStringExt f where diff --git a/ShellCheck/Analytics.hs b/ShellCheck/Analytics.hs index 67abb7b..dddd417 100644 --- a/ShellCheck/Analytics.hs +++ b/ShellCheck/Analytics.hs @@ -162,6 +162,7 @@ nodeChecks = [ ,checkSplittingInArrays ,checkRedirectionToNumber ,checkGlobAsCommand + ,checkFlagAsCommand ,checkEmptyCondition ] @@ -275,10 +276,7 @@ checkAssignAteCommand _ (T_SimpleCommand id (T_Assignment _ _ _ _ assignmentTerm isCommonCommand _ = False firstWordIsArg list = fromMaybe False $ do head <- list !!! 0 - return . or $ mapMaybe ($ head) [return . isGlob, isFlag] - isFlag word = do - first <- (concat $ oversimplify word) !!! 0 - return $ first == '-' + return $ isGlob head || isUnquotedFlag head checkAssignAteCommand _ _ = return () @@ -2770,6 +2768,18 @@ checkGlobAsCommand _ t = case t of warn (getId first) 2211 "This is a glob used as a command name. Was it supposed to be in ${..}, array, or is it missing quoting?" _ -> return () + +prop_checkFlagAsCommand1 = verify checkFlagAsCommand "-e file" +prop_checkFlagAsCommand2 = verify checkFlagAsCommand "foo\n --bar=baz" +prop_checkFlagAsCommand3 = verifyNot checkFlagAsCommand "'--myexec--' args" +prop_checkFlagAsCommand4 = verifyNot checkFlagAsCommand "var=cmd --arg" -- Handled by SC2037 +checkFlagAsCommand _ t = case t of + T_SimpleCommand _ [] (first:_) -> + when (isUnquotedFlag first) $ + warn (getId first) 2215 "This flag is used as a command name. Bad line break or missing [ .. ]?" + _ -> return () + + prop_checkEmptyCondition1 = verify checkEmptyCondition "if [ ]; then ..; fi" prop_checkEmptyCondition2 = verifyNot checkEmptyCondition "[ foo -o bar ]" checkEmptyCondition _ t = case t of