Re: [checks/scripts] [PATCH 4/4] bashisms update
On Fri, 2008-06-20 at 18:24 +0100, Adam D. Barratt wrote:
> As I suspected, the original patch didn't apply cleanly on top of the
> three earlier patches; I've attached an updated patch against lintian
> trunk which uses qr.
and, predictably, immediately spotted a small typo I'd made when
updating the patch *sigh* The (hopefully finally) updated version is
attached.
Regards,
Adam
--- checks/scripts.orig 2008-06-20 13:42:13.000000000 +0100
+++ checks/scripts 2008-06-20 18:20:30.000000000 +0100
@@ -543,41 +543,86 @@
if ($cat_string eq "" and $checkbashisms and !$within_another_shell) {
my $found = 0;
my $match = '';
+ my $LEADIN = qr'(?:(^|[`&;(|{])\s*|(if|do|while)\s+)';
+ my @bashism_single_quote_regexs = (
+ $LEADIN . qr'echo\s+(?:-[^e]+\s+)?([\'])[^\']*(\\[\\abcEfnrtv0])+.*?[\']',
+ # unsafe echo with backslashes
+ );
my @bashism_string_regexs = (
- '\$\[\w+\]', # arith not allowed
- '\$\{\w+\:\d+(?::\d+)?\}', # ${foo:3[:1]}
- '\$\{\w+(/.+?){1,2}\}', # ${parm/?/pat[/str]}
- '\$\{\#?\w+\[[0-9\*\@]+\]\}',# bash arrays, ${name[0|*|@]}
- '\$\{!\w+[\@*]\}', # ${!prefix[*|@]}
- '\$\{!\w+\}', # ${!name}
- '(\$\(|\`)\s*\<\s*\S+\s*(\)|\`)', # $(\< foo) should be $(cat foo)
- '\$RANDOM\b', # $RANDOM
- '\$(OS|MACH)TYPE\b', # $(OS|MACH)TYPE
- '\$HOST(TYPE|NAME)\b', # $HOST(TYPE|NAME)
- '\$DIRSTACK\b', # $DIRSTACK
- '\$EUID\b', # $EUID should be "id -u"
+ qr'\$\[\w+\]', # arith not allowed
+ qr'\$\{\w+\:\d+(?::\d+)?\}', # ${foo:3[:1]}
+ qr'\$\{\w+(/.+?){1,2}\}', # ${parm/?/pat[/str]}
+ qr'\$\{\#?\w+\[[0-9\*\@]+\]\}',# bash arrays, ${name[0|*|@]}
+ qr'\$\{!\w+[\@*]\}', # ${!prefix[*|@]}
+ qr'\$\{!\w+\}', # ${!name}
+ qr'(\$\(|\`)\s*\<\s*\S+\s*(\)|\`)', # $(\< foo) should be $(cat foo)
+ qr'\$\{?RANDOM\}?\b', # $RANDOM
+ qr'\$\{?(OS|MACH)TYPE\}?\b', # $(OS|MACH)TYPE
+ qr'\$\{?HOST(TYPE|NAME)\}?\b', # $HOST(TYPE|NAME)
+ qr'\$\{?DIRSTACK\}?\b', # $DIRSTACK
+ qr'\$\{?EUID\}?\b', # $EUID should be "id -u"
+ qr'\$\{?UID\}?\b', # $UID should be "id -ru"
+ qr'\$\{?SECONDS\}?\b', # $SECONDS
+ qr'\$\{?BASH_[A-Z]+\}?\b', # $BASH_SOMETHING
+ qr'\$\{?SHELLOPTS\}?\b', # $SHELLOPTS
+ qr'\$\{?PIPESTATUS\}?\b', # $PIPESTATUS
+ qr'\$\{?SHLVL\}?\b', # $SHLVL
+ qr'<<<', # <<< here string
+ $LEADIN . qr'echo\s+(?:-[^e]+\s+)?([\"])[^\"]*(\\[\\abcEfnrtv0])+.*?[\"]',
+ # unsafe echo with backslashes
);
my @bashism_regexs = (
- 'function \w+\(\s*\)', # function is useless
- # should be '.', not 'source'
- '(?:^|\s+)source\s+(?:\.\/|\/|\$)[^\s]+',
- '(\[|test|-o|-a)\s*[^\s]+\s+==\s', # should be 'b = a'
- '\s(\|\&)', # pipelining is not POSIX
- '[^\\\]\{([^\s]+?,)+[^\\\}\s]+\}', # brace expansion
- '(?:^|\s+)\w+\[\d+\]=', # bash arrays, H[0]
- '(?:^|\s+)read\s*(?:;|$)', # read without variable
- '(?:^|\s+)kill\s+-[^sl]\w*', # kill -[0-9] or -[A-Z]
- '(?:^|\s+)trap\s+["\']?.*["\']?\s+.*[1-9]', # trap with signal numbers
- '\&>', # cshism
- '(<\&|>\&)\s*((-|\d+)[^\s;|\)\`&]|[^-\d])', # should be >word 2>&1
- '\[\[(?!:)', # alternative test command
- '(?:^|\s+)select\s+\w+', # 'select' is not POSIX
- '(?:^|\s+)echo\s+-e', # echo -e
- '(?:^|\s+)exec\s+-[acl]', # exec -c/-l/-a name
- '(?:^|\s+)let\s', # let ...
- '(?<![\$\(])\(\(.*\)\)', # '((' should be '$(('
- '(\[|test)\s+-a', # test with unary -a (should be -e)
- '<<<', # <<< here string
+ qr'function \w+\(\s*\)', # function is useless
+ # should be '.', not 'source'
+ $LEADIN . qr'source\s+(?:\.\/|\/|\$)[^\s]+',
+ qr'(test|-o|-a)\s*[^\s]+\s+==\s', # should be 'b = a'
+ qr'\[\s+[^\]]+\s+==\s', # should be 'b = a'
+ qr'\s(\|\&)', # pipelining is not POSIX
+ qr'[^\\]\{(?:[^\s\\\}]+?,)+[^\\\}\s]+\}', # brace expansion
+ qr'(?:^|\s+)\w+\[\d+\]=', # bash arrays, H[0]
+ $LEADIN . qr'(read\s*(-[^r]+)*(?:;|$))',
+ # read without variable or with option other than -r
+ $LEADIN . qr'kill\s+-[^sl]\w*',# kill -[0-9] or -[A-Z]
+ $LEADIN . qr'trap\s+["\']?.*["\']?\s+.*[1-9]', # trap with signal numbers
+ qr'\&>', # cshism
+ qr'(<\&|>\&)\s*((-|\d+)[^\s;|)`&\\\\]|[^-\d\s]+)', # should be >word 2>&1
+ qr'\[\[(?!:)', # alternative test command
+ $LEADIN . qr'select\s+\w+', # 'select' is not POSIX
+ $LEADIN . qr'echo\s+(-n\s+)?-n?en?', # echo -e
+ $LEADIN . qr'exec\s+-[acl]', # exec -c/-l/-a name
+ qr'(?:^|\s+)let\s', # let ...
+ qr'(?<![\$\(])\(\(.*\)\)', # '((' should be '$(('
+ qr'\$\[[^][]+\]', # '$[' should be '$(('
+ qr'(\[|test)\s+-a', # test with unary -a (should be -e)
+ qr'/dev/(tcp|udp)', # /dev/(tcp|udp)
+ $LEADIN . qr'\w+\+=', # should be "VAR="${VAR}foo"
+ $LEADIN . qr'suspend\s',
+ $LEADIN . qr'caller\s',
+ $LEADIN . qr'complete\s',
+ $LEADIN . qr'compgen\s',
+ $LEADIN . qr'declare\s',
+ $LEADIN . qr'typeset\s',
+ $LEADIN . qr'disown\s',
+ $LEADIN . qr'builtin\s',
+ $LEADIN . qr'set\s+-[BHT]+', # set -[BHT]
+ $LEADIN . qr'alias\s+-p', # alias -p
+ $LEADIN . qr'unalias\s+-a', # unalias -a
+ $LEADIN . qr'local\s+-[a-zA-Z]+', # local -opt
+ $LEADIN . qr'local\s+\w+=', # local foo=bar
+ qr'(?:^|\s+)\s*\(?\w*[^\(\w\s]+\S*?\s*\(\)[^\"]?',
+ # function names should only contain [a-z0-9_]
+ $LEADIN . qr'(push|pop)d\b', # (push|pod)d
+ $LEADIN . qr'export\s+-[^p]', # export only takes -p as an option
+ $LEADIN . qr'ulimit\b',
+ $LEADIN . qr'shopt\b',
+ $LEADIN . qr'type\s',
+ $LEADIN . qr'time\s',
+ $LEADIN . qr'dirs\b',
+ qr'(?:^|\s+)[<>]\(.*?\)', # <() process substituion
+ qr'(?:^|\s+)readonly\s+-[af]', # readonly -[af]
+ $LEADIN . qr'(sh|\$\{?SHELL\}?) -[rD]', # sh -[rD]
+ $LEADIN . qr'(sh|\$\{?SHELL\}?) --\w+', # sh --long-option
+ $LEADIN . qr'(sh|\$\{?SHELL\}?) [-+]O', # sh [-+]O
);
# since this test is ugly, I have to do it by itself
@@ -593,9 +638,20 @@
}
}
+ my $line = $_;
+
+ unless ($found) {
+ for my $re (@bashism_single_quote_regexs) {
+ if ($line =~ m/($re)/) {
+ $found = 1;
+ ($match) = m/($re)/;
+ last;
+ }
+ }
+ }
+
# Ignore anything inside single quotes; it could be an
# argument to grep or the like.
- my $line = $_;
# $cat_line contains the version of the line we'll check
# for heredoc delimiters later. Initially, remove any
--- testset/maintainer-scripts/debian/prerm.orig 2008-06-20 13:42:44.000000000 +0100
+++ testset/maintainer-scripts/debian/prerm 2008-06-20 13:41:24.000000000 +0100
@@ -43,6 +43,7 @@
# More false positives for bashism checks. None of these are errors.
echo "$line" | grep -q '{fonts/map,}/{\$progname,pdftex,dvips,}//'
+echo "$line" | grep -q "${fonts},${foo}"
echo '$[1+2]'
printf "foo |& bar"
perl -e "print q( kill -HUP $? )"
@@ -55,3 +56,100 @@
# This is the only install-sgmlcatalog call that's allowed.
install-sgmlcatalog --quiet --remove package
+
+# More bashisms checks
+
+read -x foo
+read -x
+read -r foo
+read foo
+read
+
+echo "a\\b"
+echo 'a\nb'
+
+echo "${UID}"
+echo "$EUID"
+echo "$SHLVL"
+echo "$DIRSTACK"
+echo "$SECONDS"
+echo "$BASH"
+echo "$BASH_FOO"
+echo "$SHELLOPTS"
+echo "$PIPESTATUS"
+
+bar="$(cut '-d|' -f2 <<< "$foo")"
+
+VAR=1
+VAR+=a
+
+echos() {
+ echo -n -e "bar"
+ echo -e -n "bar"
+ echo -en "bar"
+ echo -ne "bar"
+ echo "bar"
+ echo "echo -e foo"
+}
+
+ech.os() {
+ echo foo >& 2
+ echo foo >&bar
+ echo foo >& bar
+}
+
+echoes() {
+ echo "abc\nxyz"
+ echo 'xyz\rabc'
+ echo foo\cbar
+
+ echo -e "abc\nxyz"
+ echo -net 'xyz\rabc'
+ echo -e foo\cbar
+}
+
+foobar.() {
+ suspend x
+ suspended x
+ caller x
+ complete x
+ compgen x
+ declare -a foo
+}
+
+.foobar() {
+ typeset -x bar
+ disown 1
+ builtin foo
+ set -B
+ alias -p
+ unalias -a
+}
+
+IFS="()"
+
+ulimit
+shopt
+type -v bar
+time ls
+dirs
+diff <(tac a) <(tac b)
+
+pushd
+
+local foo=bar
+local -x foo
+
+popd
+
+readonly -f
+
+echo bar > /dev/tcp
+export x
+export -x x
+export -p x
+
+sh -x
+sh -D
+sh --foo
+sh +O
--- testset/tags.maintainer-scripts.orig 2008-06-20 13:42:27.000000000 +0100
+++ testset/tags.maintainer-scripts 2008-06-20 13:40:57.000000000 +0100
@@ -9,7 +9,7 @@
E: maintainer-scripts: install-sgmlcatalog-deprecated postinst:98
E: maintainer-scripts: install-sgmlcatalog-deprecated postrm:46
E: maintainer-scripts: interpreter-without-predep control/config #!/usr/bin/python
-E: maintainer-scripts: maintainer-script-calls-init-script-directly prerm:54
+E: maintainer-scripts: maintainer-script-calls-init-script-directly prerm:55
E: maintainer-scripts: maintainer-script-does-not-check-for-existence-of-wm-menu-config postinst:31
E: maintainer-scripts: maintainer-script-modifies-inetd-conf postinst:91
E: maintainer-scripts: maintainer-script-modifies-inetd-conf postinst:92
@@ -64,6 +64,40 @@
W: maintainer-scripts: possible-bashism-in-maintainer-script postinst:20 'H[0]='
W: maintainer-scripts: possible-bashism-in-maintainer-script postinst:21 '${H[0]}'
W: maintainer-scripts: possible-bashism-in-maintainer-script postinst:23 '${H[@]}'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:102 ' echo "abc\nxyz"'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:103 ' echo 'xyz\rabc''
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:106 ' echo -e'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:107 ' echo -ne'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:108 ' echo -e'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:111 'foobar.() '
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:112 ' suspend '
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:114 ' caller '
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:115 ' complete '
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:116 ' compgen '
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:117 ' declare '
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:120 '.foobar() '
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:121 ' typeset '
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:122 ' disown '
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:123 ' builtin '
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:124 ' set -B'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:125 ' alias -p'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:126 ' unalias -a'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:131 'ulimit'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:132 'shopt'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:133 'type '
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:134 'time '
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:135 'dirs'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:136 ' <(tac a)'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:138 'pushd'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:140 'local foo='
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:141 'local -x'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:143 'popd'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:145 'readonly -f'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:147 '/dev/tcp'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:149 'export -x'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:153 'sh -D'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:154 'sh --foo'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:155 'sh +O'
W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:19 '[ "$2" == '
W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:23 'function foo( )'
W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:26 '&>'
@@ -71,7 +105,29 @@
W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:31 'trap "echo hi" EXIT HUP 3'
W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:33 '[['
W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:34 ' kill -HUP'
-W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:51 '${line:3:1}'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:52 '${line:3:1}'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:62 'read -x foo'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:63 'read -x'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:66 'read'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:68 'echo "a\\b"'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:69 'echo 'a\nb''
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:71 '${UID'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:72 '$EUID'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:73 '$SHLVL'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:74 '$DIRSTACK'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:75 '$SECONDS'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:77 '$BASH_FOO'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:78 '$SHELLOPTS'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:79 '$PIPESTATUS'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:81 '<<<'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:84 'VAR+='
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:87 ' echo -n -e'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:88 ' echo -e'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:89 ' echo -en'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:90 ' echo -ne'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:95 'ech.os() '
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:97 '>&bar'
+W: maintainer-scripts: possible-bashism-in-maintainer-script prerm:98 '>& bar'
W: maintainer-scripts: possibly-insecure-handling-of-tmp-files-in-maintainer-script postinst:50
W: maintainer-scripts: possibly-insecure-handling-of-tmp-files-in-maintainer-script postrm:39
W: maintainer-scripts: postinst-does-not-load-confmodule
@@ -79,5 +135,10 @@
W: maintainer-scripts: postrm-does-not-purge-debconf
W: maintainer-scripts: postrm-has-useless-call-to-ldconfig
W: maintainer-scripts: read-in-maintainer-script postinst:18
+W: maintainer-scripts: read-in-maintainer-script prerm:62
+W: maintainer-scripts: read-in-maintainer-script prerm:63
+W: maintainer-scripts: read-in-maintainer-script prerm:64
+W: maintainer-scripts: read-in-maintainer-script prerm:65
+W: maintainer-scripts: read-in-maintainer-script prerm:66
W: maintainer-scripts: start-stop-daemon-in-maintainer-script postinst:159
W: maintainer-scripts: update-alternatives-remove-called-in-postrm
Reply to: