Hello community, here is the log from the commit of package checkbashisms for openSUSE:Factory checked in at 2012-05-16 21:05:45 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/checkbashisms (Old) and /work/SRC/openSUSE:Factory/.checkbashisms.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "checkbashisms", Maintainer is "" Changes: -------- --- /work/SRC/openSUSE:Factory/checkbashisms/checkbashisms.changes 2012-02-21 12:16:03.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.checkbashisms.new/checkbashisms.changes 2012-05-16 21:05:47.000000000 +0200 @@ -1,0 +2,37 @@ +Wed May 16 11:04:46 UTC 2012 - g...@opensuse.org + +- update to current git version + - detect substr expansion with dynamic length + - allow stdin to be checked by accepting '-' as file name + - do not unconditionally swallow stdin + - detect the use of 'setvar' + - Update scripts to use GNU getopt-compatible option parsing + - add stdin support + - replace occurences of old FSF address with the FSF + recommendation what should be written inside of source files + - allow kill/trap XSI-isms unless --posix is given + - warn when EOF is reached unexpectedly + - avoid a false positive output redirection match + - detect the use of 'command' with options other than -p + - detect the use of the 'jobs' built-in + - detect the use of exponentiation + - fix multiple quotes-handling bugs + - checkabshisms: Fix support for indented heredoc delimiters + - fix some false positives when checking makefiles + - fix a false positive 'should be >word 2>&1' + - also handle 'ignore errors' in makefiles + - improve handling of line continuations + - allow SHELL to be prefixed with 'override' + - improve detection of n++-like arithmetic + - handle line continuations + - detect the ';;&' and ';&' case/esac operators + - detect the use of the 'coproc' built-in + - detect some printf-related bashisms + - detect use of $((n++)) (and similar variants) + - detect the use of [^] instead of [!] + - simplify all shell variables in makefiles + - simplify make variables as shell variables + - detect more Bash builtins -- readarray, mapfile, enable + - fix typo spotted by Dann Frazier + +------------------------------------------------------------------- Old: ---- checkbashisms-20100326git.tar.bz2 New: ---- checkbashisms-20120516git.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ checkbashisms.spec ++++++ --- /var/tmp/diff_new_pack.BqGYHR/_old 2012-05-16 21:05:48.000000000 +0200 +++ /var/tmp/diff_new_pack.BqGYHR/_new 2012-05-16 21:05:48.000000000 +0200 @@ -17,17 +17,17 @@ Name: checkbashisms -Version: 20100326git +Version: 20120516git Release: 0 Summary: Tool for Checking /bin/sh Scripts for Possible Bashisms License: GPL-2.0+ Group: Development/Tools/Other Url: http://git.debian.org/?p=devscripts/devscripts.git Requires: perl = %{perl_version} -Source: checkbashisms-20100326git.tar.bz2 +Source: checkbashisms-%{version}.tar.bz2 BuildRoot: %{_tmppath}/%{name}-%{version}-build -BuildArch: noarch BuildRequires: perl +BuildArch: noarch %description checkbashisms performs basic checks on /bin/sh shell scripts for the possible @@ -40,8 +40,8 @@ %build %install -install -D -m 0755 checkbashisms.pl %{buildroot}%{_bindir}/checkbashisms -install -D -m 0644 checkbashisms.1 %{buildroot}%{_mandir}/man1/checkbashisms.1 +install -D -p -m 0755 checkbashisms.pl %{buildroot}%{_bindir}/checkbashisms +install -D -p -m 0644 checkbashisms.1 %{buildroot}%{_mandir}/man1/checkbashisms.1 %files %defattr(-,root,root,-) ++++++ checkbashisms-20100326git.tar.bz2 -> checkbashisms-20120516git.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/checkbashisms-20100326git/checkbashisms.1 new/checkbashisms-20120516git/checkbashisms.1 --- old/checkbashisms-20100326git/checkbashisms.1 2010-03-26 11:46:04.000000000 +0100 +++ new/checkbashisms-20120516git/checkbashisms.1 2012-05-16 13:03:18.000000000 +0200 @@ -4,7 +4,7 @@ .SH SYNOPSIS \fBcheckbashisms\fR \fIscript\fR ... .br -\fBcheckbashisms \-\-help|\-\-version\fR +\fBcheckbashisms \-\-help\fR|\fB\-\-version\fR .SH DESCRIPTION \fBcheckbashisms\fR, based on one of the checks from the \fBlintian\fR system, performs basic checks on \fI/bin/sh\fR shell scripts for the @@ -12,13 +12,13 @@ scripts on the command line, and outputs warnings if possible bashisms are detected. .PP -Note that the definition of a bashism in this context roughly equates -to "a shell feature that is not required to be supported by POSIX"; this -means that some issues flagged may be permitted under optional sections +Note that the definition of a bashism in this context roughly equates +to "a shell feature that is not required to be supported by POSIX"; this +means that some issues flagged may be permitted under optional sections of POSIX, such as XSI or User Portability. .PP -In cases where POSIX and Debian Policy disagree, \fBcheckbashisms\fR by -default allows extensions permitted by Policy but may also provide +In cases where POSIX and Debian Policy disagree, \fBcheckbashisms\fR by +default allows extensions permitted by Policy but may also provide options for stricter checking. .SH OPTIONS .TP @@ -26,23 +26,23 @@ Show a summary of options. .TP .BR \-\-newline ", " \-n -Check for "echo \-n" usage (non POSIX but required by Debian Policy 10.4.) +Check for "\fBecho \-n\fR" usage (non POSIX but required by Debian Policy 10.4.) .TP .BR \-\-posix ", " \-p Check for issues which are non POSIX but required to be supported by Debian -Policy 10.4 (implies \-n). +Policy 10.4 (implies \fB\-n\fR). .TP .BR \-\-force ", " \-f -Force each script to be checked, even if it would normally not be (for -instance, it has a bash or non POSIX shell shebang or appears to be a +Force each script to be checked, even if it would normally not be (for +instance, it has a bash or non POSIX shell shebang or appears to be a shell wrapper). .TP .BR \-\-extra ", " \-x Highlight lines which, whilst they do not contain bashisms, may be useful in determining whether a particular issue is a false positive which may be ignored. -For example, the use of "$BASH_ENV" may be preceded by checking -whether "$BASH" is set. +For example, the use of "\fB$BASH_ENV\fR" may be preceded by checking +whether "\fB$BASH\fR" is set. .TP .BR \-\-version ", " \-v Show version and copyright information. @@ -61,5 +61,5 @@ .BR lintian (1). .SH AUTHOR \fBcheckbashisms\fR was originally written as a shell script by Yann Dirson -<dir...@debian.org> and rewritten in Perl with many more features by -Julian Gilbey <j...@debian.org>. +<\fidir...@debian.org\fR> and rewritten in Perl with many more features by +Julian Gilbey <\fi...@debian.org\fR>. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/checkbashisms-20100326git/checkbashisms.pl new/checkbashisms-20120516git/checkbashisms.pl --- old/checkbashisms-20100326git/checkbashisms.pl 2010-03-26 11:45:28.000000000 +0100 +++ new/checkbashisms-20120516git/checkbashisms.pl 2012-05-16 13:03:41.000000000 +0200 @@ -6,7 +6,7 @@ # Copyright (C) 2002 Josip Rodin # This version is # Copyright (C) 2003 Julian Gilbey -# +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -18,13 +18,11 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, you can find it on the World Wide -# Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free -# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, -# MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. use strict; -use Getopt::Long; +use Getopt::Long qw(:config gnu_getopt); +use File::Temp qw/tempfile/; sub init_hashes; @@ -50,6 +48,12 @@ my ($opt_echo, $opt_force, $opt_extra, $opt_posix); my ($opt_help, $opt_version); +my @filenames; + +# Detect if STDIN is a pipe +if (scalar(@ARGV) == 0 && (-p STDIN or -f STDIN)) { + push(@ARGV, '-'); +} ## ## handle command-line options @@ -80,31 +84,46 @@ foreach my $filename (@ARGV) { my $check_lines_count = -1; + my $display_filename = $filename; + + if ($filename eq '-') { + my $tmp_fh; + ($tmp_fh, $filename) = tempfile("chkbashisms_tmp.XXXX", TMPDIR => 1, UNLINK => 1); + while (my $line = <STDIN>) { + print $tmp_fh $line; + } + close($tmp_fh); + $display_filename = "(stdin)"; + } + if (!$opt_force) { $check_lines_count = script_is_evil_and_wrong($filename); } if ($check_lines_count == 0 or $check_lines_count == 1) { - warn "script $filename does not appear to be a /bin/sh script; skipping\n"; + warn "script $display_filename does not appear to be a /bin/sh script; skipping\n"; next; } if ($check_lines_count != -1) { - warn "script $filename appears to be a shell wrapper; only checking the first " + warn "script $display_filename appears to be a shell wrapper; only checking the first " . "$check_lines_count lines\n"; } unless (open C, '<', $filename) { - warn "cannot open script $filename for reading: $!\n"; + warn "cannot open script $display_filename for reading: $!\n"; $status |= 2; next; } my $cat_string = ""; + my $cat_indented = 0; my $quote_string = ""; my $last_continued = 0; my $continued = 0; my $found_rules = 0; + my $buffered_orig_line = ""; + my $buffered_line = ""; while (<C>) { next unless ($check_lines_count == -1 or $. <= $check_lines_count); @@ -123,18 +142,18 @@ next if $opt_force; if ($interpreter =~ m,/bash$,) { - warn "script $filename is already a bash script; skipping\n"; + warn "script $display_filename is already a bash script; skipping\n"; $status |= 2; last; # end this file } elsif ($interpreter !~ m,/(sh|posh)$,) { ### ksh/zsh? - warn "script $filename does not appear to be a /bin/sh script; skipping\n"; + warn "script $display_filename does not appear to be a /bin/sh script; skipping\n"; $status |= 2; last; } } else { - warn "script $filename does not appear to have a \#! interpreter line;\nyou may get strange results\n"; + warn "script $display_filename does not appear to have a \#! interpreter line;\nyou may get strange results\n"; } } @@ -153,7 +172,10 @@ # will be treated as part of the comment. # s/^(?:.*?[^\\])?$quote_string(.*)$/$1/ if $quote_string ne ""; - next if m,^\s*\#,; # skip comment lines + # skip comment lines + if (m,^\s*\#, && $quote_string eq '' && $buffered_line eq '' && $cat_string eq '') { + next; + } # Remove quoted strings so we can more easily ignore comments # inside them @@ -170,6 +192,21 @@ $_ = $orig_line; } + # Handle line continuation + if (!$makefile && $cat_string eq '' && m/\\$/) { + chop; + $buffered_line .= $_; + $buffered_orig_line .= $orig_line . "\n"; + next; + } + + if ($buffered_line ne '') { + $_ = $buffered_line . $_; + $orig_line = $buffered_orig_line . $orig_line; + $buffered_line =''; + $buffered_orig_line =''; + } + if ($makefile) { $last_continued = $continued; if (/[^\\]\\$/) { @@ -183,16 +220,19 @@ if (/^[\w%-]+:+\s.*?;?(.*)$/ and !($last_continued and !$found_rules)) { $found_rules = 1; $_ = $1 if $1; - } + } - last if m%^(export )?SHELL\s*:?=\s*(/bin/)?bash\s*%; + last if m%^\s*(override\s|export\s)?\s*SHELL\s*:?=\s*(/bin/)?bash\s*%; + # Remove "simple" target names + s/^[\w%.-]+(?:\s+[\w%.-]+)*::?//; s/^\t//; - s/(\$){2}/$1/; - s/^[\s\t]*@//; + s/(?<!\$)\$\((\w+)\)/\${$1}/g; + s/(\$){2}/$1/g; + s/^[\s\t]*[@-]{1,2}//; } - if ($cat_string ne "" and m/^\Q$cat_string\E$/) { + if ($cat_string ne "" && (m/^\Q$cat_string\E$/ || ($cat_indented && m/^\t*\Q$cat_string\E$/))) { $cat_string = ""; next; } @@ -257,7 +297,7 @@ my $otherquote = ($quote eq "\"" ? "\'" : "\""); # Remove balanced quotes and their content - $templine =~ s/(^|[^\\\"](?:\\\\)*)\'(?:\\.|[^\\\'])+\'/$1/g; + $templine =~ s/(^|[^\\\"](?:\\\\)*)\'[^\']*\'/$1/g; $templine =~ s/(^|[^\\\'](?:\\\\)*)\"(?:\\.|[^\\\"])+\"/$1/g; # Don't flag quotes that are themselves quoted @@ -265,6 +305,8 @@ $templine =~ s/$otherquote.*?$quote.*?$otherquote//g; # "\"" $templine =~ s/(^|[^\\])$quote\\$quote$quote/$1/g; + # \' or \" + $templine =~ s/\\[\'\"]//g; my $count = () = $templine =~ /(^|(?!\\))$quote/g; # If there's an odd number of non-escaped @@ -291,7 +333,7 @@ $found = 1; $match = $1; $explanation = "sourced script with arguments"; - output_explanation($filename, $orig_line, $explanation); + output_explanation($display_filename, $orig_line, $explanation); } } @@ -307,7 +349,7 @@ $found = 1; $match = $1; $explanation = $expl; - output_explanation($filename, $orig_line, $explanation); + output_explanation($display_filename, $orig_line, $explanation); } } @@ -315,9 +357,9 @@ if ($line =~ m/(.*)($re)/){ my $count = () = $1 =~ /(^|[^\\])\'/g; if( $count % 2 == 0 ) { - output_explanation($filename, $orig_line, q<$'...' should be "$(printf '...')">); + output_explanation($display_filename, $orig_line, q<$'...' should be "$(printf '...')">); } - } + } # $cat_line contains the version of the line we'll check # for heredoc delimiters later. Initially, remove any @@ -341,16 +383,16 @@ if ($line =~ m/(.*)($re)/){ my $count = () = $1 =~ /(^|[^\\])\"/g; if( $count % 2 == 0 ) { - output_explanation($filename, $orig_line, q<$"foo" should be eval_gettext "foo">); + output_explanation($display_filename, $orig_line, q<$"foo" should be eval_gettext "foo">); } - } + } while (my ($re,$expl) = each %string_bashisms) { if ($line =~ m/($re)/) { $found = 1; $match = $1; $explanation = $expl; - output_explanation($filename, $orig_line, $explanation); + output_explanation($display_filename, $orig_line, $explanation); } } @@ -363,19 +405,27 @@ $found = 1; $match = $1; $explanation = $expl; - output_explanation($filename, $orig_line, $explanation); + output_explanation($display_filename, $orig_line, $explanation); } } # Only look for the beginning of a heredoc here, after we've # stripped out quoted material, to avoid false positives. - if ($cat_line =~ m/(?:^|[^<])\<\<\-?\s*(?:[\\]?(\w+)|[\'\"](.*?)[\'\"])/) { - $cat_string = $1; - $cat_string = $2 if not defined $cat_string; + if ($cat_line =~ m/(?:^|[^<])\<\<(\-?)\s*(?:[\\]?(\w+)|[\'\"](.*?)[\'\"])/) { + $cat_indented = ($1 && $1 eq '-')? 1 : 0; + $cat_string = $2; + $cat_string = $3 if not defined $cat_string; } } } + warn "error: $filename: Unterminated heredoc found, EOF reached. Wanted: <$cat_string>\n" + if ($cat_string ne ''); + warn "error: $filename: Unterminated quoted string found, EOF reached. Wanted: <$quote_string>\n" + if ($quote_string ne ''); + warn "error: $filename: EOF reached while on line continuation.\n" + if ($buffered_line ne ''); + close C; } @@ -423,8 +473,8 @@ # Match expressions of the form '${1+$@}', '${1:+"$@"', # '"${1+$@', "$@", etc where the quotes (before the dollar # sign(s)) are optional and the second (or only if the $1 - # clause is omitted) parameter may be $@ or $*. - # + # clause is omitted) parameter may be $@ or $*. + # # Finally the whole subexpression may be omitted for scripts # which do not pass on their parameters (i.e. after re-execing # they take their parameters (and potentially data) from stdin @@ -481,43 +531,52 @@ qr'(?<![\$\(])\(\(.*\)\)' => q<'((' should be '$(('>, qr'(?:^|\s+)(\[|test)\s+-a' => q<test with unary -a (should be -e)>, qr'\&>' => q<should be \>word 2\>&1>, - qr'(<\&|>\&)\s*((-|\d+)[^\s;|)`&\\\\]|[^-\d\s]+)' => + qr'(<\&|>\&)\s*((-|\d+)[^\s;|)}`&\\\\]|[^-\d\s]+(?<!\$)(?!\d))' => q<should be \>word 2\>&1>, - $LEADIN . qr'kill\s+-[^sl]\w*' => q<kill -[0-9] or -[A-Z]>, - $LEADIN . qr'trap\s+["\']?.*["\']?\s+.*[1-9]' => q<trap with signal numbers>, qr'\[\[(?!:)' => q<alternative test command ([[ foo ]] should be [ foo ])>, qr'/dev/(tcp|udp)' => q</dev/(tcp|udp)>, - $LEADIN . qr'suspend\s' => q<suspend>, + $LEADIN . qr'builtin\s' => q<builtin>, $LEADIN . qr'caller\s' => q<caller>, - $LEADIN . qr'complete\s' => q<complete>, $LEADIN . qr'compgen\s' => q<compgen>, + $LEADIN . qr'complete\s' => q<complete>, $LEADIN . qr'declare\s' => q<declare>, - $LEADIN . qr'typeset\s' => q<typeset>, + $LEADIN . qr'dirs(\s|\Z)' => q<dirs>, $LEADIN . qr'disown\s' => q<disown>, - $LEADIN . qr'builtin\s' => q<builtin>, + $LEADIN . qr'enable\s' => q<enable>, + $LEADIN . qr'mapfile\s' => q<mapfile>, + $LEADIN . qr'readarray\s' => q<readarray>, + $LEADIN . qr'shopt(\s|\Z)' => q<shopt>, + $LEADIN . qr'suspend\s' => q<suspend>, + $LEADIN . qr'time\s' => q<time>, + $LEADIN . qr'type\s' => q<type>, + $LEADIN . qr'typeset\s' => q<typeset>, + $LEADIN . qr'ulimit(\s|\Z)' => q<ulimit>, $LEADIN . qr'set\s+-[BHT]+' => q<set -[BHT]>, $LEADIN . qr'alias\s+-p' => q<alias -p>, $LEADIN . qr'unalias\s+-a' => q<unalias -a>, $LEADIN . qr'local\s+-[a-zA-Z]+' => q<local -opt>, qr'(?:^|\s+)\s*\(?\w*[^\(\w\s]+\S*?\s*\(\)\s*([\{|\(]|\Z)' => q<function names should only contain [a-z0-9_]>, - $LEADIN . qr'(push|pop)d(\s|\Z)' => q<(push|pod)d>, + $LEADIN . qr'(push|pop)d(\s|\Z)' => q<(push|pop)d>, $LEADIN . qr'export\s+-[^p]' => q<export only takes -p as an option>, - $LEADIN . qr'ulimit(\s|\Z)' => q<ulimit>, - $LEADIN . qr'shopt(\s|\Z)' => q<shopt>, - $LEADIN . qr'type\s' => q<type>, - $LEADIN . qr'time\s' => q<time>, - $LEADIN . qr'dirs(\s|\Z)' => q<dirs>, qr'(?:^|\s+)[<>]\(.*?\)' => q<\<() process substituion>, $LEADIN . qr'readonly\s+-[af]' => q<readonly -[af]>, $LEADIN . qr'(sh|\$\{?SHELL\}?) -[rD]' => q<sh -[rD]>, $LEADIN . qr'(sh|\$\{?SHELL\}?) --\w+' => q<sh --long-option>, $LEADIN . qr'(sh|\$\{?SHELL\}?) [-+]O' => q<sh [-+]O>, + qr'\[\^[^]]+\]' => q<[^] should be [!]>, + $LEADIN . qr'printf\s+-v' => q<'printf -v var ...' should be var='$(printf ...)'>, + $LEADIN . qr'coproc\s' => q<coproc>, + qr';;?&' => q<;;& and ;& special case operators>, + $LEADIN . qr'jobs\s' => q<jobs>, +# $LEADIN . qr'jobs\s+-[^lp]\s' => q<'jobs' with option other than -l or -p>, + $LEADIN . qr'command\s+-[^p]\s' => q<'command' with option other than -p>, + $LEADIN . qr'setvar\s' => q<setvar 'foo' 'bar' should be eval \$'foo' 'bar'>, ); %string_bashisms = ( qr'\$\[[^][]+\]' => q<'$[' should be '$(('>, - qr'\$\{\w+\:\d+(?::\d+)?\}' => q<${foo:3[:1]}>, + qr'\$\{\w+\:(?:\d+|\$\{?\w+\}?)+(?::(?:\d+|\$\{?\w+\}?)+)?\}' => q<${foo:3[:1]}>, qr'\$\{!\w+[\@*]\}' => q<${!prefix[*|@]>, qr'\$\{!\w+\}' => q<${!name}>, qr'\$\{\w+(/.+?){1,2}\}' => q<${parm/?/pat[/str]}>, @@ -535,6 +594,12 @@ qr'\$\{?SHLVL\}?\b' => q<$SHLVL>, qr'<<<' => q<\<\<\< here string>, $LEADIN . qr'echo\s+(?:-[^e\s]+\s+)?\"[^\"]*(\\[abcEfnrtv0])+.*?[\"]' => q<unsafe echo with backslash>, + qr'\$\(\([\s\w$*/+-]*\w\+\+.*?\)\)' => q<'$((n++))' should be '$n; $((n=n+1))'>, + qr'\$\(\([\s\w$*/+-]*\+\+\w.*?\)\)' => q<'$((++n))' should be '$((n=n+1))'>, + qr'\$\(\([\s\w$*/+-]*\w\-\-.*?\)\)' => q<'$((n--))' should be '$n; $((n=n-1))'>, + qr'\$\(\([\s\w$*/+-]*\-\-\w.*?\)\)' => q<'$((--n))' should be '$((n=n-1))'>, + qr'\$\(\([\s\w$*/+-]*\*\*.*?\)\)' => q<exponentiation is not POSIX>, + $LEADIN . qr'printf\s["\'][^"\']+?%[qb].+?["\']' => q<printf %q|%b>, ); %singlequote_bashisms = ( @@ -551,6 +616,8 @@ $bashisms{$LEADIN . qr'local\s+\w+='} = q<local foo=bar>; $bashisms{$LEADIN . qr'local\s+\w+\s+\w+'} = q<local x y>; $bashisms{$LEADIN . qr'((?:test|\[)\s+.+\s-[ao])\s'} = q<test -a/-o>; + $bashisms{$LEADIN . qr'kill\s+-[^sl]\w*'} = q<kill -[0-9] or -[A-Z]>; + $bashisms{$LEADIN . qr'trap\s+["\']?.*["\']?\s+.*[1-9]'} = q<trap with signal numbers>; } if ($makefile) { -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org