SC2114 about rm -rf /usr is no longer silenced by --
This commit is contained in:
parent
070a465b64
commit
ac3f0b3360
|
@ -141,7 +141,6 @@ nodeChecks = [
|
||||||
,checkWrongArithmeticAssignment
|
,checkWrongArithmeticAssignment
|
||||||
,checkConditionalAndOrs
|
,checkConditionalAndOrs
|
||||||
,checkFunctionDeclarations
|
,checkFunctionDeclarations
|
||||||
,checkCatastrophicRm
|
|
||||||
,checkStderrPipe
|
,checkStderrPipe
|
||||||
,checkOverridingPath
|
,checkOverridingPath
|
||||||
,checkArrayAsString
|
,checkArrayAsString
|
||||||
|
@ -2135,72 +2134,6 @@ checkFunctionDeclarations params
|
||||||
checkFunctionDeclarations _ _ = return ()
|
checkFunctionDeclarations _ _ = return ()
|
||||||
|
|
||||||
|
|
||||||
prop_checkCatastrophicRm1 = verify checkCatastrophicRm "rm -r $1/$2"
|
|
||||||
prop_checkCatastrophicRm2 = verify checkCatastrophicRm "rm -r /home/$foo"
|
|
||||||
prop_checkCatastrophicRm3 = verifyNot checkCatastrophicRm "rm -r /home/${USER:?}/*"
|
|
||||||
prop_checkCatastrophicRm4 = verify checkCatastrophicRm "rm -fr /home/$(whoami)/*"
|
|
||||||
prop_checkCatastrophicRm5 = verifyNot checkCatastrophicRm "rm -r /home/${USER:-thing}/*"
|
|
||||||
prop_checkCatastrophicRm6 = verify checkCatastrophicRm "rm --recursive /etc/*$config*"
|
|
||||||
prop_checkCatastrophicRm8 = verify checkCatastrophicRm "rm -rf /home"
|
|
||||||
prop_checkCatastrophicRm9 = verifyNot checkCatastrophicRm "rm -rf -- /home"
|
|
||||||
prop_checkCatastrophicRm10= verifyNot checkCatastrophicRm "rm -r \"${DIR}\"/{.gitignore,.gitattributes,ci}"
|
|
||||||
prop_checkCatastrophicRm11= verify checkCatastrophicRm "rm -r /{bin,sbin}/$exec"
|
|
||||||
prop_checkCatastrophicRm12= verify checkCatastrophicRm "rm -r /{{usr,},{bin,sbin}}/$exec"
|
|
||||||
prop_checkCatastrophicRm13= verifyNot checkCatastrophicRm "rm -r /{{a,b},{c,d}}/$exec"
|
|
||||||
prop_checkCatastrophicRmA = verify checkCatastrophicRm "rm -rf /usr /lib/nvidia-current/xorg/xorg"
|
|
||||||
prop_checkCatastrophicRmB = verify checkCatastrophicRm "rm -rf \"$STEAMROOT/\"*"
|
|
||||||
checkCatastrophicRm params t@(T_SimpleCommand id _ tokens) | t `isCommand` "rm" =
|
|
||||||
when (any isRecursiveFlag simpleArgs) $
|
|
||||||
mapM_ (mapM_ checkWord . braceExpand) tokens
|
|
||||||
where
|
|
||||||
simpleArgs = oversimplify t
|
|
||||||
|
|
||||||
checkWord token =
|
|
||||||
case getLiteralString token of
|
|
||||||
Just str ->
|
|
||||||
when (notElem "--" simpleArgs && (fixPath str `elem` importantPaths)) $
|
|
||||||
warn (getId token) 2114 "Warning: deletes a system directory. Use 'rm --' to disable this message."
|
|
||||||
Nothing ->
|
|
||||||
checkWord' token
|
|
||||||
|
|
||||||
checkWord' token = fromMaybe (return ()) $ do
|
|
||||||
filename <- getPotentialPath token
|
|
||||||
let path = fixPath filename
|
|
||||||
return . when (path `elem` importantPaths) $
|
|
||||||
warn (getId token) 2115 $ "Use \"${var:?}\" to ensure this never expands to " ++ path ++ " ."
|
|
||||||
|
|
||||||
fixPath filename =
|
|
||||||
let normalized = skipRepeating '/' . skipRepeating '*' $ filename in
|
|
||||||
if normalized == "/" then normalized else stripTrailing '/' normalized
|
|
||||||
|
|
||||||
getPotentialPath = getLiteralStringExt f
|
|
||||||
where
|
|
||||||
f (T_Glob _ str) = return str
|
|
||||||
f (T_DollarBraced _ word) =
|
|
||||||
let var = onlyLiteralString word in
|
|
||||||
if any (`isInfixOf` var) [":?", ":-", ":="]
|
|
||||||
then Nothing
|
|
||||||
else return ""
|
|
||||||
f _ = return ""
|
|
||||||
|
|
||||||
isRecursiveFlag "--recursive" = True
|
|
||||||
isRecursiveFlag ('-':'-':_) = False
|
|
||||||
isRecursiveFlag ('-':str) = 'r' `elem` str || 'R' `elem` str
|
|
||||||
isRecursiveFlag _ = False
|
|
||||||
|
|
||||||
stripTrailing c = reverse . dropWhile (== c) . reverse
|
|
||||||
skipRepeating c (a:b:rest) | a == b && b == c = skipRepeating c (b:rest)
|
|
||||||
skipRepeating c (a:r) = a:skipRepeating c r
|
|
||||||
skipRepeating _ [] = []
|
|
||||||
|
|
||||||
paths = [
|
|
||||||
"", "/bin", "/etc", "/home", "/mnt", "/usr", "/usr/share", "/usr/local",
|
|
||||||
"/var", "/lib"
|
|
||||||
]
|
|
||||||
importantPaths = filter (not . null) $
|
|
||||||
["", "/", "/*", "/*/*"] >>= (\x -> map (++x) paths)
|
|
||||||
checkCatastrophicRm _ _ = return ()
|
|
||||||
|
|
||||||
|
|
||||||
prop_checkStderrPipe1 = verify checkStderrPipe "#!/bin/ksh\nfoo |& bar"
|
prop_checkStderrPipe1 = verify checkStderrPipe "#!/bin/ksh\nfoo |& bar"
|
||||||
prop_checkStderrPipe2 = verifyNot checkStderrPipe "#!/bin/bash\nfoo |& bar"
|
prop_checkStderrPipe2 = verifyNot checkStderrPipe "#!/bin/bash\nfoo |& bar"
|
||||||
|
|
|
@ -86,6 +86,7 @@ commandChecks = [
|
||||||
,checkDeprecatedEgrep
|
,checkDeprecatedEgrep
|
||||||
,checkDeprecatedFgrep
|
,checkDeprecatedFgrep
|
||||||
,checkWhileGetoptsCase
|
,checkWhileGetoptsCase
|
||||||
|
,checkCatastrophicRm
|
||||||
]
|
]
|
||||||
|
|
||||||
buildCommandMap :: [CommandCheck] -> Map.Map CommandName (Token -> Analysis)
|
buildCommandMap :: [CommandCheck] -> Map.Map CommandName (Token -> Analysis)
|
||||||
|
@ -756,6 +757,65 @@ checkWhileGetoptsCase = CommandCheck (Exactly "getopts") f
|
||||||
T_Redirecting _ _ x@(T_CaseExpression {}) -> return x
|
T_Redirecting _ _ x@(T_CaseExpression {}) -> return x
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
|
prop_checkCatastrophicRm1 = verify checkCatastrophicRm "rm -r $1/$2"
|
||||||
|
prop_checkCatastrophicRm2 = verify checkCatastrophicRm "rm -r /home/$foo"
|
||||||
|
prop_checkCatastrophicRm3 = verifyNot checkCatastrophicRm "rm -r /home/${USER:?}/*"
|
||||||
|
prop_checkCatastrophicRm4 = verify checkCatastrophicRm "rm -fr /home/$(whoami)/*"
|
||||||
|
prop_checkCatastrophicRm5 = verifyNot checkCatastrophicRm "rm -r /home/${USER:-thing}/*"
|
||||||
|
prop_checkCatastrophicRm6 = verify checkCatastrophicRm "rm --recursive /etc/*$config*"
|
||||||
|
prop_checkCatastrophicRm8 = verify checkCatastrophicRm "rm -rf /home"
|
||||||
|
prop_checkCatastrophicRm10= verifyNot checkCatastrophicRm "rm -r \"${DIR}\"/{.gitignore,.gitattributes,ci}"
|
||||||
|
prop_checkCatastrophicRm11= verify checkCatastrophicRm "rm -r /{bin,sbin}/$exec"
|
||||||
|
prop_checkCatastrophicRm12= verify checkCatastrophicRm "rm -r /{{usr,},{bin,sbin}}/$exec"
|
||||||
|
prop_checkCatastrophicRm13= verifyNot checkCatastrophicRm "rm -r /{{a,b},{c,d}}/$exec"
|
||||||
|
prop_checkCatastrophicRmA = verify checkCatastrophicRm "rm -rf /usr /lib/nvidia-current/xorg/xorg"
|
||||||
|
prop_checkCatastrophicRmB = verify checkCatastrophicRm "rm -rf \"$STEAMROOT/\"*"
|
||||||
|
checkCatastrophicRm = CommandCheck (Basename "rm") $ \t ->
|
||||||
|
when (isRecursive t) $
|
||||||
|
mapM_ (mapM_ checkWord . braceExpand) $ arguments t
|
||||||
|
where
|
||||||
|
isRecursive = any (`elem` ["r", "R", "recursive"]) . map snd . getAllFlags
|
||||||
|
|
||||||
|
checkWord token =
|
||||||
|
case getLiteralString token of
|
||||||
|
Just str ->
|
||||||
|
when (fixPath str `elem` importantPaths) $
|
||||||
|
warn (getId token) 2114 "Warning: deletes a system directory."
|
||||||
|
Nothing ->
|
||||||
|
checkWord' token
|
||||||
|
|
||||||
|
checkWord' token = fromMaybe (return ()) $ do
|
||||||
|
filename <- getPotentialPath token
|
||||||
|
let path = fixPath filename
|
||||||
|
return . when (path `elem` importantPaths) $
|
||||||
|
warn (getId token) 2115 $ "Use \"${var:?}\" to ensure this never expands to " ++ path ++ " ."
|
||||||
|
|
||||||
|
fixPath filename =
|
||||||
|
let normalized = skipRepeating '/' . skipRepeating '*' $ filename in
|
||||||
|
if normalized == "/" then normalized else stripTrailing '/' normalized
|
||||||
|
|
||||||
|
getPotentialPath = getLiteralStringExt f
|
||||||
|
where
|
||||||
|
f (T_Glob _ str) = return str
|
||||||
|
f (T_DollarBraced _ word) =
|
||||||
|
let var = onlyLiteralString word in
|
||||||
|
-- This shouldn't handle non-colon cases.
|
||||||
|
if any (`isInfixOf` var) [":?", ":-", ":="]
|
||||||
|
then Nothing
|
||||||
|
else return ""
|
||||||
|
f _ = return ""
|
||||||
|
|
||||||
|
stripTrailing c = reverse . dropWhile (== c) . reverse
|
||||||
|
skipRepeating c (a:b:rest) | a == b && b == c = skipRepeating c (b:rest)
|
||||||
|
skipRepeating c (a:r) = a:skipRepeating c r
|
||||||
|
skipRepeating _ [] = []
|
||||||
|
|
||||||
|
paths = [
|
||||||
|
"", "/bin", "/etc", "/home", "/mnt", "/usr", "/usr/share", "/usr/local",
|
||||||
|
"/var", "/lib", "/dev", "/media", "/boot", "/lib64", "/usr/bin"
|
||||||
|
]
|
||||||
|
importantPaths = filter (not . null) $
|
||||||
|
["", "/", "/*", "/*/*"] >>= (\x -> map (++x) paths)
|
||||||
|
|
||||||
return []
|
return []
|
||||||
runTests = $( [| $(forAllProperties) (quickCheckWithResult (stdArgs { maxSuccess = 1 }) ) |])
|
runTests = $( [| $(forAllProperties) (quickCheckWithResult (stdArgs { maxSuccess = 1 }) ) |])
|
||||||
|
|
Loading…
Reference in New Issue