#1016919 lintian: bash-term-in-posix-shell false positive for `. "$(dirname "$0")/functions.sh"`

#1016919#5
Date:
2022-08-09 19:20:17 UTC
From:
To:
The following script (approved by `shellcheck -s sh`) causes a false
positive warning `bash-term-in-posix-shell`:

     #!/bin/sh
     . "$(dirname "$0")/functions.sh"
     do_something

I: my-test: bash-term-in-posix-shell '. "$(dirname "$0")/functions.sh"'
[usr/bin/my-test:2]

Probably the lintian check is misparsing the quotes and the space
between `dirname` and `"$0"`, leading it to believe that an argument is
being passed to the sourced script (that would be, in fact, a bashism).

Regards,

#1016919#10
Date:
2023-01-31 16:11:10 UTC
From:
To:
While inspecting lintian's output wrt (several) kernel builds I did, I
found the following warning, which seems to be a false positive?

I: linux-perf: bash-term-in-posix-shell '. $(dirname $0)/../lib/coresight.sh' [usr/lib/perf-core/tests/shell/coresight/asm_pure_loop.sh:8]
I: linux-perf: bash-term-in-posix-shell '. $(dirname $0)/../lib/coresight.sh' [usr/lib/perf-core/tests/shell/coresight/memcpy_thread_16k_10.sh:8]
I: linux-perf: bash-term-in-posix-shell '. $(dirname $0)/../lib/coresight.sh' [usr/lib/perf-core/tests/shell/coresight/thread_loop_check_tid_10.sh:8]
I: linux-perf: bash-term-in-posix-shell '. $(dirname $0)/../lib/coresight.sh' [usr/lib/perf-core/tests/shell/coresight/thread_loop_check_tid_2.sh:8]
I: linux-perf: bash-term-in-posix-shell '. $(dirname $0)/../lib/coresight.sh' [usr/lib/perf-core/tests/shell/coresight/unroll_loop_thread_10.sh:8]
I: linux-perf: bash-term-in-posix-shell '. $(dirname $0)/lib/probe.sh' [usr/lib/perf-core/tests/shell/probe_vfs_getname.sh:7]
I: linux-perf: bash-term-in-posix-shell '. $(dirname $0)/lib/probe.sh' [usr/lib/perf-core/tests/shell/record+probe_libc_inet_pton.sh:13]
I: linux-perf: bash-term-in-posix-shell '. $(dirname $0)/lib/probe.sh' [usr/lib/perf-core/tests/shell/record+script_probe_vfs_getname.sh:12]
I: linux-perf: bash-term-in-posix-shell '. $(dirname $0)/lib/probe.sh' [usr/lib/perf-core/tests/shell/trace+probe_vfs_getname.sh:13]
I: linux-perf: bash-term-in-posix-shell '. $(dirname $0)/lib/probe_vfs_getname.sh' [usr/lib/perf-core/tests/shell/probe_vfs_getname.sh:11]
I: linux-perf: bash-term-in-posix-shell '. $(dirname $0)/lib/probe_vfs_getname.sh' [usr/lib/perf-core/tests/shell/record+script_probe_vfs_getname.sh:16]
I: linux-perf: bash-term-in-posix-shell '. $(dirname $0)/lib/probe_vfs_getname.sh' [usr/lib/perf-core/tests/shell/trace+probe_vfs_getname.sh:18]

Looking at the first item:
```sh
$ cat tools/perf/tests/shell/coresight/asm_pure_loop.sh
#!/bin/sh -e
# CoreSight / ASM Pure Loop

# SPDX-License-Identifier: GPL-2.0
# Carsten Haitzler <carsten.haitzler@arm.com>, 2021

TEST="asm_pure_loop"
. $(dirname $0)/../lib/coresight.sh
ARGS=""
DATV="out"
DATA="$DATD/perf-$TEST-$DATV.data"

perf record $PERFRECOPT -o "$DATA" "$BIN" $ARGS

perf_dump_aux_verify "$DATA" 10 10 10

err=$?
exit $err
```

Shellcheck does not flag this as having bashisms.
Searching for both `.` and `dirname` and they both seem to be POSIX compliant.
https://unix.stackexchange.com/a/253527
https://unix.stackexchange.com/a/17885

Which leads me to believe this is a false positive indeed.

