23 Commits

Author SHA1 Message Date
Vidar Holen
cff3e22911 Stable version v0.7.2
This release is dedicated to ethanol, for keeping
COVID-19 off both our hands and our minds.
2021-04-19 14:44:27 -07:00
Vidar Holen
5669eb2203 Make x-comparison warning default 2021-04-11 15:52:13 -07:00
Vidar Holen
b68df1882d Merge pull request #2181 from matthiasdiener/patch-1
Clarify 'which'
2021-03-31 20:03:23 -07:00
Matthias Diener
087865c680 Clarify 'which' 2021-03-20 20:43:18 -05:00
Vidar Holen
19c6f22c3f Merge branch 'm-ildefons-comment-backslash' 2021-03-20 18:13:50 -07:00
Vidar Holen
98952df35b Improve warnings on backslashes in comments 2021-03-20 18:12:39 -07:00
Vidar Holen
a277efdbb1 Merge branch 'comment-backslash' of https://github.com/m-ildefons/shellcheck into m-ildefons-comment-backslash 2021-03-20 13:34:40 -07:00
Vidar Holen
45687b0548 Merge pull request #2166 from avoidik/patch-1
suppress ntlm error messages in Windows build
2021-03-20 13:31:04 -07:00
Vidar Holen
ecdc21b0b7 Merge pull request #2112 from pepeiborra/patch-1
Add Haddock markup to SystemInterface
2021-03-14 13:16:29 -07:00
Vidar Holen
4eb42fa3c1 Merge branch 'austin987-busybox' 2021-03-14 13:02:41 -07:00
Vidar Holen
f02c297fdd Merge parser and analyzer shebang parsing 2021-03-11 23:04:17 -08:00
Vidar Holen
ea83b602d7 Merge branch 'busybox' of https://github.com/austin987/shellcheck into austin987-busybox 2021-03-11 21:44:17 -08:00
Vidar Holen
88cd21fd0f Fix missing +x with new cabal and use previous release deps for caching 2021-03-08 14:01:48 -08:00
Vidar Holen
83435c4f2e Merge pull request #2134 from kolyshkin/podman-sc2016
Whitelist podman for SC2016 about '$var'
2021-03-07 20:48:58 -08:00
Vidar Holen
4324b4a213 Merge pull request #2122 from freddii/master
fixed typing mistakes in changelog
2021-03-07 20:48:24 -08:00
Vidar Holen
a69d6cb661 Merge pull request #2117 from brother/patch-1
Change error 2076 to a warning.
2021-03-07 20:47:53 -08:00
Viacheslav Vasilyev
8442695b73 suppress ntlm error messages in Windows build
when building for windows there are many error message like below

```
003a:err:winediag:SECUR32_initNTLMSP ntlm_auth was not found or is outdated. Make sure that ntlm_auth >= 3.0.25 is in your path. Usually, you can find it in the winbind package of your distribution.
```
2021-03-06 14:19:08 +02:00
Moritz Röhrich
d6bb8fc0d8 Error on backslash in comment #2132
- Report error in case of a backspace in a comment

Backspaces in comments are no good. In most cases they are the result of
commenting out a longer line, that was broken down. This usually results
in the shell treating the following lines as their own commands on their
own lines instead of as parts of the longer, broken down line.
2021-02-14 19:13:29 +01:00
Austin English
2e59eba6eb add support for /bin/busybox sh shebang 2021-02-05 19:56:44 -06:00
Kir Kolyshkin
99e9d5c54b Whitelist podman for SC2016 about '$var'
Same as 08d2eef411 but for podman.

Fixes https://github.com/koalaman/shellcheck/issues/2057

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-01-27 16:21:44 -08:00
freddii
c5756760cb fixed typing mistakes in changelog 2021-01-05 14:08:03 +01:00
Martin Bagge / brother
19355226e1 Change error 2076 to a warning.
Implementing the suggestion by @pixarbuff #1985.
2020-12-27 00:27:36 +01:00
Pepe Iborra
4e7e3f9456 Add Haddock markup to SystemInterface 2020-12-22 09:15:57 +00:00
22 changed files with 103 additions and 108 deletions

