From 210cdcd01a91923a7e1d04b4392616460ec5be68 Mon Sep 17 00:00:00 2001 From: Vidar Holen Date: Sun, 28 Jun 2020 17:24:07 -0700 Subject: [PATCH] Treat $x/ or $(x)/ as ./ when finding sourced files (fixes #1998) --- CHANGELOG.md | 3 +++ src/ShellCheck/ASTLib.hs | 5 +++++ src/ShellCheck/Checker.hs | 6 ++++++ src/ShellCheck/Parser.hs | 12 +++++++++++- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index deacf5b..fde8b0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ - SC1072/SC1073 now respond to disable annotations, though ignoring parse errors is still purely cosmetic and does not allow ShellCheck to continue. +### Changed +- SC1090: A leading `$x/` or `$(x)/` is now treated as `./` when locating files + ## v0.7.1 - 2020-04-04 ### Fixed diff --git a/src/ShellCheck/ASTLib.hs b/src/ShellCheck/ASTLib.hs index 4fdf078..29ce27f 100644 --- a/src/ShellCheck/ASTLib.hs +++ b/src/ShellCheck/ASTLib.hs @@ -503,6 +503,11 @@ isCommandSubstitution t = case t of T_Backticked {} -> True _ -> False +-- Is this an expansion that results in a simple string? +isStringExpansion t = isCommandSubstitution t || case t of + T_DollarArithmetic {} -> True + T_DollarBraced {} -> not (isArrayExpansion t) + _ -> False -- Is this a T_Annotation that ignores a specific code? isAnnotationIgnoringCode code t = diff --git a/src/ShellCheck/Checker.hs b/src/ShellCheck/Checker.hs index f639ab3..673a116 100644 --- a/src/ShellCheck/Checker.hs +++ b/src/ShellCheck/Checker.hs @@ -229,6 +229,12 @@ prop_cantSourceDynamic = prop_cantSourceDynamic2 = [1090] == checkWithIncludes [("lib", "")] "source ~/foo" +prop_canStripPrefixAndSource = + null $ checkWithIncludes [("./lib", "")] "source \"$MYDIR/lib\"" + +prop_canStripPrefixAndSource2 = + null $ checkWithIncludes [("./utils.sh", "")] "source \"$(dirname \"${BASH_SOURCE[0]}\")/utils.sh\"" + prop_canSourceDynamicWhenRedirected = null $ checkWithIncludes [("lib", "")] "#shellcheck source=lib\n. \"$1\"" diff --git a/src/ShellCheck/Parser.hs b/src/ShellCheck/Parser.hs index 359fabd..bb27ea3 100644 --- a/src/ShellCheck/Parser.hs +++ b/src/ShellCheck/Parser.hs @@ -2122,7 +2122,7 @@ readSource t@(T_Redirecting _ _ (T_SimpleCommand cmdId _ (cmd:file':rest'))) = d let file = getFile file' rest' override <- getSourceOverride let literalFile = do - name <- override `mplus` getLiteralString file + name <- override `mplus` getLiteralString file `mplus` stripDynamicPrefix file -- Hack to avoid 'source ~/foo' trying to read from literal tilde guard . not $ "~/" `isPrefixOf` name return name @@ -2182,6 +2182,16 @@ readSource t@(T_Redirecting _ _ (T_SimpleCommand cmdId _ (cmd:file':rest'))) = d SourcePath x -> Just x _ -> Nothing + -- If the word has a single expansion as the directory, try stripping it + -- This affects `$foo/bar` but not `${foo}-dir/bar` or `/foo/$file` + stripDynamicPrefix word = + case getWordParts word of + exp : rest | isStringExpansion exp -> do + str <- getLiteralString (T_NormalWord (Id 0) rest) + guard $ "/" `isPrefixOf` str + return $ "." ++ str + _ -> Nothing + subRead name script = withContext (ContextSource name) $ inSeparateContext $