- -- System Information:
Debian Release: bookworm/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable'), (101, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 6.1.0-2-amd64 (SMP w/4 CPU threads; PREEMPT)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE=en_US:en
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages lintian depends on:
ii  binutils                        2.40-2
ii  bzip2                           1.0.8-5+b1
ii  diffstat                        1.65-1
ii  dpkg                            1.21.19
ii  dpkg-dev                        1.21.19
ii  file                            1:5.44-3
ii  gettext                         0.21-10
ii  gpg                             2.2.40-1
ii  intltool-debian                 0.35.0+20060710.6
ii  iso-codes                       4.12.0-1
ii  libapt-pkg-perl                 0.1.40+b2
ii  libarchive-zip-perl             1.68-1
ii  libberkeleydb-perl              0.64-2+b1
ii  libcapture-tiny-perl            0.48-2
ii  libclass-xsaccessor-perl        1.19-4+b1
ii  libclone-perl                   0.46-1
ii  libconfig-tiny-perl             2.28-2
ii  libconst-fast-perl              0.014-2
ii  libcpanel-json-xs-perl          4.32-1+b1
ii  libdata-dpath-perl              0.58-2
ii  libdata-validate-domain-perl    0.10-1.1
ii  libdata-validate-uri-perl       0.07-2
ii  libdevel-size-perl              0.83-2+b1
pn  libdigest-sha-perl              <none>
ii  libdpkg-perl                    1.21.19
ii  libemail-address-xs-perl        1.05-1+b1
ii  libfile-basedir-perl            0.09-2
ii  libfile-find-rule-perl          0.34-3
ii  libfont-ttf-perl                1.06-2
ii  libhtml-html5-entities-perl     0.004-3
ii  libhtml-tokeparser-simple-perl  3.16-4
ii  libio-interactive-perl          1.023-2
ii  libipc-run3-perl                0.048-3
ii  libjson-maybexs-perl            1.004004-1
ii  liblist-compare-perl            0.55-2
ii  liblist-someutils-perl          0.59-1
ii  liblist-utilsby-perl            0.12-2
ii  libmldbm-perl                   2.05-4
ii  libmoo-perl                     2.005005-1
ii  libmoox-aliases-perl            0.001006-2
ii  libnamespace-clean-perl         0.27-2
ii  libpath-tiny-perl               0.144-1
ii  libperlio-gzip-perl             0.20-1+b1
ii  libperlio-utf8-strict-perl      0.010-1
ii  libproc-processtable-perl       0.634-1+b2
ii  libregexp-wildcards-perl        1.05-3
ii  libsereal-decoder-perl          5.001+ds-1+b1
ii  libsereal-encoder-perl          5.001+ds-2
ii  libsort-versions-perl           1.62-3
ii  libsyntax-keyword-try-perl      0.28-1
ii  libterm-readkey-perl            2.38-2+b1
ii  libtext-levenshteinxs-perl      0.03-5+b1
ii  libtext-markdown-discount-perl  0.16-1
ii  libtext-xslate-perl             3.5.9-1+b2
ii  libtime-duration-perl           1.21-2
ii  libtime-moment-perl             0.44-2+b1
ii  libtimedate-perl                2.3300-2
ii  libunicode-utf8-perl            0.62-2
ii  liburi-perl                     5.17-1
ii  libwww-mechanize-perl           2.15-1
ii  libwww-perl                     6.67-1
ii  libxml-libxml-perl              2.0207+dfsg+really+2.0134-1+b1
ii  libyaml-libyaml-perl            0.84+ds-1+b1
ii  lzip [lzip-decompressor]        1.23-4
ii  lzop                            1.04-2
ii  man-db                          2.11.2-1
ii  patchutils                      0.4.2-1
ii  perl [libencode-perl]           5.36.0-7
ii  t1utils                         1.41-4
ii  unzip                           6.0-27
ii  xz-utils                        5.4.1-0.0

lintian recommends no packages.

Versions of packages lintian suggests:
pn  binutils-multiarch     <none>
pn  libtext-template-perl  <none>

- -- no debconf information
-----BEGIN PGP SIGNATURE-----

iHUEARYIAB0WIQT1sUPBYsyGmi4usy/XblvOeH7bbgUCY9k9lQAKCRDXblvOeH7b
boHVAP0T1pAgn778b5BVeXI0zh8UqJMBW2QimI4X0l0RcyLk7QD+KWM0+MPsDhin
t0GreG/8ObX7kvPF+mmW9UXrzY5RkAE=
=vXNU
-----END PGP SIGNATURE-----

#1016919#15
Date:
2023-01-31 17:10:57 UTC
From:
To:
Diederik de Haas <didi.debian@cknow.org> writes:

Yeah, I think it's a false positive in this check (check_line in
Lintian::Check::Shell::NonPosix::BashCentric):

    # since this test is ugly, I have to do it by itself
    # detect source (.) trying to pass args to the command it runs
    # The first expression weeds out '. "foo bar"'
    if (
        $line !~  m{\A \s*\.\s+
                                   (?:\"[^\"]+\"|\'[^\']+\')\s*
                                   (?:[\&\|<;]|\d?>|\Z)}xsm
        && $line =~ /^\s*(\.\s+[^\s;\`:]+\s+([^\s;]+))/
    ) {

        my ($dot_command, $extra) = ($1, $2);

        push(@matches, $dot_command)
          if length $dot_command
          && $extra !~ m{^ & | [|] | < | \d? > }x;
    }

It's picking up the space in $(dirname $0) and thinking that's a space in
the . command line and therefore arguments are being passed to the sourced
file, which is a bashism.  The missing logic is understanding that a $()
block is effectively a quoted string and thus should be ignored for the
purposes of this test.

#1016919#20
Date:
2023-01-31 21:16:22 UTC
From:
To:
I looked a little deeper/further and specifically into `lib/coresight.sh` and
that file does contain `echo -n`, which ShellCheck does flag as it's undefined in
POSIX.  So maybe it was actually triggered by the 'included' file?

I don't know if that could also be the case for the original reporter.

#1016919#25
Date:
2023-01-31 21:27:24 UTC
From:
To:
Diederik de Haas <didi.debian@cknow.org> writes:

Although echo -n is undefined in POSIX, Debian requires it to work in all
shells that are eligible to be /bin/sh.  See:

https://www.debian.org/doc/debian-policy/ch-files.html#scripts

#1016919#30
Date:
2023-01-31 21:38:29 UTC
From:
To:
Ah, yeah, then lintian shouldn't trip over that.
I lack any Perl knowledge to (properly) understand the code snippet you posted
earlier or what lintian does in code, so I can't help with that.

Cheers,
  Diederik