View File

@@ -1,4 +1,4 @@
name: Build Lol
name: Build ShellCheck
# Run this workflow every time a new commit pushed to your repository
on: push
@@ -21,7 +21,7 @@ jobs:
run: |
mkdir source
cabal sdist
mv dist/*.tar.gz source/source.tar.gz
mv dist-newstyle/sdist/*.tar.gz source/source.tar.gz
- name: Deduce tags
run: |

View File

@@ -1,13 +1,14 @@
## Git
## v0.7.2 - 2021-04-19
### Added
- `disable` directives can now be a range, e.g. `disable=SC3000-SC4000`
- SC1143: Warn about line continuations in comments
- SC2259/SC2260: Warn when redirections override pipes
- SC2261: Warn about multiple competing redirections
- SC2262/SC2263: Warn about aliases declared and used in the same parsing unit
- SC2264: Warn about wrapper functions that blatantly recurse
- SC2265/SC2266: Warn when using & or | with test statements
- SC2267: Warn when using xargs -i instead of -I
- Optional avoid-x-comparisons: Style warning SC2268 for `[ x$var = xval ]`
- SC2268: Warn about unnecessary x-comparisons like `[ x$var = xval ]`
### Fixed
- SC1072/SC1073 now respond to disable annotations, though ignoring parse errors
@@ -21,7 +22,7 @@
- POSIX/dash unsupported feature warnings now have individual SC3xxx codes
- SC1090: A leading `$x/` or `$(x)/` is now treated as `./` when locating files
- SC2154: Variables appearing in -z/-n tests are no longer considered unassigned
- SC2270-SC2285: Improved warnings about misused =, e.g. `${var}=42`
- SC2270-SC2285: Improved warnings about misused `=`, e.g. `${var}=42`
## v0.7.1 - 2020-04-04
@@ -164,7 +165,7 @@
- SC2204/SC2205: Warn about `( -z foo )` and `( foo -eq bar )`
- SC2200/SC2201: Warn about brace expansion in [/[[
- SC2198/SC2199: Warn about arrays in [/[[
- SC2196/SC2197: Warn about deprected egrep/fgrep
- SC2196/SC2197: Warn about deprecated egrep/fgrep
- SC2195: Warn about unmatchable case branches
- SC2194: Warn about constant 'case' statements
- SC2193: Warn about `[[ file.png == *.mp3 ]]` and other unmatchables
@@ -181,7 +182,7 @@
### Fixed
- `-c` no longer suggested when using `grep -o | wc`
- Comments and whitespace are now allowed before filewide directives
- Here doc delimters with esoteric quoting like `foo""` are now handled
- Here doc delimiters with esoteric quoting like `foo""` are now handled
- SC2095 about `ssh` in while read loops is now suppressed when using `-n`
- `%(%Y%M%D)T` now recognized as a single formatter in `printf` checks
- `grep -F` now suppresses regex related suggestions

View File

@@ -1,5 +1,5 @@
Name: ShellCheck
Version: 0.7.1
Version: 0.7.2
Synopsis: Shell script analysis tool
License: GPL-3
License-file: LICENSE

View File

@@ -22,7 +22,7 @@ RUN curl -L "https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-in
ENV CABALOPTS "--with-ghc=$TARGET-ghc;--with-hc-pkg=$TARGET-ghc-pkg"
# Prebuild the dependencies
RUN cabal update && IFS=';' && cabal install $CABALOPTS --lib Diff-0.4.0 base-compat-0.11.2 base-orphans-0.8.4 dlist-1.0 hashable-1.3.0.0 indexed-traversable-0.1.1 integer-logarithms-1.0.3.1 primitive-0.7.1.0 regex-base-0.94.0.0 splitmix-0.1.0.3 tagged-0.8.6.1 th-abstraction-0.4.2.0 transformers-compat-0.6.6 base-compat-batteries-0.11.2 time-compat-1.9.5 unordered-containers-0.2.13.0 data-fix-0.3.1 vector-0.12.2.0 scientific-0.3.6.2 regex-tdfa-1.3.1.0 random-1.2.0 distributive-0.6.2.1 attoparsec-0.13.2.5 uuid-types-1.0.3 comonad-5.0.8 bifunctors-5.5.10 assoc-1.0.2 these-1.1.1.1 strict-0.4.0.1 aeson-1.5.5.1
RUN cabal update && IFS=';' && cabal install --dependencies-only $CABALOPTS ShellCheck
# Copy the build script
COPY build /usr/bin

View File

@@ -2,7 +2,7 @@
set -xe
{
tar xzv --strip-components=1
./striptests
chmod +x striptests && ./striptests
mkdir "$TARGETNAME"
cabal update
( IFS=';'; cabal build $CABALOPTS )

View File

@@ -21,7 +21,7 @@ RUN curl -L "https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-in
ENV CABALOPTS "--ghc-options;-split-sections -optc-Os -optc-Wl,--gc-sections;--with-ghc=$TARGET-ghc;--with-hc-pkg=$TARGET-ghc-pkg"
# Prebuild the dependencies
RUN cabal update && IFS=';' && cabal install $CABALOPTS --lib Diff-0.4.0 base-compat-0.11.2 base-orphans-0.8.4 dlist-1.0 hashable-1.3.0.0 indexed-traversable-0.1.1 integer-logarithms-1.0.3.1 primitive-0.7.1.0 regex-base-0.94.0.0 splitmix-0.1.0.3 tagged-0.8.6.1 th-abstraction-0.4.2.0 transformers-compat-0.6.6 base-compat-batteries-0.11.2 time-compat-1.9.5 unordered-containers-0.2.13.0 data-fix-0.3.1 vector-0.12.2.0 scientific-0.3.6.2 regex-tdfa-1.3.1.0 random-1.2.0 distributive-0.6.2.1 attoparsec-0.13.2.5 uuid-types-1.0.3 comonad-5.0.8 bifunctors-5.5.10 assoc-1.0.2 these-1.1.1.1 strict-0.4.0.1 aeson-1.5.5.1
RUN cabal update && IFS=';' && cabal install --dependencies-only $CABALOPTS ShellCheck
# Copy the build script
COPY build /usr/bin

View File

@@ -2,7 +2,7 @@
set -xe
{
tar xzv --strip-components=1
./striptests
chmod +x striptests && ./striptests
mkdir "$TARGETNAME"
cabal update
( IFS=';'; cabal build $CABALOPTS --enable-executable-static )

View File

@@ -51,7 +51,7 @@ RUN pirun apt-get install -y ghc cabal-install
# Finally we can build the current dependencies. This takes hours.
ENV CABALOPTS "--ghc-options;-split-sections -optc-Os -optc-Wl,--gc-sections;--gcc-options;-Os -Wl,--gc-sections -ffunction-sections -fdata-sections"
RUN pirun cabal update
RUN IFS=";" && pirun cabal install --lib $CABALOPTS Diff-0.4.0 base-compat-0.11.2 base-orphans-0.8.4 dlist-1.0 hashable-1.3.1.0 indexed-traversable-0.1.1 integer-logarithms-1.0.3.1 primitive-0.7.1.0 regex-base-0.94.0.1 splitmix-0.1.0.3 tagged-0.8.6.1 th-abstraction-0.4.2.0 transformers-compat-0.6.6 base-compat-batteries-0.11.2 time-compat-1.9.5 unordered-containers-0.2.13.0 data-fix-0.3.1 vector-0.12.2.0 scientific-0.3.6.2 regex-tdfa-1.3.1.0 random-1.2.0 distributive-0.6.2.1 attoparsec-0.13.2.5 uuid-types-1.0.4 comonad-5.0.8 bifunctors-5.5.10 assoc-1.0.2 these-1.1.1.1 strict-0.4.0.1 aeson-1.5.6.0
RUN IFS=";" && pirun cabal install --dependencies-only $CABALOPTS ShellCheck
# Copy the build script
WORKDIR /pi/scratch

View File

@@ -3,7 +3,7 @@ set -xe
cd /scratch
{
tar xzv --strip-components=1
./striptests
chmod +x striptests && ./striptests
mkdir "$TARGETNAME"
# This script does not cabal update because compiling anything new is slow
( IFS=';'; cabal build $CABALOPTS --enable-executable-static )

View File

@@ -1,30 +0,0 @@
FROM ubuntu:20.04
ENV TARGET powerpc64le-linux-gnu
ENV TARGETNAME linux.ppc64le
# Build dependencies
USER root
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y ghc automake autoconf build-essential llvm curl qemu-user-static gcc-$TARGET
# Build GHC
WORKDIR /ghc
RUN curl -L "https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-src.tar.xz" | tar xJ --strip-components=1
RUN ./boot && ./configure --host x86_64-linux-gnu --build x86_64-linux-gnu --target "$TARGET" --enable-unregisterised
RUN cp mk/flavours/quick-cross.mk mk/build.mk && make -j "$(nproc)"
RUN make install
RUN curl -L "https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz" | tar xJv -C /usr/local/bin
# Due to an apparent cabal bug, we specify our options directly to cabal
# It won't reuse caches if ghc-options are specified in ~/.cabal/config
ENV CABALOPTS "--ghc-options;-optl-Wl,-fuse-ld=bfd -split-sections -optc-Os -optc-Wl,--gc-sections;--with-ghc=$TARGET-ghc;--with-hc-pkg=$TARGET-ghc-pkg"
# Prebuild the dependencies
#RUN cabal update && IFS=';' && cabal install $CABALOPTS --lib Diff-0.4.0 base-compat-0.11.2 base-orphans-0.8.4 dlist-1.0 hashable-1.3.0.0 indexed-traversable-0.1.1 integer-logarithms-1.0.3.1 primitive-0.7.1.0 regex-base-0.94.0.0 splitmix-0.1.0.3 tagged-0.8.6.1 th-abstraction-0.4.2.0 transformers-compat-0.6.6 base-compat-batteries-0.11.2 time-compat-1.9.5 unordered-containers-0.2.13.0 data-fix-0.3.1 vector-0.12.2.0 scientific-0.3.6.2 regex-tdfa-1.3.1.0 random-1.2.0 distributive-0.6.2.1 attoparsec-0.13.2.5 uuid-types-1.0.3 comonad-5.0.8 bifunctors-5.5.10 assoc-1.0.2 these-1.1.1.1 strict-0.4.0.1 aeson-1.5.5.1
# Copy the build script
COPY build /usr/bin
WORKDIR /scratch
ENTRYPOINT ["/usr/bin/build"]

View File

@@ -1,15 +0,0 @@
#!/bin/sh
set -xe
{
tar xzv --strip-components=1
./striptests
mkdir "$TARGETNAME"
cabal update
( IFS=';'; cabal build $CABALOPTS --enable-executable-static )
find . -name shellcheck -type f -exec mv {} "$TARGETNAME/" \;
ls -l "$TARGETNAME"
"$TARGET-strip" -s "$TARGETNAME/shellcheck"
ls -l "$TARGETNAME"
qemu-ppc64le-static "$TARGETNAME/shellcheck" --version
} >&2
tar czv "$TARGETNAME"

View File

@@ -1 +0,0 @@
koalaman/scbuilder-linux-ppc64le

View File

@@ -2,7 +2,7 @@
set -xe
{
tar xzv --strip-components=1
./striptests
chmod +x striptests && ./striptests
mkdir "$TARGETNAME"
cabal update
( IFS=';'; cabal build $CABALOPTS --enable-executable-static )

View File

@@ -5,7 +5,7 @@ ENV TARGETNAME windows.x86_64
# We don't need wine32, even though it complains
USER root
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y curl busybox wine
RUN apt-get update && apt-get install -y curl busybox wine winbind
# Fetch Windows version, will be available under z:\haskell
WORKDIR /haskell
@@ -19,8 +19,8 @@ ENV WINEPATH /haskell/bin
# that necessitated this but I don't care enough to find out
ENV CABALOPTS "--ghc-options;-split-sections -optc-Os -optc-Wl,--gc-sections"
# Precompile some deps to speed up later builds. This list is just copied from `cabal build`
RUN wine /haskell/bin/cabal.exe update && IFS=';' && wine /haskell/bin/cabal.exe install $CABALOPTS --lib Diff-0.4.0 base-compat-0.11.2 base-orphans-0.8.4 dlist-1.0 hashable-1.3.0.0 indexed-traversable-0.1.1 integer-logarithms-1.0.3.1 primitive-0.7.1.0 regex-base-0.94.0.0 splitmix-0.1.0.3 tagged-0.8.6.1 th-abstraction-0.4.2.0 transformers-compat-0.6.6 base-compat-batteries-0.11.2 time-compat-1.9.5 unordered-containers-0.2.13.0 data-fix-0.3.1 vector-0.12.2.0 scientific-0.3.6.2 regex-tdfa-1.3.1.0 random-1.2.0 distributive-0.6.2.1 attoparsec-0.13.2.5 uuid-types-1.0.3 comonad-5.0.8 bifunctors-5.5.10 assoc-1.0.2 these-1.1.1.1 strict-0.4.0.1 aeson-1.5.5.1
# Precompile some deps to speed up later builds
RUN wine /haskell/bin/cabal.exe update && IFS=';' && wine /haskell/bin/cabal.exe install --lib --dependencies-only $CABALOPTS ShellCheck
COPY build /usr/bin
WORKDIR /scratch

View File

@@ -6,7 +6,7 @@ cabal() {
set -xe
{
tar xzv --strip-components=1
./striptests
chmod +x striptests && ./striptests
mkdir "$TARGETNAME"
cabal update
( IFS=';'; cabal build $CABALOPTS )

View File

@@ -17,9 +17,11 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
-}
{-# LANGUAGE TemplateHaskell #-}
module ShellCheck.ASTLib where
import ShellCheck.AST
import ShellCheck.Regex
import Control.Monad.Writer
import Control.Monad
@@ -31,6 +33,8 @@ import Data.Maybe
import qualified Data.Map as Map
import Numeric (showHex)
import Test.QuickCheck
arguments (T_SimpleCommand _ _ (cmd:args)) = args
-- Is this a type of loop?
@@ -672,3 +676,43 @@ isAnnotationIgnoringCode code t =
where
hasNum (DisableComment from to) = code >= from && code < to
hasNum _ = False
prop_executableFromShebang1 = executableFromShebang "/bin/sh" == "sh"
prop_executableFromShebang2 = executableFromShebang "/bin/bash" == "bash"
prop_executableFromShebang3 = executableFromShebang "/usr/bin/env ksh" == "ksh"
prop_executableFromShebang4 = executableFromShebang "/usr/bin/env -S foo=bar bash -x" == "bash"
prop_executableFromShebang5 = executableFromShebang "/usr/bin/env --split-string=bash -x" == "bash"
prop_executableFromShebang6 = executableFromShebang "/usr/bin/env --split-string=foo=bar bash -x" == "bash"
prop_executableFromShebang7 = executableFromShebang "/usr/bin/env --split-string bash -x" == "bash"
prop_executableFromShebang8 = executableFromShebang "/usr/bin/env --split-string foo=bar bash -x" == "bash"
prop_executableFromShebang9 = executableFromShebang "/usr/bin/env foo=bar dash" == "dash"
prop_executableFromShebang10 = executableFromShebang "/bin/busybox sh" == "ash"
prop_executableFromShebang11 = executableFromShebang "/bin/busybox ash" == "ash"
-- Get the shell executable from a string like '/usr/bin/env bash'
executableFromShebang :: String -> String
executableFromShebang = shellFor
where
re = mkRegex "/env +(-S|--split-string=?)? *(.*)"
shellFor s | s `matches` re =
case matchRegex re s of
Just [flag, shell] -> fromEnvArgs (words shell)
_ -> ""
shellFor sb =
case words sb of
[] -> ""
[x] -> basename x
(first:second:args) | basename first == "busybox" ->
case basename second of
"sh" -> "ash" -- busybox sh is ash
x -> x
(first:args) | basename first == "env" ->
fromEnvArgs args
(first:_) -> basename first
fromEnvArgs args = fromMaybe "" $ find (notElem '=') $ skipFlags args
basename s = reverse . takeWhile (/= '/') . reverse $ s
skipFlags = dropWhile ("-" `isPrefixOf`)
return []
runTests = $quickCheckAll

View File

@@ -196,6 +196,7 @@ nodeChecks = [
,checkAssignToSelf
,checkEqualsInCommand
,checkSecondArgIsComparison
,checkComparisonWithLeadingX
]
optionalChecks = map fst optionalTreeChecks
@@ -243,13 +244,6 @@ optionalTreeChecks = [
cdPositive = "echo $VAR",
cdNegative = "VAR=hello; echo $VAR"
}, checkUnassignedReferences' True)
,(newCheckDescription {
cdName = "avoid-x-comparisons",
cdDescription = "Warn about 'x'-prefix in comparisons",
cdPositive = "[ \"x$var\" = xval ]",
cdNegative = "[ \"$var\" = val ]"
}, nodeChecksToTreeCheck [checkComparisonWithLeadingX])
]
optionalCheckMap :: Map.Map String (Parameters -> Token -> [TokenComment])
@@ -590,6 +584,12 @@ prop_checkShebang9 = verifyNotTree checkShebang "# shellcheck shell=sh\ntrue"
prop_checkShebang10= verifyNotTree checkShebang "#!foo\n# shellcheck shell=sh ignore=SC2239\ntrue"
prop_checkShebang11= verifyTree checkShebang "#!/bin/sh/\ntrue"
prop_checkShebang12= verifyTree checkShebang "#!/bin/sh/ -xe\ntrue"
prop_checkShebang13= verifyTree checkShebang "#!/bin/busybox sh"
prop_checkShebang14= verifyNotTree checkShebang "#!/bin/busybox sh\n# shellcheck shell=sh\n"
prop_checkShebang15= verifyNotTree checkShebang "#!/bin/busybox sh\n# shellcheck shell=dash\n"
prop_checkShebang16= verifyTree checkShebang "#!/bin/busybox ash"
prop_checkShebang17= verifyNotTree checkShebang "#!/bin/busybox ash\n# shellcheck shell=dash\n"
prop_checkShebang18= verifyNotTree checkShebang "#!/bin/busybox ash\n# shellcheck shell=sh\n"
checkShebang params (T_Annotation _ list t) =
if any isOverride list then [] else checkShebang params t
where
@@ -1015,6 +1015,7 @@ checkSingleQuotedVariables params t@(T_SingleQuoted id s) =
,"alias"
,"sudo" -- covering "sudo sh" and such
,"docker" -- like above
,"podman"
,"dpkg-query"
,"jq" -- could also check that user provides --arg
,"rename"
@@ -1216,8 +1217,8 @@ checkQuotedCondRegex _ (TC_Binary _ _ "=~" _ rhs) =
where
error t =
unless (isConstantNonRe t) $
err (getId t) 2076
"Don't quote right-hand side of =~, it'll match literally rather than as a regex."
warn (getId t) 2076
"Remove quotes from right-hand side of =~ to match as a regex rather than literally."
re = mkRegex "[][*.+()|]"
hasMetachars s = s `matches` re
isConstantNonRe t = fromMaybe False $ do
@@ -3999,7 +4000,7 @@ checkComparisonWithLeadingX params t =
check lhs rhs
_ -> return ()
where
msg = "Avoid outdated x-prefix in comparisons as it no longer serves a purpose."
msg = "Avoid x-prefix in comparisons as it no longer serves a purpose."
check lhs rhs = sequence_ $ do
l <- fixLeadingX lhs
r <- fixLeadingX rhs

View File

@@ -240,6 +240,8 @@ prop_determineShell7 = determineShellTest "#! /bin/ash" == Dash
prop_determineShell8 = determineShellTest' (Just Ksh) "#!/bin/sh" == Sh
prop_determineShell9 = determineShellTest "#!/bin/env -S dash -x" == Dash
prop_determineShell10 = determineShellTest "#!/bin/env --split-string= dash -x" == Dash
prop_determineShell11 = determineShellTest "#!/bin/busybox sh" == Dash -- busybox sh is a specific shell, not posix sh
prop_determineShell12 = determineShellTest "#!/bin/busybox ash" == Dash
determineShellTest = determineShellTest' Nothing
determineShellTest' fallbackShell = determineShell fallbackShell . fromJust . prRoot . pScript
@@ -253,19 +255,6 @@ determineShell fallbackShell t = fromMaybe Bash $
headOrDefault (fromShebang s) [s | ShellOverride s <- annotations]
fromShebang (T_Script _ (T_Literal _ s) _) = executableFromShebang s
-- Given a string like "/bin/bash" or "/usr/bin/env dash",
-- return the shell basename like "bash" or "dash"
executableFromShebang :: String -> String
executableFromShebang = shellFor
where
shellFor s | "/env " `isInfixOf` s = case matchRegex re s of
Just [flag, shell] -> shell
_ -> ""
shellFor s | ' ' `elem` s = shellFor $ takeWhile (/= ' ') s
shellFor s = reverse . takeWhile (/= '/') . reverse $ s
re = mkRegex "/env +(-S|--split-string=?)? *([^ ]*)"
-- Given a root node, make a map from Id to parent Token.
-- This is used to populate parentMap in Parameters
getParentTree :: Token -> Map.Map Id Token

View File

@@ -1056,7 +1056,7 @@ checkFindRedirections = CommandCheck (Basename "find") f
prop_checkWhich = verify checkWhich "which '.+'"
checkWhich = CommandCheck (Basename "which") $
\t -> info (getId $ getCommandTokenOrThis t) 2230 "which is non-standard. Use builtin 'command -v' instead."
\t -> info (getId $ getCommandTokenOrThis t) 2230 "'which' is non-standard. Use builtin 'command -v' instead."
prop_checkSudoRedirect1 = verify checkSudoRedirect "sudo echo 3 > /proc/file"
prop_checkSudoRedirect2 = verify checkSudoRedirect "sudo cmd < input"

View File

@@ -73,15 +73,15 @@ import qualified Data.Map as Map
data SystemInterface m = SystemInterface {
-- Read a file by filename, or return an error
-- | Read a file by filename, or return an error
siReadFile :: String -> m (Either ErrorMessage String),
-- Given:
-- | Given:
-- the current script,
-- a list of source-path annotations in effect,
-- and a sourced file,
-- find the sourced file
siFindSource :: String -> [String] -> String -> m FilePath,
-- Get the configuration file (name, contents) for a filename
-- | Get the configuration file (name, contents) for a filename
siGetConfig :: String -> m (Maybe (FilePath, String))
}

View File

@@ -24,7 +24,7 @@
module ShellCheck.Parser (parseScript, runTests) where
import ShellCheck.AST
import ShellCheck.ASTLib
import ShellCheck.ASTLib hiding (runTests)
import ShellCheck.Data
import ShellCheck.Interface
@@ -87,11 +87,23 @@ extglobStart = oneOf extglobStartChars
unicodeDoubleQuotes = "\x201C\x201D\x2033\x2036"
unicodeSingleQuotes = "\x2018\x2019"
prop_spacing = isOk spacing " \\\n # Comment"
prop_spacing1 = isOk spacing " \\\n # Comment"
prop_spacing2 = isOk spacing "# We can continue lines with \\"
prop_spacing3 = isWarning spacing " \\\n # --verbose=true \\"
spacing = do
x <- many (many1 linewhitespace <|> try (string "\\\n" >> return ""))
x <- many (many1 linewhitespace <|> continuation)
optional readComment
return $ concat x
where
continuation = do
try (string "\\\n")
-- The line was continued. Warn if this next line is a comment with a trailing \
whitespace <- many linewhitespace
optional $ do
x <- readComment
when ("\\" `isSuffixOf` x) $
parseProblem ErrorC 1143 "This backslash is part of a comment and does not continue the line."
return whitespace
spacing1 = do
spacing <- spacing
@@ -1039,6 +1051,7 @@ readComment = do
unexpecting "shellcheck annotation" readAnnotationPrefix
readAnyComment
prop_readAnyComment = isOk readAnyComment "# Comment"
readAnyComment = do
char '#'
many $ noneOf "\r\n"
@@ -1404,6 +1417,8 @@ readNormalEscaped = called "escaped char" $ do
do
next <- quotable <|> oneOf "?*@!+[]{}.,~#"
when (next == ' ') $ checkTrailingSpaces pos <|> return ()
-- Check if this line is followed by a commented line with a trailing backslash
when (next == '\n') $ try . lookAhead $ void spacing
return $ if next == '\n' then "" else [next]
<|>
do
@@ -3216,8 +3231,8 @@ readScriptFile sourced = do
let ignoreShebang = shellAnnotationSpecified || shellFlagSpecified
unless ignoreShebang $
verifyShebang pos (getShell shebangString)
if ignoreShebang || isValidShell (getShell shebangString) /= Just False
verifyShebang pos (executableFromShebang shebangString)
if ignoreShebang || isValidShell (executableFromShebang shebangString) /= Just False
then do
commands <- withAnnotations annotations readCompoundListOrEmpty
id <- endSpan start
@@ -3231,17 +3246,6 @@ readScriptFile sourced = do
return $ T_Script id shebang []
where
basename s = reverse . takeWhile (/= '/') . reverse $ s
skipFlags = dropWhile ("-" `isPrefixOf`)
getShell sb =
case words sb of
[] -> ""
[x] -> basename x
(first:args) ->
if basename first == "env"
then fromMaybe "" $ find (notElem '=') $ skipFlags args
else basename first
verifyShebang pos s = do
case isValidShell s of
Just True -> return ()

View File

@@ -4,6 +4,7 @@ import Control.Monad
import System.Exit
import qualified ShellCheck.Analytics
import qualified ShellCheck.AnalyzerLib
import qualified ShellCheck.ASTLib
import qualified ShellCheck.Checker
import qualified ShellCheck.Checks.Commands
import qualified ShellCheck.Checks.Custom
@@ -17,6 +18,7 @@ main = do
results <- sequence [
ShellCheck.Analytics.runTests
,ShellCheck.AnalyzerLib.runTests
,ShellCheck.ASTLib.runTests
,ShellCheck.Checker.runTests
,ShellCheck.Checks.Commands.runTests
,ShellCheck.Checks.Custom.runTests