From c4181d45d223984b93c6c7da9b63cc4a701530d5 Mon Sep 17 00:00:00 2001 From: Vidar Holen Date: Sat, 10 May 2014 15:37:02 -0700 Subject: [PATCH] Warn about suspicious IFS, such as IFS="\n" --- ShellCheck/Analytics.hs | 20 ++++++++++++++++++++ ShellCheck/Parser.hs | 4 +++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/ShellCheck/Analytics.hs b/ShellCheck/Analytics.hs index 53ca975..2ea2e04 100644 --- a/ShellCheck/Analytics.hs +++ b/ShellCheck/Analytics.hs @@ -197,6 +197,7 @@ nodeChecks = [ ,checkUnsupported ,checkMultipleAppends ,checkAliasesExpandEarly + ,checkSuspiciousIFS ] @@ -2723,3 +2724,22 @@ checkAliasesExpandEarly params = flip mapM_ (take 1 $ filter (not . isLiteral) $ getWordParts arg) $ \x -> warn (getId x) 2139 "This expands when defined, not when used. Consider escaping." checkArg _ = return () + +prop_checkSuspiciousIFS1 = verify checkSuspiciousIFS "IFS=\"\\n\"" +prop_checkSuspiciousIFS2 = verifyNot checkSuspiciousIFS "IFS=$'\\t'" +checkSuspiciousIFS params (T_Assignment id Assign "IFS" Nothing value) = + potentially $ do + str <- getLiteralString value + return $ check str + where + n = if (shellType params == Sh) then "''" else "$'\\n'" + t = if (shellType params == Sh) then "\"$(printf '\\t')\"" else "$'\\t'" + check value = + case value of + "\\n" -> suggest n + "/n" -> suggest n + "\\t" -> suggest t + "/t" -> suggest t + _ -> return () + suggest r = warn id 2141 $ "Did you mean IFS=" ++ r ++ " ?" +checkSuspiciousIFS _ _ = return () diff --git a/ShellCheck/Parser.hs b/ShellCheck/Parser.hs index 6db8813..592380b 100644 --- a/ShellCheck/Parser.hs +++ b/ShellCheck/Parser.hs @@ -965,10 +965,12 @@ readNormalEscaped = called "escaped char" $ do do next <- anyChar case escapedChar next of - Just name -> parseNoteAt pos WarningC 1012 $ "\\" ++ [next] ++ " is just literal '" ++ [next] ++ "' here. For " ++ name ++ ", use \"$(printf \"\\" ++ [next] ++ "\")\"." + Just name -> parseNoteAt pos WarningC 1012 $ "\\" ++ [next] ++ " is just literal '" ++ [next] ++ "' here. For " ++ name ++ ", use " ++ (alternative next) ++ " instead." Nothing -> parseNoteAt pos InfoC 1001 $ "This \\" ++ [next] ++ " will be a regular '" ++ [next] ++ "' in this context." return [next] where + alternative 'n' = "a quoted, literal line feed" + alternative t = "\"$(printf \"\\" ++ [t] ++ "\")\"" escapedChar 'n' = Just "line feed" escapedChar 't' = Just "tab" escapedChar 'r' = Just "carriage return"