]> ruderich.org/simon Gitweb - blhc/blhc.git/blobdiff - bin/blhc
Use index() in a few more places.
[blhc/blhc.git] / bin / blhc
index 1d35e0ba489008f5c2eee8bab499256e0445d2b3..57ea0005df4f17712ef3e775d0e6ba8f1a829f12 100755 (executable)
--- a/bin/blhc
+++ b/bin/blhc
@@ -24,7 +24,7 @@ use warnings;
 use Getopt::Long ();
 use Text::ParseWords ();
 
 use Getopt::Long ();
 use Text::ParseWords ();
 
-our $VERSION = '0.01';
+our $VERSION = '0.03';
 
 
 # CONSTANTS/VARIABLES
 
 
 # CONSTANTS/VARIABLES
@@ -42,8 +42,12 @@ my $cc_regex_full = qr/
     (?:[a-z0-9_]+-(?:linux-|kfreebsd-)?gnu(?:eabi|eabihf)?-)?
     $cc_regex
     /x;
     (?:[a-z0-9_]+-(?:linux-|kfreebsd-)?gnu(?:eabi|eabihf)?-)?
     $cc_regex
     /x;
+# Regex to check if a line contains a compiler command.
+my $cc_regex_normal = qr/
+    \b$cc_regex(?:\s|\\)
+    /x;
 # Regex to catch (GCC) compiler warnings.
 # Regex to catch (GCC) compiler warnings.
