[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[SCM] Debian package checker branch, master, updated. b75cbcef5c417b9a540ecf259f443eac9b272b58



The following commit has been merged in the master branch:
commit b75cbcef5c417b9a540ecf259f443eac9b272b58
Author: Adam D. Barratt <adam@adam-barratt.org.uk>
Date:   Fri Jun 20 20:19:54 2008 +0100

    [ADB] Update bashism regexes to add new checks, improve performance and reduce false positives.

diff --git a/checks/scripts b/checks/scripts
index 41ff808..0fe348b 100644
--- a/checks/scripts
+++ b/checks/scripts
@@ -543,41 +543,86 @@ while (<SCRIPTS>) {
 	    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 @@ while (<SCRIPTS>) {
 		    }
 		}
 
+		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
diff --git a/debian/changelog b/debian/changelog
index 3851965..53bec99 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -20,6 +20,8 @@ lintian (1.24.2) unstable; urgency=low
     + [FL] Improve heredoc detection.  Patch by Adam D. Barratt.
     + [FL] Improve script_is_evil_and_wrong() to catch more scripts.
       Patch by Adam D. Barratt.
+    + [ADB] Update bashism regexes to add new checks, improve performance
+      and reduce false positives.
   * checks/watch-file{,.desc}:
      + [FL] Check for more Debian specific strings in version
        number.  Issue an info tag if the watch file uses
diff --git a/testset/maintainer-scripts/debian/prerm b/testset/maintainer-scripts/debian/prerm
index 368f9c4..7567a79 100644
--- a/testset/maintainer-scripts/debian/prerm
+++ b/testset/maintainer-scripts/debian/prerm
@@ -43,6 +43,7 @@ update-rc.d foo remove
 
 # 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 @@ echo "${line:3:1}"
 
 # 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
diff --git a/testset/tags.maintainer-scripts b/testset/tags.maintainer-scripts
index 6c34acb..1788ad0 100644
--- a/testset/tags.maintainer-scripts
+++ b/testset/tags.maintainer-scripts
@@ -9,7 +9,7 @@ E: maintainer-scripts: init.d-script-not-included-in-package /etc/init.d/foo
 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:18 'read'
 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:29 'source $F
 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: postinst-should-not-set-usr-doc-link
 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

-- 
Debian package checker


Reply to: