Fixed incorrect n=1 & n=foo$n and same for $((n++))

This commit is contained in:
Vidar Holen 2012-11-15 23:23:08 -08:00
parent 5d26f627cf
commit ad9db04856
4 changed files with 71 additions and 44 deletions

View File

@ -35,6 +35,8 @@ basicChecks = [
,checkNumberComparisons
,checkNoaryWasBinary
,checkBraceExpansionVars
,checkForDecimals
,checkDivBeforeMult
]
modifyMap = modify
@ -239,6 +241,17 @@ checkBraceExpansionVars (T_BraceExpansion id s) | '$' `elem` s =
addNoteFor id $ Note WarningC $ "You can't use variables in brace expansions."
checkBraceExpansionVars _ = return ()
prop_checkForDecimals = verify checkForDecimals "((3.14*c))"
checkForDecimals (TA_Literal id s) | any (== '.') s = do
addNoteFor id $ Note ErrorC $ "(( )) doesn't support decimals. Use bc or awk."
checkForDecimals _ = return ()
prop_checkDivBeforeMult = verify checkDivBeforeMult "echo $((c/n*100))"
prop_checkDivBeforeMult2 = verifyNot checkDivBeforeMult "echo $((c*100/n))"
checkDivBeforeMult (TA_Binary _ "*" (TA_Binary id "/" _ _) _) = do
addNoteFor id $ Note InfoC $ "Increase precision by replacing a/b*c with a*c/b"
checkDivBeforeMult _ = return ()
allModifiedVariables t = snd $ runState (doAnalysis (\x -> modify $ (++) (getModifiedVariables x)) t) []
--- Subshell detection
@ -249,6 +262,10 @@ prop_subshellAssignmentCheck3 = verifyFull subshellAssignmentCheck "( A=foo;
prop_subshellAssignmentCheck4 = verifyNotFull subshellAssignmentCheck "( A=foo; rm $A; )"
prop_subshellAssignmentCheck5 = verifyFull subshellAssignmentCheck "cat foo | while read cow; do true; done; echo $cow;"
prop_subshellAssignmentCheck6 = verifyFull subshellAssignmentCheck "( export lol=$(ls); ); echo $lol;"
prop_subshellAssignmentCheck7 = verifyFull subshellAssignmentCheck "cmd | while read foo; do (( n++ )); done; echo \"$n lines\""
prop_subshellAssignmentCheck8 = verifyFull subshellAssignmentCheck "n=3 & echo $((n++))"
prop_subshellAssignmentCheck9 = verifyFull subshellAssignmentCheck "read n & n=foo$n"
prop_subshellAssignmentCheck10 = verifyFull subshellAssignmentCheck "(( n <<= 3 )) & (( n |= 4 )) &"
subshellAssignmentCheck t map =
let flow = getVariableFlow t
check = findSubshelled flow [("oops",[])] Map.empty
@ -279,6 +296,12 @@ getModifiedVariables t =
c@(T_SimpleCommand _ _ _) ->
getModifiedVariableCommand c
TA_Unary _ "++|" (TA_Variable id name) -> [(id, name)]
TA_Unary _ "|++" (TA_Variable id name) -> [(id, name)]
TA_Binary _ op (TA_Variable id name) _ -> if any (==op) ["=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|="]
then [(id,name)]
else []
--Points to 'for' rather than variable
T_ForIn id str _ _ -> [(id, str)]
_ -> []
@ -305,23 +328,23 @@ getBracedReference s = takeWhile (\x -> not $ x `elem` ":[#%/^,") $ dropWhile (=
getReferencedVariables t =
case t of
T_DollarBraced id str -> map (\x -> (id, x)) $ [getBracedReference str]
T_Arithmetic _ _ -> [] -- TODO
_ -> []
TA_Variable id str -> [(id,str)]
x -> []
startScope t =
let scopeType = leadType t
written = getModifiedVariables t
read = getReferencedVariables t
in do
when (scopeType /= NoneScope) $ modify ((StackScope scopeType):)
mapM_ (\v -> modify ((Assignment v):)) written
mapM_ (\v -> modify ((Reference v):)) read
endScope t =
let scopeType = leadType t
written = getModifiedVariables t
read = getReferencedVariables t
in do
when (scopeType /= NoneScope) $ modify ((StackScopeEnd):)
mapM_ (\v -> modify ((Reference v):)) read
mapM_ (\v -> modify ((Assignment v):)) written
getVariableFlow t =
let (_, stack) = runState (doStackAnalysis startScope endScope t) []

View File

@ -459,6 +459,7 @@ analyze f g i t =
delve (T_NormalWord id list) = dl list $ T_NormalWord id
delve (T_DoubleQuoted id list) = dl list $ T_DoubleQuoted id
delve (T_DollarExpansion id list) = dl list $ T_DollarExpansion 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_HereString id word) = d1 word $ T_HereString id
delve (T_FdRedirect id v t) = d1 t $ T_FdRedirect id v
@ -475,6 +476,7 @@ analyze f g i t =
delve (T_OrIf id t u) = d2 t u $ T_OrIf id
delve (T_Backgrounded id l) = d1 l $ T_Backgrounded id
delve (T_Subshell id l) = dl l $ T_Subshell id
delve (T_Arithmetic id c) = d1 c $ T_Arithmetic id
delve (T_IfExpression id conditions elses) = do
newConds <- mapM (\(c, t) -> do
x <- mapM round c
@ -518,7 +520,6 @@ analyze f g i t =
delve (TA_Expansion id t) = d1 t $ TA_Expansion id
delve t = return t
blank = const $ return ()
doAnalysis f t = analyze f blank id t
doStackAnalysis startToken endToken t = analyze startToken endToken id t
@ -1279,3 +1280,4 @@ parseShell filename contents = do
(Right (script, map, notes), parsenotes) -> ParseResult (Just (script, map)) (nub $ sortNotes $ notes ++ parsenotes)
(Left err, p) -> ParseResult Nothing (nub $ sortNotes $ p ++ ([makeErrorFor err]))
lt x = trace (show x) x

View File

@ -19,7 +19,6 @@ shellCheck script =
data ShellCheckComment = ShellCheckComment { scLine :: Int, scColumn :: Int, scSeverity :: String, scMessage :: String }
instance Show ShellCheckComment where
show c = concat ["(", show $ scLine c, ",", show $ scColumn c, ") ", scSeverity c, ": ", scMessage c]

3
badcase/subshellvar4 Normal file
View File

@ -0,0 +1,3 @@
n=0;
mycmd | while read foo; do rm "$foo"; ((n++)); done
echo "Deleted $n files"