-my $warning_regex = qr/^(.+?):([0-9]+):[0-9]+: warning: (.+?) \[(.+?)\]$/;
+my $warning_regex = qr/^(.+?):(\d+):\d+: warning: (.+?) \[(.+?)\]$/;
 
 # List of source file extensions which require preprocessing.
 my @source_preprocess_compile_cpp = (
 
 # List of source file extensions which require preprocessing.
 my @source_preprocess_compile_cpp = (
@@ -102,10 +106,22 @@ my @header_preprocess = (
     # C++
     qw( hh H hp hxx hpp HPP h++ tcc ),
 );
     # C++
     qw( hh H hp hxx hpp HPP h++ tcc ),
 );
+# Object files.
+my @object = (
+    # Normal object files.
+    qw ( o ),
+    # Libtool object files.
+    qw ( lo la ),
+    # Dynamic libraries. bzip2 uses .sho.
+    qw ( so sho ),
+    # Static libraries.
+    qw ( a ),
+);
 
 # Hashes for fast extensions lookup to check if a file falls in one of these
 # categories.
 my %extensions_no_preprocess = map { $_ => 1 } (
 
 # Hashes for fast extensions lookup to check if a file falls in one of these
 # categories.
 my %extensions_no_preprocess = map { $_ => 1 } (
+    # There's no @header_no_preprocess.
     @source_no_preprocess,
 );
 my %extensions_preprocess = map { $_ => 1 } (
     @source_no_preprocess,
 );
 my %extensions_preprocess = map { $_ => 1 } (
@@ -128,10 +144,14 @@ my %extensions_compile_cpp = map { $_ => 1 } (
     @source_preprocess_compile_cpp,
     @source_no_preprocess_compile_cpp,
 );
     @source_preprocess_compile_cpp,
     @source_no_preprocess_compile_cpp,
 );
+my %extensions_object = map { $_ => 1 } (
+    @object,
+);
 my %extension = map { $_ => 1 } (
     @source_no_preprocess,
     @header_preprocess,
     @source_preprocess,
 my %extension = map { $_ => 1 } (
     @source_no_preprocess,
     @header_preprocess,
     @source_preprocess,
+    @object,
 );
 
 # Regexp to match file extensions.
 );
 
 # Regexp to match file extensions.
@@ -153,8 +173,7 @@ my @def_cflags = (
 );
 my @def_cflags_format = (
     '-Wformat',
 );
 my @def_cflags_format = (
     '-Wformat',
-    '-Wformat-security',
-    '-Werror=format-security',
+    '-Werror=format-security', # implies -Wformat-security
 );
 my @def_cflags_fortify = (
     # fortify needs at least -O1, but -O2 is recommended anyway
 );
 my @def_cflags_fortify = (
     # fortify needs at least -O1, but -O2 is recommended anyway
@@ -172,7 +191,14 @@ my @def_cxxflags = (
 # @def_cxxflags_* is the same as @def_cflags_*.
 my @def_cppflags = ();
 my @def_cppflags_fortify = (
 # @def_cxxflags_* is the same as @def_cflags_*.
 my @def_cppflags = ();
 my @def_cppflags_fortify = (
-    '-D_FORTIFY_SOURCE=2',
+    '-D_FORTIFY_SOURCE=2', # must be first, see cppflags_fortify_broken()
+    # If you add another flag fix hack below (search for "Hack to fix").
+);
+my @def_cppflags_fortify_bad = (
+    # These flags may overwrite -D_FORTIFY_SOURCE=2.
+    '-U_FORTIFY_SOURCE',
+    '-D_FORTIFY_SOURCE=0',
+    '-D_FORTIFY_SOURCE=1',
 );
 my @def_ldflags = ();
 my @def_ldflags_relro = (
 );
 my @def_ldflags = ();
 my @def_ldflags_relro = (
@@ -190,7 +216,7 @@ my @def_ldflags_pic = (
     '-fpic',
     '-shared',
 );
     '-fpic',
     '-shared',
 );
-# References to all flags checked by the parser.
+# References to all flags checked by the flag checker.
 my @flag_refs = (
     \@def_cflags,
     \@def_cflags_format,
 my @flag_refs = (
     \@def_cflags,
     \@def_cflags_format,
@@ -203,11 +229,12 @@ my @flag_refs = (
     \@def_ldflags,
     \@def_ldflags_relro,
     \@def_ldflags_bindnow,
     \@def_ldflags,
     \@def_ldflags_relro,
     \@def_ldflags_bindnow,
+    \@def_ldflags_pie,
 );
 # References to all used flags.
 my @flag_refs_all = (
     @flag_refs,
 );
 # References to all used flags.
 my @flag_refs_all = (
     @flag_refs,
-    \@def_ldflags_pie,
+    \@def_cppflags_fortify_bad,
     \@def_ldflags_pic,
 );
 # Renaming rules for the output so the regex parts are not visible. Also
     \@def_ldflags_pic,
 );
 # Renaming rules for the output so the regex parts are not visible. Also
@@ -227,6 +254,14 @@ my %exit_code = (
     invalid_cmake        => 1 << 5,
 );
 
     invalid_cmake        => 1 << 5,
 );
 
+my %buildd_tag = (
+    no_compiler_commands => 'I-no-compiler-commands',
+    non_verbose_build    => 'W-compiler-flags-hidden',
+    flags_missing        => 'W-dpkg-buildflags-missing',
+    hardening_wrapper    => 'I-hardening-wrapper-used',
+    invalid_cmake        => 'I-invalid-cmake-used',
+);
+
 # Statistics of missing flags and non-verbose build commands. Used for
 # $option_buildd.
 my %statistics = (
 # Statistics of missing flags and non-verbose build commands. Used for
 # $option_buildd.
 my %statistics = (
@@ -257,14 +292,14 @@ sub error_flags {
         } @{$missing_flags_ref};
 
     my $flags = join ' ', @missing_flags;
         } @{$missing_flags_ref};
 
     my $flags = join ' ', @missing_flags;
-    printf "%s (%s)%s %s",
+    printf '%s (%s)%s %s',
            error_color($message, 'red'), $flags, error_color(':', 'yellow'),
            $line;
 }
 sub error_non_verbose_build {
     my ($line) = @_;
 
            error_color($message, 'red'), $flags, error_color(':', 'yellow'),
            $line;
 }
 sub error_non_verbose_build {
     my ($line) = @_;
 
-    printf "%s%s %s",
+    printf '%s%s %s',
            error_color('NONVERBOSE BUILD', 'red'),
            error_color(':', 'yellow'),
            $line;
            error_color('NONVERBOSE BUILD', 'red'),
            error_color(':', 'yellow'),
            $line;
@@ -318,6 +353,22 @@ sub all_flags_used {
     return 0;
 }
 
     return 0;
 }
 
+sub cppflags_fortify_broken {
+    my ($line, $missing_flags) = @_;
+
+    # This doesn't take the position into account, but is a simple solution.
+    # And if the build system tries to force -D_FORTIFY_SOURCE=0/1, something
+    # is wrong anyway.
+
+    if (any_flags_used($line, @def_cppflags_fortify_bad)) {
+        # $def_cppflags_fortify[0] must be -D_FORTIFY_SOURCE=2!
+        push @{$missing_flags}, $def_cppflags_fortify[0];
+        return 1;
+    }
+
+    return 0;
+}
+
 # Modifies $missing_flags_ref array.
 sub pic_pie_conflict {
     my ($line, $pie, $missing_flags_ref, @flags_pie) = @_;
 # Modifies $missing_flags_ref array.
 sub pic_pie_conflict {
     my ($line, $pie, $missing_flags_ref, @flags_pie) = @_;
@@ -343,10 +394,10 @@ sub pic_pie_conflict {
 sub is_non_verbose_build {
     my ($line, $next_line, $skip_ref) = @_;
 
 sub is_non_verbose_build {
     my ($line, $next_line, $skip_ref) = @_;
 
-    if (not ($line =~ /^checking if you want to see long compiling messages\.\.\. no/
+    if (not (index($line, 'checking if you want to see long compiling messages... no') == 0
                 or $line =~ /^\s*\[?(?:CC|CCLD|C\+\+|CXX|CXXLD|LD|LINK)\]?\s+(.+?)$/
                 or $line =~ /^\s*\[?(?:CC|CCLD|C\+\+|CXX|CXXLD|LD|LINK)\]?\s+(.+?)$/
-                or $line =~ /^\s*(?:C|c)ompiling\s+(.+?)(?:\.\.\.)?$/
-                or $line =~ /^\s*(?:B|b)uilding (?:program|shared library)\s+(.+?)$/
+                or $line =~ /^\s*[Cc]ompiling\s+(.+?)(?:\.\.\.)?$/
+                or $line =~ /^\s*[Bb]uilding (?:program|shared library)\s+(.+?)$/
                 or $line =~ /^\s*\[[\d ]+%\] Building (?:C|CXX) object (.+?)$/)) {
         return 0;
     }
                 or $line =~ /^\s*\[[\d ]+%\] Building (?:C|CXX) object (.+?)$/)) {
         return 0;
     }
@@ -356,7 +407,7 @@ sub is_non_verbose_build {
     # C++ compiler setting.
     return 0 if $line =~ /^\s*C\+\+.+?:\s+(?:yes|no)\s*$/;
     # "Compiling" with no file name.
     # C++ compiler setting.
     return 0 if $line =~ /^\s*C\+\+.+?:\s+(?:yes|no)\s*$/;
     # "Compiling" with no file name.
-    if ($line =~ /^\s*(?:C|c)ompiling\s+(.+?)(?:\.\.\.)?$/) {
+    if ($line =~ /^\s*[Cc]ompiling\s+(.+?)(?:\.\.\.)?$/) {
         # $file_extension_regex may need spaces around the filename.
         return 0 if not " $1 " =~ /$file_extension_regex/o;
     }
         # $file_extension_regex may need spaces around the filename.
         return 0 if not " $1 " =~ /$file_extension_regex/o;
     }
@@ -378,7 +429,7 @@ sub is_non_verbose_build {
         $file =~ m{/([^/\s]+)$};
         $file = $1;
 
         $file =~ m{/([^/\s]+)$};
         $file = $1;
 
-        if ($next_line =~ /\Q$file\E/ and $next_line =~ /$cc_regex/o) {
+        if (index($next_line, $file) != -1 and $next_line =~ /$cc_regex/o) {
             # We still have to skip the current line as it doesn't contain any
             # compiler commands.
             ${$skip_ref} = 1;
             # We still have to skip the current line as it doesn't contain any
             # compiler commands.
             ${$skip_ref} = 1;
@@ -389,6 +440,21 @@ sub is_non_verbose_build {
     return 1;
 }
 
     return 1;
 }
 
+sub remove_flags {
+    my ($flag_refs_ref, $flag_renames_ref, @flags) = @_;
+
+    my %removes = map { $_ => 1 } @flags;
+    foreach my $flags (@{$flag_refs_ref}) {
+        @{$flags} = grep {
+            # Flag found as string.
+            not exists $removes{$_}
+            # Flag found as string representation of regexp.
+                and (not defined $flag_renames_ref->{$_}
+                        or not exists $removes{$flag_renames_ref->{$_}})
+        } @{$flags};
+    }
+}
+
 sub compile_flag_regexp {
     my ($flag_renames_ref, @flags) = @_;
 
 sub compile_flag_regexp {
     my ($flag_renames_ref, @flags) = @_;
 
@@ -424,32 +490,37 @@ sub extension_found {
 # MAIN
 
 # Parse command line arguments.
 # MAIN
 
 # Parse command line arguments.
-my $option_help        = 0;
-my $option_version     = 0;
-my $option_pie         = 0;
-my $option_bindnow     = 0;
-my @option_ignore_flag = ();
-my @option_ignore_line = ();
-my $option_all         = 0;
-my $option_arch        = undef;
-my $option_buildd      = 0;
-   $option_color       = 0;
+my $option_help             = 0;
+my $option_version          = 0;
+my $option_pie              = 0;
+my $option_bindnow          = 0;
+my @option_ignore_arch      = ();
+my @option_ignore_flag      = ();
+my @option_ignore_arch_flag = ();
+my @option_ignore_line      = ();
+my @option_ignore_arch_line = ();
+my $option_all              = 0;
+my $option_arch             = undef;
+my $option_buildd           = 0;
+   $option_color            = 0;
 if (not Getopt::Long::GetOptions(
 if (not Getopt::Long::GetOptions(
-            'help|h|?'      => \$option_help,
-            'version'       => \$option_version,
+            'help|h|?'           => \$option_help,
+            'version'            => \$option_version,
             # Hardening options.
             # Hardening options.
-            'pie'           => \$option_pie,
-            'bindnow'       => \$option_bindnow,
-            'all'           => \$option_all,
+            'pie'                => \$option_pie,
+            'bindnow'            => \$option_bindnow,
+            'all'                => \$option_all,
             # Ignore.
             # Ignore.
-            'ignore-flag=s' => \@option_ignore_flag,
-            'ignore-line=s' => \@option_ignore_line,
+            'ignore-arch=s'      => \@option_ignore_arch,
+            'ignore-flag=s'      => \@option_ignore_flag,
+            'ignore-arch-flag=s' => \@option_ignore_arch_flag,
+            'ignore-line=s'      => \@option_ignore_line,
+            'ignore-arch-line=s' => \@option_ignore_arch_line,
             # Misc.
             # Misc.
-            'color'         => \$option_color,
-            'arch=s'        => \$option_arch,
-            'buildd'        => \$option_buildd,
-        )
-        or scalar @ARGV == 0) {
+            'color'              => \$option_color,
+            'arch=s'             => \$option_arch,
+            'buildd'             => \$option_buildd,
+        )) {
     require Pod::Usage;
     Pod::Usage::pod2usage(2);
 }
     require Pod::Usage;
     Pod::Usage::pod2usage(2);
 }
@@ -476,6 +547,12 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
     exit 0;
 }
 
     exit 0;
 }
 
+# Arguments missing.
+if (scalar @ARGV == 0) {
+    require Pod::Usage;
+    Pod::Usage::pod2usage(2);
+}
+
 # Don't load Term::ANSIColor in buildd mode because Term::ANSIColor is not
 # installed on Debian's buildds.
 if (not $option_buildd) {
 # Don't load Term::ANSIColor in buildd mode because Term::ANSIColor is not
 # installed on Debian's buildds.
 if (not $option_buildd) {
@@ -487,17 +564,27 @@ if ($option_all) {
     $option_bindnow = 1;
 }
 
     $option_bindnow = 1;
 }
 
+# Precompiled ignores for faster lookup.
+my %option_ignore_arch_flag = ();
+my %option_ignore_arch_line = ();
+
 # Strip flags which should be ignored.
 if (scalar @option_ignore_flag > 0) {
 # Strip flags which should be ignored.
 if (scalar @option_ignore_flag > 0) {
-    my %ignores = map { $_ => 1 } @option_ignore_flag;
-    foreach my $flags (@flag_refs) {
-        @{$flags} = grep {
-            # Flag found as string.
-            not exists $ignores{$_}
-            # Flag found as string representation of regexp.
-                and (not defined $flag_renames{$_}
-                        or not exists $ignores{$flag_renames{$_}})
-            } @{$flags};
+    remove_flags(\@flag_refs, \%flag_renames, @option_ignore_flag);
+}
+# Same for arch specific ignore flags, but only prepare here.
+if (scalar @option_ignore_arch_flag > 0) {
+    foreach my $ignore (@option_ignore_arch_flag) {
+        my ($ignore_arch, $ignore_flag) = split /:/, $ignore, 2;
+
+        if (not $ignore_arch or not $ignore_flag) {
+            printf STDERR 'Value "%s" invalid for option ignore-arch-flag '
+                        . '("arch:flag" expected)' . "\n", $ignore;
+            require Pod::Usage;
+            Pod::Usage::pod2usage(2);
+        }
+
+        push @{$option_ignore_arch_flag{$ignore_arch}}, $ignore_flag;
     }
 }
 
     }
 }
 
@@ -511,6 +598,21 @@ foreach my $flags (@flag_refs_all) {
 foreach my $ignore (@option_ignore_line) {
     $ignore = qr/^$ignore$/;
 }
 foreach my $ignore (@option_ignore_line) {
     $ignore = qr/^$ignore$/;
 }
+# Same for arch specific ignore lines.
+if (scalar @option_ignore_arch_line > 0) {
+    foreach my $ignore (@option_ignore_arch_line) {
+        my ($ignore_arch, $ignore_line) = split /:/, $ignore, 2;
+
+        if (not $ignore_arch or not $ignore_line) {
+            printf STDERR 'Value "%s" invalid for option ignore-arch-line '
+                        . '("arch:line" expected)' . "\n", $ignore;
+            require Pod::Usage;
+            Pod::Usage::pod2usage(2);
+        }
+
+        push @{$option_ignore_arch_line{$ignore_arch}}, qr/^$ignore_line$/;
+    }
+}
 
 # Final exit code.
 my $exit = 0;
 
 # Final exit code.
 my $exit = 0;
@@ -519,7 +621,9 @@ FILE:
 foreach my $file (@ARGV) {
     print "checking '$file'...\n" if scalar @ARGV > 1;
 
 foreach my $file (@ARGV) {
     print "checking '$file'...\n" if scalar @ARGV > 1;
 
-    open my $fh, '<', $file or die "$!: $file";
+    -f $file or die "No such file: $file";
+
+    open my $fh, '<', $file or die $!;
 
     # Architecture of this file.
     my $arch = $option_arch;
 
     # Architecture of this file.
     my $arch = $option_arch;
@@ -533,15 +637,24 @@ foreach my $file (@ARGV) {
     my $harden_pie     = $option_pie;     # defaults to 0
 
     while (my $line = <$fh>) {
     my $harden_pie     = $option_pie;     # defaults to 0
 
     while (my $line = <$fh>) {
+        # Detect architecture automatically unless overridden. For buildd logs
+        # only, doesn't use the dpkg-buildpackage header. Necessary to ignore
+        # build logs which aren't built (wrong architecture, build error,
+        # etc.).
+        if (not $arch and index($line, 'Architecture: ') == 0) {
+            $arch = substr $line, 14, -1; # -1 to ignore '\n' at the end
+        }
+
         # dpkg-buildflags only provides hardening flags since 1.16.1, don't
         # check for hardening flags in buildd mode if an older dpkg-dev is
         # used. Default flags (-g -O2) are still checked.
         #
         # Packages which were built before 1.16.1 but used their own hardening
         # flags are not checked.
         # dpkg-buildflags only provides hardening flags since 1.16.1, don't
         # check for hardening flags in buildd mode if an older dpkg-dev is
         # used. Default flags (-g -O2) are still checked.
         #
         # Packages which were built before 1.16.1 but used their own hardening
         # flags are not checked.
-        if ($option_buildd and $line =~ /^Toolchain package versions: /) {
+        if ($option_buildd
+                and index($line, 'Toolchain package versions: ') == 0) {
             require Dpkg::Version;
             require Dpkg::Version;
-            if ($line !~ /\bdpkg-dev_(\S+)/
+            if (not $line =~ /\bdpkg-dev_(\S+)/
                     or Dpkg::Version::version_compare($1, '1.16.1') < 0) {
                 $harden_format  = 0;
                 $harden_fortify = 0;
                     or Dpkg::Version::version_compare($1, '1.16.1') < 0) {
                 $harden_format  = 0;
                 $harden_fortify = 0;
@@ -558,36 +671,41 @@ foreach my $file (@ARGV) {
         # enabled, even though they may be not correctly set and are missing
         # when build with later CMake versions. Thanks to Aron Xu for letting
         # me know.
         # enabled, even though they may be not correctly set and are missing
         # when build with later CMake versions. Thanks to Aron Xu for letting
         # me know.
-        if ($line =~ /^Package versions: /
+        if (index($line, 'Package versions: ') == 0
                 and $line =~ /\bcmake_(\S+)/
                 and ($1 eq '2.8.7-1' or $1 eq '2.8.7-2')) {
             if (not $option_buildd) {
                 error_invalid_cmake($1);
                 and $line =~ /\bcmake_(\S+)/
                 and ($1 eq '2.8.7-1' or $1 eq '2.8.7-2')) {
             if (not $option_buildd) {
                 error_invalid_cmake($1);
+                $exit |= $exit_code{invalid_cmake};
             } else {
             } else {
-                print "W-invalid-cmake-used $1\n";
+                print "$buildd_tag{invalid_cmake}|$1|\n";
             }
             }
-            $exit |= $exit_code{invalid_cmake};
         }
 
         # If hardening wrapper is used (wraps calls to gcc and adds hardening
         # flags automatically) we can't perform any checks, abort.
         }
 
         # If hardening wrapper is used (wraps calls to gcc and adds hardening
         # flags automatically) we can't perform any checks, abort.
-        if ($line =~ /^Build-Depends: .*\bhardening-wrapper\b/) {
+        if (index($line, 'Build-Depends: ') == 0
+                and $line =~ /\bhardening-wrapper\b/) {
             if (not $option_buildd) {
                 error_hardening_wrapper();
             if (not $option_buildd) {
                 error_hardening_wrapper();
+                $exit |= $exit_code{hardening_wrapper};
             } else {
             } else {
-                print "I-hardening-wrapper-used\n";
+                print "$buildd_tag{hardening_wrapper}||\n";
             }
             }
-            $exit |= $exit_code{hardening_wrapper};
             next FILE;
         }
 
         # We skip over unimportant lines at the beginning of the log to
         # prevent false positives.
             next FILE;
         }
 
         # We skip over unimportant lines at the beginning of the log to
         # prevent false positives.
-        last if $line =~ /^dpkg-buildpackage:/;
+        last if index($line, 'dpkg-buildpackage: ') == 0;
     }
 
     # Input lines, contain only the lines with compiler commands.
     my @input = ();
     }
 
     # Input lines, contain only the lines with compiler commands.
     my @input = ();
+    # Non-verbose lines in the input. Used to reduce calls to
+    # is_non_verbose_build() (which is quite slow) in the second loop when
+    # it's already clear if a line is non-verbose or not.
+    my @input_nonverbose = ();
 
     my $continuation = 0;
     my $complete_line = undef;
 
     my $continuation = 0;
     my $complete_line = undef;
@@ -595,18 +713,19 @@ foreach my $file (@ARGV) {
         # And stop at the end of the build log. Package details (reported by
         # the buildd logs) are not important for us. This also prevents false
         # positives.
         # And stop at the end of the build log. Package details (reported by
         # the buildd logs) are not important for us. This also prevents false
         # positives.
-        last if $line =~ /^Build finished at \d{8}-\d{4}$/;
+        last if index($line, 'Build finished at ') == 0
+                and $line =~ /^Build finished at \d{8}-\d{4}$/;
 
         # Detect architecture automatically unless overridden.
         if (not $arch
 
         # Detect architecture automatically unless overridden.
         if (not $arch
-                and $line =~ /^dpkg-buildpackage: host architecture (.+)$/) {
-            $arch = $1;
+                and index($line, 'dpkg-buildpackage: host architecture ') == 0) {
+            $arch = substr $line, 37, -1; # -1 to ignore '\n' at the end
         }
 
         # Ignore compiler warnings for now.
         next if $line =~ /$warning_regex/o;
 
         }
 
         # Ignore compiler warnings for now.
         next if $line =~ /$warning_regex/o;
 
-        if (not $option_buildd and $line =~ /\033/) { # esc
+        if (not $option_buildd and index($line, "\033") != -1) { # \033 = esc
             # Remove all ANSI color sequences which are sometimes used in
             # non-verbose builds.
             $line = Term::ANSIColor::colorstrip($line);
             # Remove all ANSI color sequences which are sometimes used in
             # non-verbose builds.
             $line = Term::ANSIColor::colorstrip($line);
@@ -623,7 +742,7 @@ foreach my $file (@ARGV) {
 
         # One line may contain multiple commands (";"). Treat each one as
         # single line. parse_line() is slow, only use it when necessary.
 
         # One line may contain multiple commands (";"). Treat each one as
         # single line. parse_line() is slow, only use it when necessary.
-        my @line = (not $line =~ /;/)
+        my @line = (index($line, ';') == -1)
                  ? ($line)
                  : map {
                        # Ensure newline at the line end - necessary for
                  ? ($line)
                  : map {
                        # Ensure newline at the line end - necessary for
@@ -631,7 +750,7 @@ foreach my $file (@ARGV) {
                        $_ =~ s/\s+$//;
                        $_ .= "\n";
                    } Text::ParseWords::parse_line(';', 1, $line);
                        $_ =~ s/\s+$//;
                        $_ .= "\n";
                    } Text::ParseWords::parse_line(';', 1, $line);
-        foreach $line (@line) {
+        foreach my $line (@line) {
             if ($continuation) {
                 $continuation = 0;
 
             if ($continuation) {
                 $continuation = 0;
 
@@ -641,7 +760,7 @@ foreach my $file (@ARGV) {
                 $complete_line .= ' ' . $line;
             }
             # Line continuation, line ends with "\".
                 $complete_line .= ' ' . $line;
             }
             # Line continuation, line ends with "\".
-            if ($line =~ /\\\s*$/) {
+            if ($line =~ /\\$/) {
                 $continuation = 1;
                 # Start line continuation.
                 if (not defined $complete_line) {
                 $continuation = 1;
                 # Start line continuation.
                 if (not defined $complete_line) {
@@ -658,7 +777,7 @@ foreach my $file (@ARGV) {
 
             # Ignore lines with no compiler commands.
             next if not $non_verbose
 
             # Ignore lines with no compiler commands.
             next if not $non_verbose
-                    and not $line =~ /\b$cc_regex(?:\s|\\)/o;
+                    and not $line =~ /$cc_regex_normal/o;
             # Ignore lines with no filenames with extensions. May miss some
             # non-verbose builds (e.g. "gcc -o test" [sic!]), but shouldn't be
             # a problem as the log will most likely contain other non-verbose
             # Ignore lines with no filenames with extensions. May miss some
             # non-verbose builds (e.g. "gcc -o test" [sic!]), but shouldn't be
             # a problem as the log will most likely contain other non-verbose
@@ -670,30 +789,57 @@ foreach my $file (@ARGV) {
             #
             # `./configure` output.
             next if not $non_verbose
             #
             # `./configure` output.
             next if not $non_verbose
-                    and $line =~ /^(?:checking|(?:C|c)onfigure:) /;
+                    and $line =~ /^(?:checking|[Cc]onfigure:) /;
             next if $line =~ /^\s*(?:Host\s+)?(?:C(?:\+\+)?\s+)?
             next if $line =~ /^\s*(?:Host\s+)?(?:C(?:\+\+)?\s+)?
-                                (?:C|c)ompiler[\s.]*:?\s+
-                                /xo;
+                                [Cc]ompiler[\s.]*:?\s+
+                                /x;
             next if $line =~ /^\s*(?:- )?(?:HOST_)?(?:CC|CXX)\s*=\s*$cc_regex_full\s*$/o;
             next if $line =~ /^\s*(?:- )?(?:HOST_)?(?:CC|CXX)\s*=\s*$cc_regex_full\s*$/o;
+            # `moc-qt4`, contains '-I/usr/share/qt4/mkspecs/linux-g++' (or
+            # similar for other architectures) which gets recognized as a
+            # compiler line. Ignore it.
+            next if $line =~ m{^/usr/bin/moc-qt4
+                               \s.+\s
+                               -I/usr/share/qt4/mkspecs/[a-z]+-g\++(?:-64)?
+                               \s}x;
+            # Ignore false positives when the line contains only CC=gcc but no
+            # other gcc command.
+            if ($line =~ /(.*)CC=$cc_regex_full(.*)/o) {
+                my $before = $1;
+                my $after  = $2;
+                next if     not $before =~ /$cc_regex_normal/o
+                        and not $after  =~ /$cc_regex_normal/o;
+            }
 
             # Check if additional hardening options were used. Used to ensure
             # they are used for the complete build.
 
             # Check if additional hardening options were used. Used to ensure
             # they are used for the complete build.
-            $harden_pie     = 1 if any_flags_used($line, @def_cflags_pie, @def_ldflags_pie);
+            $harden_pie     = 1 if any_flags_used($line, @def_cflags_pie,
+                                                         @def_ldflags_pie);
             $harden_bindnow = 1 if any_flags_used($line, @def_ldflags_bindnow);
 
             push @input, $line;
             $harden_bindnow = 1 if any_flags_used($line, @def_ldflags_bindnow);
 
             push @input, $line;
+            push @input_nonverbose, $non_verbose;
         }
     }
 
         }
     }
 
-    close $fh;
+    close $fh or die $!;
+
+    # Ignore arch if requested.
+    if (scalar @option_ignore_arch > 0 and $arch) {
+        foreach my $ignore (@option_ignore_arch) {
+            if ($arch eq $ignore) {
+                print "ignoring architecture '$arch'\n";
+                next FILE;
+            }
+        }
+    }
 
     if (scalar @input == 0) {
         if (not $option_buildd) {
             print "No compiler commands!\n";
 
     if (scalar @input == 0) {
         if (not $option_buildd) {
             print "No compiler commands!\n";
+            $exit |= $exit_code{no_compiler_commands};
         } else {
         } else {
-            print "W-no-compiler-commands\n";
+            print "$buildd_tag{no_compiler_commands}||\n";
         }
         }
-        $exit |= $exit_code{no_compiler_commands};
         next FILE;
     }
 
         next FILE;
     }
 
@@ -703,7 +849,7 @@ foreach my $file (@ARGV) {
 
     # Option or auto detected.
     if ($arch) {
 
     # Option or auto detected.
     if ($arch) {
-        # The following was partially copied from dpkg-dev 1.16.1.2
+        # The following was partially copied from dpkg-dev 1.16.4.3
         # (/usr/share/perl5/Dpkg/Vendor/Debian.pm, add_hardening_flags()),
         # copyright Raphaël Hertzog <hertzog@debian.org>, Kees Cook
         # <kees@debian.org>, Canonical, Ltd. licensed under GPL version 2 or
         # (/usr/share/perl5/Dpkg/Vendor/Debian.pm, add_hardening_flags()),
         # copyright Raphaël Hertzog <hertzog@debian.org>, Kees Cook
         # <kees@debian.org>, Canonical, Ltd. licensed under GPL version 2 or
@@ -753,23 +899,46 @@ foreach my $file (@ARGV) {
         @ldflags = (@ldflags, @def_ldflags_bindnow);
     }
 
         @ldflags = (@ldflags, @def_ldflags_bindnow);
     }
 
+    # Hack to fix cppflags_fortify_broken() if --ignore-flag
+    # -D_FORTIFY_SOURCE=2 is used to ignore missing fortification. Only works
+    # as long as @def_cppflags_fortify contains only one variable.
+    if (scalar @def_cppflags_fortify == 0) {
+        $harden_fortify = 0;
+    }
+
+    # Ignore flags for this arch if requested.
+    if ($arch and exists $option_ignore_arch_flag{$arch}) {
+        my @local_flag_refs = (\@cflags, \@cxxflags, \@cppflags, \@ldflags);
+
+        remove_flags(\@local_flag_refs,
+                     \%flag_renames,
+                     @{$option_ignore_arch_flag{$arch}});
+    }
+
+    my @ignore_line = @option_ignore_line;
+    # Ignore lines for this arch if requested.
+    if ($arch and exists $option_ignore_arch_line{$arch}) {
+        @ignore_line = (@ignore_line, @{$option_ignore_arch_line{$arch}});
+    }
+
 LINE:
     for (my $i = 0; $i < scalar @input; $i++) {
         my $line = $input[$i];
 
         # Ignore line if requested.
 LINE:
     for (my $i = 0; $i < scalar @input; $i++) {
         my $line = $input[$i];
 
         # Ignore line if requested.
-        foreach my $ignore (@option_ignore_line) {
+        foreach my $ignore (@ignore_line) {
             next LINE if $line =~ /$ignore/;
         }
 
         my $skip = 0;
             next LINE if $line =~ /$ignore/;
         }
 
         my $skip = 0;
-        if (is_non_verbose_build($line, $input[$i + 1], \$skip)) {
+        if ($input_nonverbose[$i]
+                and is_non_verbose_build($line, $input[$i + 1], \$skip)) {
             if (not $option_buildd) {
                 error_non_verbose_build($line);
             if (not $option_buildd) {
                 error_non_verbose_build($line);
+                $exit |= $exit_code{non_verbose_build};
             } else {
                 $statistics{commands_nonverbose}++;
             }
             } else {
                 $statistics{commands_nonverbose}++;
             }
-            $exit |= $exit_code{non_verbose_build};
             next;
         }
         # Even if it's a verbose build, we might have to skip this line.
             next;
         }
         # Even if it's a verbose build, we might have to skip this line.
@@ -779,7 +948,7 @@ LINE:
         # checks easier and faster.
         $line =~ s/^.*?$cc_regex//o;
         # "([...] test.c)" is not detected as 'test.c' - fix this by removing
         # checks easier and faster.
         $line =~ s/^.*?$cc_regex//o;
         # "([...] test.c)" is not detected as 'test.c' - fix this by removing
-        # the brace and similar characters.
+        # the brace and similar characters at the line end.
         $line =~ s/['")]+$//;
 
         # Skip unnecessary tests when only preprocessing.
         $line =~ s/['")]+$//;
 
         # Skip unnecessary tests when only preprocessing.
@@ -828,18 +997,29 @@ LINE:
             $preprocess = 1;
         }
 
             $preprocess = 1;
         }
 
-        # If there are source files then it's compiling/linking in one step
-        # and we must check both. We only check for source files here, because
-        # header files cause too many false positives.
-        if (not $flag_preprocess
-                and extension_found(\%extensions_compile_link, @extensions)) {
-            # Assembly files don't need CFLAGS.
-            if (not extension_found(\%extensions_compile, @extensions)
-                    and extension_found(\%extensions_no_compile, @extensions)) {
-                $compile = 0;
-            # But the rest does.
-            } else {
-                $compile = 1;
+        if (not $flag_preprocess) {
+            # If there are source files then it's compiling/linking in one
+            # step and we must check both. We only check for source files
+            # here, because header files cause too many false positives.
+            if (extension_found(\%extensions_compile_link, @extensions)) {
+                # Assembly files don't need CFLAGS.
+                if (not extension_found(\%extensions_compile, @extensions)
+                        and extension_found(\%extensions_no_compile, @extensions)) {
+                    $compile = 0;
+                # But the rest does.
+                } else {
+                    $compile = 1;
+                }
+            # No compilable extensions found, either linking or compiling
+            # header flags.
+            #
+            # If there are also no object files we are just compiling headers
+            # (.h -> .h.gch). Don't check for linker flags in this case. Due
+            # to our liberal checks for compiler lines, this also reduces the
+            # number of false positives considerably.
+            } elsif ($link
+                    and not extension_found(\%extensions_object, @extensions)) {
+                $link = 0;
             }
         }
 
             }
         }
 
@@ -867,48 +1047,52 @@ LINE:
                 # are missing.
                 and not pic_pie_conflict($line, $harden_pie, \@missing, @def_cflags_pie)
                 # Assume dpkg-buildflags returns the correct flags.
                 # are missing.
                 and not pic_pie_conflict($line, $harden_pie, \@missing, @def_cflags_pie)
                 # Assume dpkg-buildflags returns the correct flags.
-                and not $line =~ /`dpkg-buildflags --get CFLAGS`/) {
+                and index($line, '`dpkg-buildflags --get CFLAGS`') == -1) {
             if (not $option_buildd) {
                 error_flags('CFLAGS missing', \@missing, \%flag_renames, $input[$i]);
             if (not $option_buildd) {
                 error_flags('CFLAGS missing', \@missing, \%flag_renames, $input[$i]);
+                $exit |= $exit_code{flags_missing};
             } else {
                 $statistics{compile_missing}++;
             }
             } else {
                 $statistics{compile_missing}++;
             }
-            $exit |= $exit_code{flags_missing};
         } elsif ($compile_cpp and not all_flags_used($line, \@missing, @cflags)
                 # Libraries linked with -fPIC don't have to (and can't) be
                 # linked with -fPIE as well. It's no error if only PIE flags
                 # are missing.
                 and not pic_pie_conflict($line, $harden_pie, \@missing, @def_cflags_pie)
                 # Assume dpkg-buildflags returns the correct flags.
         } elsif ($compile_cpp and not all_flags_used($line, \@missing, @cflags)
                 # Libraries linked with -fPIC don't have to (and can't) be
                 # linked with -fPIE as well. It's no error if only PIE flags
                 # are missing.
                 and not pic_pie_conflict($line, $harden_pie, \@missing, @def_cflags_pie)
                 # Assume dpkg-buildflags returns the correct flags.
-                and not $line =~ /`dpkg-buildflags --get CXXFLAGS`/) {
+                and index($line, '`dpkg-buildflags --get CXXFLAGS`') == -1) {
             if (not $option_buildd) {
                 error_flags('CXXFLAGS missing', \@missing, \%flag_renames, $input[$i]);
             if (not $option_buildd) {
                 error_flags('CXXFLAGS missing', \@missing, \%flag_renames, $input[$i]);
+                $exit |= $exit_code{flags_missing};
             } else {
                 $statistics{compile_cpp_missing}++;
             }
             } else {
                 $statistics{compile_cpp_missing}++;
             }
-            $exit |= $exit_code{flags_missing};
         }
         }
-        if ($preprocess and not all_flags_used($line, \@missing, @cppflags)
+        if ($preprocess
+                and (not all_flags_used($line, \@missing, @cppflags)
+                    # The fortify flag might be overwritten, detect that.
+                     or ($harden_fortify
+                         and cppflags_fortify_broken($line, \@missing)))
                 # Assume dpkg-buildflags returns the correct flags.
                 # Assume dpkg-buildflags returns the correct flags.
-                and not $line =~ /`dpkg-buildflags --get CPPFLAGS`/) {
+                and index($line, '`dpkg-buildflags --get CPPFLAGS`') == -1) {
             if (not $option_buildd) {
                 error_flags('CPPFLAGS missing', \@missing, \%flag_renames, $input[$i]);
             if (not $option_buildd) {
                 error_flags('CPPFLAGS missing', \@missing, \%flag_renames, $input[$i]);
+                $exit |= $exit_code{flags_missing};
             } else {
                 $statistics{preprocess_missing}++;
             }
             } else {
                 $statistics{preprocess_missing}++;
             }
-            $exit |= $exit_code{flags_missing};
         }
         if ($link and not all_flags_used($line, \@missing, @ldflags)
                 # Same here, -fPIC conflicts with -fPIE.
                 and not pic_pie_conflict($line, $harden_pie, \@missing, @def_ldflags_pie)
                 # Assume dpkg-buildflags returns the correct flags.
         }
         if ($link and not all_flags_used($line, \@missing, @ldflags)
                 # Same here, -fPIC conflicts with -fPIE.
                 and not pic_pie_conflict($line, $harden_pie, \@missing, @def_ldflags_pie)
                 # Assume dpkg-buildflags returns the correct flags.
-                and not $line =~ /`dpkg-buildflags --get LDFLAGS`/) {
+                and index($line, '`dpkg-buildflags --get LDFLAGS`') == -1) {
             if (not $option_buildd) {
                 error_flags('LDFLAGS missing', \@missing, \%flag_renames, $input[$i]);
             if (not $option_buildd) {
                 error_flags('LDFLAGS missing', \@missing, \%flag_renames, $input[$i]);
+                $exit |= $exit_code{flags_missing};
             } else {
                 $statistics{link_missing}++;
             }
             } else {
                 $statistics{link_missing}++;
             }
-            $exit |= $exit_code{flags_missing};
         }
     }
 }
         }
     }
 }
@@ -918,32 +1102,32 @@ if ($option_buildd) {
     my @warning;
 
     if ($statistics{preprocess_missing}) {
     my @warning;
 
     if ($statistics{preprocess_missing}) {
-        push @warning, sprintf "CPPFLAGS %d (of %d)",
+        push @warning, sprintf 'CPPFLAGS %d (of %d)',
                                $statistics{preprocess_missing},
                                $statistics{preprocess};
     }
     if ($statistics{compile_missing}) {
                                $statistics{preprocess_missing},
                                $statistics{preprocess};
     }
     if ($statistics{compile_missing}) {
-        push @warning, sprintf "CFLAGS %d (of %d)",
+        push @warning, sprintf 'CFLAGS %d (of %d)',
                                $statistics{compile_missing},
                                $statistics{compile};
     }
     if ($statistics{compile_cpp_missing}) {
                                $statistics{compile_missing},
                                $statistics{compile};
     }
     if ($statistics{compile_cpp_missing}) {
-        push @warning, sprintf "CXXFLAGS %d (of %d)",
+        push @warning, sprintf 'CXXFLAGS %d (of %d)',
                                $statistics{compile_cpp_missing},
                                $statistics{compile_cpp};
     }
     if ($statistics{link_missing}) {
                                $statistics{compile_cpp_missing},
                                $statistics{compile_cpp};
     }
     if ($statistics{link_missing}) {
-        push @warning, sprintf "LDFLAGS %d (of %d)",
+        push @warning, sprintf 'LDFLAGS %d (of %d)',
                                $statistics{link_missing},
                                $statistics{link};
     }
     if (scalar @warning) {
         local $" = ', '; # array join string
                                $statistics{link_missing},
                                $statistics{link};
     }
     if (scalar @warning) {
         local $" = ', '; # array join string
-        print "W-dpkg-buildflags-missing @warning missing\n";
+        print "$buildd_tag{flags_missing}|@warning missing|\n";
     }
 
     if ($statistics{commands_nonverbose}) {
     }
 
     if ($statistics{commands_nonverbose}) {
-        printf "W-compiler-flags-hidden %d (of %d) hidden\n",
+        printf "$buildd_tag{non_verbose_build}|%d (of %d) hidden|\n",
                $statistics{commands_nonverbose},
                $statistics{commands},
     }
                $statistics{commands_nonverbose},
                $statistics{commands},
     }
@@ -961,7 +1145,7 @@ blhc - build log hardening check, checks build logs for missing hardening flags
 
 =head1 SYNOPSIS
 
 
 =head1 SYNOPSIS
 
-B<blhc> [I<options>] I<E<lt>dpkg-buildpackage build log fileE<gt>..>
+B<blhc> [I<options>] I<< <dpkg-buildpackage build log file>.. >>
 
 =head1 DESCRIPTION
 
 
 =head1 DESCRIPTION
 
@@ -972,6 +1156,11 @@ It's designed to check build logs generated by Debian's dpkg-buildpackage (or
 tools using dpkg-buildpackage like pbuilder or the official buildd build logs)
 to help maintainers detect missing hardening flags in their packages.
 
 tools using dpkg-buildpackage like pbuilder or the official buildd build logs)
 to help maintainers detect missing hardening flags in their packages.
 
+Only gcc is detected as compiler at the moment. If other compilers support
+hardening flags as well, please report them.
+
+If there's no output, no flags are missing and the build log is fine.
+
 =head1 OPTIONS
 
 =over 8
 =head1 OPTIONS
 
 =over 8
@@ -998,26 +1187,45 @@ changes are in effect:
 
 =over 2
 
 
 =over 2
 
-=item
+=item *
 
 Print tags instead of normal warnings, see L</"BUILDD TAGS"> for a list of
 possible tags.
 
 
 Print tags instead of normal warnings, see L</"BUILDD TAGS"> for a list of
 possible tags.
 
-=item
+=item *
 
 Don't check hardening flags in old log files (if dpkg-dev << 1.16.1 is
 detected).
 
 
 Don't check hardening flags in old log files (if dpkg-dev << 1.16.1 is
 detected).
 
-=item
+=item *
 
 Don't require Term::ANSIColor.
 
 
 Don't require Term::ANSIColor.
 
+=item *
+
+Return exit code 0, unless there was a error (-I, -W messages don't count as
+error).
+
 =back
 
 =item B<--color>
 
 Use colored (ANSI) output for warning messages.
 
 =back
 
 =item B<--color>
 
 Use colored (ANSI) output for warning messages.
 
+=item B<--ignore-arch> I<arch>
+
+Ignore build logs from architectures matching I<arch>. I<arch> is a string.
+
+Used to prevent false positives. This option can be specified multiple times.
+
+=item B<--ignore-arch-flag> I<arch>:I<flag>
+
+Like B<--ignore-flag>, but only ignore flag on I<arch>.
+
+=item B<--ignore-arch-line> I<arch>:I<line>
+
+Like B<--ignore-line>, but only ignore line on I<arch>.
+
 =item B<--ignore-flag> I<flag>
 
 Don't print an error when the specific flag is missing in a compiler line.
 =item B<--ignore-flag> I<flag>
 
 Don't print an error when the specific flag is missing in a compiler line.
@@ -1059,6 +1267,8 @@ Normal usage, parse a single log file.
 
     blhc path/to/log/file
 
 
     blhc path/to/log/file
 
+If there's no output, no flags are missing and the build log is fine.
+
 Parse multiple log files. The exit code is ORed over all files.
 
     blhc path/to/directory/with/log/files/*
 Parse multiple log files. The exit code is ORed over all files.
 
     blhc path/to/directory/with/log/files/*
@@ -1067,6 +1277,10 @@ Don't treat missing C<-g> as error:
 
     blhc --ignore-flag -g path/to/log/file
 
 
     blhc --ignore-flag -g path/to/log/file
 
+Don't treat missing C<-pie> on kfreebsd-amd64 as error:
+
+    blhc --ignore-arch-flag kfreebsd-amd64:-pie path/to/log/file
+
 Ignore lines consisting exactly of C<./script gcc file> which would cause a
 false positive.
 
 Ignore lines consisting exactly of C<./script gcc file> which would cause a
 false positive.
 
@@ -1088,17 +1302,13 @@ which is displayed.
 
 =over 2
 
 
 =over 2
 
-=item
-
-B<I-hardening-wrapper-used>
+=item B<I-hardening-wrapper-used>
 
 The package uses hardening-wrapper which intercepts calls to gcc and adds
 hardening flags. The build log doesn't contain any hardening flags and thus
 can't be checked by blhc.
 
 
 The package uses hardening-wrapper which intercepts calls to gcc and adds
 hardening flags. The build log doesn't contain any hardening flags and thus
 can't be checked by blhc.
 
-=item
-
-B<W-compiler-flags-hidden> (summary of hidden lines)
+=item B<W-compiler-flags-hidden> (summary of hidden lines)
 
 Build log contains lines which hide the real compiler flags. For example:
 
 
 Build log contains lines which hide the real compiler flags. For example:
 
@@ -1112,19 +1322,20 @@ F<debian/rules> fixes builds with hidden compiler flags. Sometimes C<.SILENT>
 in a F<Makefile> must be removed. And as last resort the F<Makefile> must be
 patched to remove the C<@>s hiding the real compiler commands.
 
 in a F<Makefile> must be removed. And as last resort the F<Makefile> must be
 patched to remove the C<@>s hiding the real compiler commands.
 
-=item
-
-B<W-dpkg-buildflags-missing> (summary of missing flags)
+=item B<W-dpkg-buildflags-missing> (summary of missing flags)
 
 CPPFLAGS, CFLAGS, CXXFLAGS, LDFLAGS missing.
 
 
 CPPFLAGS, CFLAGS, CXXFLAGS, LDFLAGS missing.
 
-=item
-
-B<W-invalid-cmake-used> (version)
+=item B<I-invalid-cmake-used> (version)
 
 
-=item
+By default CMake ignores CPPFLAGS thus missing those hardening flags. Debian
+patched CMake in versions 2.8.7-1 and 2.8.7-2 to respect CPPFLAGS, but this
+patch was rejected by upstream and later reverted in Debian. Thus those two
+versions show correct usage of CPPFLAGS even if the package doesn't correctly
+handle them (for example by passing them to CFLAGS). To prevent false
+negatives just blacklist those two versions.
 
 
-B<W-no-compiler-commands>
+=item B<I-no-compiler-commands>
 
 No compiler commands were detected. Either the log contains none or they were
 not correctly detected by blhc (please report the bug in this case).
 
 No compiler commands were detected. Either the log contains none or they were
 not correctly detected by blhc (please report the bug in this case).
@@ -1162,6 +1373,11 @@ Missing hardening flags.
 
 Hardening wrapper detected, no tests performed.
 
 
 Hardening wrapper detected, no tests performed.
 
+=item B<32>
+
+Invalid CMake version used. See B<I-invalid-cmake-used> under L</"BUILDD
+TAGS"> for a detailed explanation.
+
 =back
 
 =head1 AUTHOR
 =back
 
 =head1 AUTHOR
@@ -1171,7 +1387,7 @@ Simon Ruderich, E<lt>simon@ruderich.orgE<gt>
 Thanks to to Bernhard R. Link E<lt>brlink@debian.orgE<gt> and Jaria Alto
 E<lt>jari.aalto@cante.netE<gt> for their valuable input and suggestions.
 
 Thanks to to Bernhard R. Link E<lt>brlink@debian.orgE<gt> and Jaria Alto
 E<lt>jari.aalto@cante.netE<gt> for their valuable input and suggestions.
 
-=head1 COPYRIGHT AND LICENSE
+=head1 LICENSE AND COPYRIGHT
 
 Copyright (C) 2012 by Simon Ruderich
 
 
 Copyright (C) 2012 by Simon Ruderich