diff --git a/src/ShellCheck/Analytics.hs b/src/ShellCheck/Analytics.hs index a4e2186a4..de1665268 100644 --- a/src/ShellCheck/Analytics.hs +++ b/src/ShellCheck/Analytics.hs @@ -2625,8 +2625,10 @@ prop_checkGlobsAsOptions3 = verifyNot checkGlobsAsOptions "rm -- *.txt" prop_checkGlobsAsOptions4 = verifyNot checkGlobsAsOptions "*.txt" prop_checkGlobsAsOptions5 = verifyNot checkGlobsAsOptions "echo 'Files:' *.txt" prop_checkGlobsAsOptions6 = verifyNot checkGlobsAsOptions "printf '%s\\n' *" -checkGlobsAsOptions _ cmd@(T_SimpleCommand _ _ args) = - unless ((fromMaybe "" $ getCommandBasename cmd) `elem` ["echo", "printf"]) $ +prop_checkGlobsAsOptions7 = verifyNot checkGlobsAsOptions "set -f; ls *" +prop_checkGlobsAsOptions8 = verifyNot checkGlobsAsOptions "set -o noglob\nrm *" +checkGlobsAsOptions params cmd@(T_SimpleCommand _ _ args) = + unless (((fromMaybe "" $ getCommandBasename cmd) `elem` ["echo", "printf"]) || hasSetF params) $ mapM_ check $ takeWhile (not . isEndOfArgs) (drop 1 args) where check v@(T_NormalWord _ (T_Glob id s:_)) | s == "*" || s == "?" = diff --git a/src/ShellCheck/AnalyzerLib.hs b/src/ShellCheck/AnalyzerLib.hs index 71defa0ca..4d6580555 100644 --- a/src/ShellCheck/AnalyzerLib.hs +++ b/src/ShellCheck/AnalyzerLib.hs @@ -87,6 +87,8 @@ data Parameters = Parameters { hasInheritErrexit :: Bool, -- Whether this script has 'set -e' anywhere. hasSetE :: Bool, + -- Whether this script has 'set -f' anywhere. + hasSetF :: Bool, -- Whether this script has 'set -o pipefail' anywhere. hasPipefail :: Bool, -- Whether this script has 'shopt -s execfail' anywhere. @@ -207,6 +209,7 @@ makeParameters spec = params rootNode = root, shellType = fromMaybe (determineShell (asFallbackShell spec) root) $ asShellType spec, hasSetE = containsSetE root, + hasSetF = containsSetF root, hasLastpipe = case shellType params of Bash -> isOptionSet "lastpipe" root @@ -262,6 +265,17 @@ containsSetE root = isNothing $ doAnalysis (guard . not . isSetE) root _ -> False re = mkRegex "[[:space:]]-[^-]*e" +containsSetF root = isNothing $ doAnalysis (guard . not . isSetF) root + where + isSetF t = + case t of + T_Script _ (T_Literal _ str) _ -> str `matches` re + T_SimpleCommand {} -> + t `isUnqualifiedCommand` "set" && + ("noglob" `elem` oversimplify t || + "f" `elem` map snd (getAllFlags t)) + _ -> False + re = mkRegex "[[:space:]]-[^-]*f" containsSetOption opt root = isNothing $ doAnalysis (guard . not . isPipefail) root where