Added check for bashisms with #!/bin/sh
This commit is contained in:
parent
1a4301ea98
commit
55a4c3c44f
|
@ -23,7 +23,7 @@ import qualified Text.Regex as Re
|
||||||
|
|
||||||
data Id = Id Int deriving (Show, Eq, Ord)
|
data Id = Id Int deriving (Show, Eq, Ord)
|
||||||
|
|
||||||
data Token = T_AND_IF Id | T_OR_IF Id | T_DSEMI Id | T_Semi Id | T_DLESS Id | T_DGREAT Id | T_LESSAND Id | T_GREATAND Id | T_LESSGREAT Id | T_DLESSDASH Id | T_CLOBBER Id | T_If Id | T_Then Id | T_Else Id | T_Elif Id | T_Fi Id | T_Do Id | T_Done Id | T_Case Id | T_Esac Id | T_While Id | T_Until Id | T_For Id | T_Lbrace Id | T_Rbrace Id | T_Lparen Id | T_Rparen Id | T_Bang Id | T_In Id | T_NEWLINE Id | T_EOF Id | T_Less Id | T_Greater Id | T_SingleQuoted Id String | T_Literal Id String | T_NormalWord Id [Token] | T_DoubleQuoted Id [Token] | T_DollarExpansion Id [Token] | T_DollarBraced Id Token | T_DollarArithmetic Id Token | T_BraceExpansion Id String | T_IoFile Id Token Token | T_HereDoc Id Bool Bool String | T_HereString Id Token | T_FdRedirect Id String Token | T_Assignment Id String Token | T_Array Id [Token] | T_Redirecting Id [Token] Token | T_SimpleCommand Id [Token] [Token] | T_Pipeline Id [Token] | T_Banged Id Token | T_AndIf Id (Token) (Token) | T_OrIf Id (Token) (Token) | T_Backgrounded Id Token | T_IfExpression Id [([Token],[Token])] [Token] | T_Subshell Id [Token] | T_BraceGroup Id [Token] | T_WhileExpression Id [Token] [Token] | T_UntilExpression Id [Token] [Token] | T_ForIn Id String [Token] [Token] | T_CaseExpression Id Token [([Token],[Token])] | T_Function Id String Token | T_Arithmetic Id Token | T_Script Id String [Token] | T_Condition Id ConditionType Token | T_Extglob Id String [Token] | TC_And Id ConditionType String Token Token | TC_Or Id ConditionType String Token Token | TC_Group Id ConditionType Token | TC_Binary Id ConditionType String Token Token | TC_Unary Id ConditionType String Token | TC_Noary Id ConditionType Token | TA_Binary Id String Token Token | TA_Unary Id String Token | TA_Sequence Id [Token] | TA_Variable Id String | TA_Trinary Id Token Token Token | TA_Expansion Id Token | TA_Literal Id String | T_Backticked Id String | T_ProcSub Id String [Token] | T_Glob Id String | T_ForArithmetic Id Token Token Token [Token]
|
data Token = T_AND_IF Id | T_OR_IF Id | T_DSEMI Id | T_Semi Id | T_DLESS Id | T_DGREAT Id | T_LESSAND Id | T_GREATAND Id | T_LESSGREAT Id | T_DLESSDASH Id | T_CLOBBER Id | T_If Id | T_Then Id | T_Else Id | T_Elif Id | T_Fi Id | T_Do Id | T_Done Id | T_Case Id | T_Esac Id | T_While Id | T_Until Id | T_For Id | T_Lbrace Id | T_Rbrace Id | T_Lparen Id | T_Rparen Id | T_Bang Id | T_In Id | T_NEWLINE Id | T_EOF Id | T_Less Id | T_Greater Id | T_SingleQuoted Id String | T_Literal Id String | T_NormalWord Id [Token] | T_DoubleQuoted Id [Token] | T_DollarExpansion Id [Token] | T_DollarBraced Id Token | T_DollarArithmetic Id Token | T_BraceExpansion Id String | T_IoFile Id Token Token | T_HereDoc Id Bool Bool String | T_HereString Id Token | T_FdRedirect Id String Token | T_Assignment Id String Token | T_Array Id [Token] | T_Redirecting Id [Token] Token | T_SimpleCommand Id [Token] [Token] | T_Pipeline Id [Token] | T_Banged Id Token | T_AndIf Id (Token) (Token) | T_OrIf Id (Token) (Token) | T_Backgrounded Id Token | T_IfExpression Id [([Token],[Token])] [Token] | T_Subshell Id [Token] | T_BraceGroup Id [Token] | T_WhileExpression Id [Token] [Token] | T_UntilExpression Id [Token] [Token] | T_ForIn Id String [Token] [Token] | T_CaseExpression Id Token [([Token],[Token])] | T_Function Id String Token | T_Arithmetic Id Token | T_Script Id String [Token] | T_Condition Id ConditionType Token | T_Extglob Id String [Token] | TC_And Id ConditionType String Token Token | TC_Or Id ConditionType String Token Token | TC_Group Id ConditionType Token | TC_Binary Id ConditionType String Token Token | TC_Unary Id ConditionType String Token | TC_Noary Id ConditionType Token | TA_Binary Id String Token Token | TA_Unary Id String Token | TA_Sequence Id [Token] | TA_Variable Id String | TA_Trinary Id Token Token Token | TA_Expansion Id Token | TA_Literal Id String | T_Backticked Id String | T_ProcSub Id String [Token] | T_Glob Id String | T_ForArithmetic Id Token Token Token [Token] | T_DollarSingleQuoted Id String | T_DollarDoubleQuoted Id [Token]
|
||||||
|
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ analyze f g i t =
|
||||||
|
|
||||||
delve (T_NormalWord id list) = dl list $ T_NormalWord id
|
delve (T_NormalWord id list) = dl list $ T_NormalWord id
|
||||||
delve (T_DoubleQuoted id list) = dl list $ T_DoubleQuoted id
|
delve (T_DoubleQuoted id list) = dl list $ T_DoubleQuoted id
|
||||||
|
delve (T_DollarDoubleQuoted id list) = dl list $ T_DollarDoubleQuoted id
|
||||||
delve (T_DollarExpansion id list) = dl list $ T_DollarExpansion id
|
delve (T_DollarExpansion id list) = dl list $ T_DollarExpansion id
|
||||||
delve (T_DollarArithmetic id c) = d1 c $ T_DollarArithmetic id
|
delve (T_DollarArithmetic id c) = d1 c $ T_DollarArithmetic id
|
||||||
delve (T_IoFile id op file) = d2 op file $ T_IoFile id
|
delve (T_IoFile id op file) = d2 op file $ T_IoFile id
|
||||||
|
@ -219,6 +220,8 @@ getId t = case t of
|
||||||
T_ProcSub id _ _ -> id
|
T_ProcSub id _ _ -> id
|
||||||
T_Glob id _ -> id
|
T_Glob id _ -> id
|
||||||
T_ForArithmetic id _ _ _ _ -> id
|
T_ForArithmetic id _ _ _ _ -> id
|
||||||
|
T_DollarSingleQuoted id _ -> id
|
||||||
|
T_DollarDoubleQuoted id _ -> id
|
||||||
|
|
||||||
blank :: Monad m => Token -> m ()
|
blank :: Monad m => Token -> m ()
|
||||||
blank = const $ return ()
|
blank = const $ return ()
|
||||||
|
|
|
@ -33,7 +33,7 @@ checks = concat [
|
||||||
,[subshellAssignmentCheck]
|
,[subshellAssignmentCheck]
|
||||||
,[checkSpacefulness]
|
,[checkSpacefulness]
|
||||||
,[checkUnquotedExpansions]
|
,[checkUnquotedExpansions]
|
||||||
,[checkShebang]
|
,[checkShebang, checkUndeclaredBash]
|
||||||
]
|
]
|
||||||
|
|
||||||
runAllAnalytics = checkList checks
|
runAllAnalytics = checkList checks
|
||||||
|
@ -232,6 +232,24 @@ checkShebang (T_Script id sb _) m =
|
||||||
in Map.adjust (\(Metadata pos notes) -> Metadata pos (note:notes)) id m
|
in Map.adjust (\(Metadata pos notes) -> Metadata pos (note:notes)) id m
|
||||||
else m
|
else m
|
||||||
|
|
||||||
|
prop_checkUndeclaredBash = verifyFull checkUndeclaredBash "#!/bin/sh -l\nwhile read a; do :; done < <(a)"
|
||||||
|
prop_checkUndeclaredBash2 = verifyNotFull checkUndeclaredBash "#!/bin/bash\nwhile read a; do :; done < <(a)"
|
||||||
|
checkUndeclaredBash t@(T_Script id sb _) m =
|
||||||
|
let tokens = words sb
|
||||||
|
in if (not $ null tokens) && "/sh" `isSuffixOf` (head tokens)
|
||||||
|
then runBasicAnalysis bashism t m
|
||||||
|
else m
|
||||||
|
where
|
||||||
|
errMsg id s = err id $ "The shebang specifies sh, so " ++ s ++ " is not supported, even if sh is bash."
|
||||||
|
warnMsg id s = warn id $ "The shebang specifies sh, so " ++ s ++ " may not be supported."
|
||||||
|
bashism (T_ProcSub id _ _) = errMsg id "process substitution"
|
||||||
|
bashism (T_Extglob id _ _) = warnMsg id "extglob"
|
||||||
|
bashism (T_DollarSingleQuoted id _) = warnMsg id "$'..'"
|
||||||
|
bashism (T_DollarDoubleQuoted id _) = warnMsg id "$\"..\""
|
||||||
|
bashism (T_ForArithmetic id _ _ _ _) = warnMsg id "arithmetic for loops"
|
||||||
|
bashism (T_Arithmetic id _) = warnMsg id "((..))"
|
||||||
|
bashism _ = return()
|
||||||
|
|
||||||
prop_checkForInQuoted = verify checkForInQuoted "for f in \"$(ls)\"; do echo foo; done"
|
prop_checkForInQuoted = verify checkForInQuoted "for f in \"$(ls)\"; do echo foo; done"
|
||||||
prop_checkForInQuoted2 = verifyNot checkForInQuoted "for f in \"$@\"; do echo foo; done"
|
prop_checkForInQuoted2 = verifyNot checkForInQuoted "for f in \"$@\"; do echo foo; done"
|
||||||
prop_checkForInQuoted3 = verify checkForInQuoted "for f in 'find /'; do true; done"
|
prop_checkForInQuoted3 = verify checkForInQuoted "for f in 'find /'; do true; done"
|
||||||
|
@ -543,6 +561,7 @@ getLiteralString t = g t
|
||||||
where
|
where
|
||||||
allInList l = let foo = map g l in if all isJust foo then return $ concat (catMaybes foo) else Nothing
|
allInList l = let foo = map g l in if all isJust foo then return $ concat (catMaybes foo) else Nothing
|
||||||
g s@(T_DoubleQuoted _ l) = allInList l
|
g s@(T_DoubleQuoted _ l) = allInList l
|
||||||
|
g s@(T_DollarDoubleQuoted _ l) = allInList l
|
||||||
g s@(T_NormalWord _ l) = allInList l
|
g s@(T_NormalWord _ l) = allInList l
|
||||||
g (T_SingleQuoted _ s) = return s
|
g (T_SingleQuoted _ s) = return s
|
||||||
g (T_Literal _ s) = return s
|
g (T_Literal _ s) = return s
|
||||||
|
|
|
@ -713,7 +713,7 @@ readBraced = try $ do
|
||||||
char '}'
|
char '}'
|
||||||
return $ T_BraceExpansion id $ concat str
|
return $ T_BraceExpansion id $ concat str
|
||||||
|
|
||||||
readDollar = readDollarArithmetic <|> readDollarBraced <|> readDollarExpansion <|> readDollarVariable <|> readDollarSingleQuote <|> readDollarLonely
|
readDollar = readDollarArithmetic <|> readDollarBraced <|> readDollarExpansion <|> readDollarVariable <|> readDollarSingleQuote <|> readDollarDoubleQuote <|> readDollarLonely
|
||||||
|
|
||||||
prop_readDollarSingleQuote = isOk readDollarSingleQuote "$'foo\\\'lol'"
|
prop_readDollarSingleQuote = isOk readDollarSingleQuote "$'foo\\\'lol'"
|
||||||
readDollarSingleQuote = called "$'..' expression" $ do
|
readDollarSingleQuote = called "$'..' expression" $ do
|
||||||
|
@ -721,7 +721,18 @@ readDollarSingleQuote = called "$'..' expression" $ do
|
||||||
try $ string "$'"
|
try $ string "$'"
|
||||||
str <- readGenericLiteral (char '\'')
|
str <- readGenericLiteral (char '\'')
|
||||||
char '\''
|
char '\''
|
||||||
return $ T_Literal id str
|
return $ T_DollarSingleQuoted id str
|
||||||
|
|
||||||
|
prop_readDollarDoubleQuote = isOk readDollarDoubleQuote "$\"hello\""
|
||||||
|
readDollarDoubleQuote = do
|
||||||
|
lookAhead . try $ string "$\""
|
||||||
|
id <- getNextId
|
||||||
|
char '$'
|
||||||
|
doubleQuote
|
||||||
|
x <- many doubleQuotedPart
|
||||||
|
doubleQuote <?> "end of translated double quoted string"
|
||||||
|
return $ T_DollarDoubleQuoted id x
|
||||||
|
|
||||||
|
|
||||||
prop_readDollarArithmetic = isOk readDollarArithmetic "$(( 3 * 4 +5))"
|
prop_readDollarArithmetic = isOk readDollarArithmetic "$(( 3 * 4 +5))"
|
||||||
prop_readDollarArithmetic2 = isOk readDollarArithmetic "$(((3*4)+(1*2+(3-1))))"
|
prop_readDollarArithmetic2 = isOk readDollarArithmetic "$(((3*4)+(1*2+(3-1))))"
|
||||||
|
|
Loading…
Reference in New Issue