]> ruderich.org/simon Gitweb - blhc/blhc.git/blobdiff - bin/blhc
Store exit codes in %exit_code.
[blhc/blhc.git] / bin / blhc
index 62ddb86a6076f986eb6fdeffec5b84e71b6f8731..7f1fd84fe1b078841eebbcd06a1c4f83cd6a5e2c 100755 (executable)
--- a/bin/blhc
+++ b/bin/blhc
@@ -142,13 +142,13 @@ my %extension = map { $_ => 1 } (
 # Regexp to match file extensions.
 my $file_extension_regex = qr/
     \s
 # Regexp to match file extensions.
 my $file_extension_regex = qr/
     \s
-    \S+         # Filename without extension.
+    \S+             # Filename without extension.
     \.
     \.
-    ([^\\.\s]+) # File extension.
-    (?=\s|\\)   # At end of word. Can't use \b because some files have non
-                # word characters at the end and because \b matches double
-                # extensions (like .cpp.o). Works always as all lines are
-                # terminated with "\n".
+    ([^\\.,;:\s]+)  # File extension.
+    (?=\s|\\)       # At end of word. Can't use \b because some files have non
+                    # word characters at the end and because \b matches double
+                    # extensions (like .cpp.o). Works always as all lines are
+                    # terminated with "\n".
     /x;
 
 # Expected (hardening) flags. All flags are used as regexps.
     /x;
 
 # Expected (hardening) flags. All flags are used as regexps.
@@ -193,6 +193,7 @@ my @def_ldflags_pie = (
 my @def_ldflags_pic = (
     '-fPIC',
     '-fpic',
 my @def_ldflags_pic = (
     '-fPIC',
     '-fpic',
+    '-shared',
 );
 # Renaming rules for the output so the regex parts are not visible. Also
 # stores string values of flag regexps above, see compile_flag_regexp().
 );
 # Renaming rules for the output so the regex parts are not visible. Also
 # stores string values of flag regexps above, see compile_flag_regexp().
@@ -202,6 +203,14 @@ my %flag_renames = (
     '-Wl,(-z,)?now'   => '-Wl,-z,now',
 );
 
     '-Wl,(-z,)?now'   => '-Wl,-z,now',
 );
 
+my %exit_code = (
+    no_compiler_commands => 1 << 0,
+    # used by POD::Usage => 1 << 1,
+    non_verbose_build    => 1 << 2,
+    flags_missing        => 1 << 3,
+    hardening_wrapper    => 1 << 4,
+);
+
 # 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 = (
@@ -311,13 +320,16 @@ sub is_non_verbose_build {
     my ($line, $next_line, $skip_ref) = @_;
 
     if (not ($line =~ /^checking if you want to see long compiling messages\.\.\. no/
     my ($line, $next_line, $skip_ref) = @_;
 
     if (not ($line =~ /^checking if you want to see long compiling messages\.\.\. no/
-                or $line =~ /^\s*\[?(?:CC|CCLD|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*\[[\d ]+%\] Building (?:C|CXX) object (.+?)$/)) {
         return 0;
     }
 
                 or $line =~ /^\s*(?:C|c)ompiling\s+(.+?)(?:\.\.\.)?$/
                 or $line =~ /^\s*(?:B|b)uilding (?:program|shared library)\s+(.+?)$/
                 or $line =~ /^\s*\[[\d ]+%\] Building (?:C|CXX) object (.+?)$/)) {
         return 0;
     }
 
+    # False positives.
+    return 0 if $line =~ /^\s*C\+\+.+?:\s+(?:yes|no)\s*$/;
+
     my $file = $1;
 
     # On the first pass we only check if this line is verbose or not.
     my $file = $1;
 
     # On the first pass we only check if this line is verbose or not.
@@ -490,7 +502,7 @@ FILE: foreach my $file (@ARGV) {
             } else {
                 print "I-hardening-wrapper-used\n";
             }
             } else {
                 print "I-hardening-wrapper-used\n";
             }
-            $exit |= 1 << 4;
+            $exit |= $exit_code{hardening_wrapper};
             next FILE;
         }
 
             next FILE;
         }
 
@@ -571,23 +583,24 @@ FILE: foreach my $file (@ARGV) {
                 }
 
                 # Ignore lines with no compiler commands.
                 }
 
                 # Ignore lines with no compiler commands.
-                next if $line !~ /\b$cc_regex(?:\s|\\)/o and not $non_verbose;
+                next if not $non_verbose
+                        and not $line =~ /\b$cc_regex(?:\s|\\)/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 commands which are detected.
+                next if not $non_verbose
+                        and not $line =~ /$file_extension_regex/o;
 
                 # Ignore false positives.
                 #
                 # `./configure` output.
                 next if not $non_verbose
                         and $line =~ /^(?:checking|(?:C|c)onfigure:) /;
 
                 # Ignore false positives.
                 #
                 # `./configure` output.
                 next if not $non_verbose
                         and $line =~ /^(?:checking|(?:C|c)onfigure:) /;
-                next if $line =~ /^\s*(?:Host\s+)?(?:C\s+)?
+                next if $line =~ /^\s*(?:Host\s+)?(?:C(?:\+\+)?\s+)?
                                    (?:C|c)ompiler[\s.]*:?\s+
                                    (?:C|c)ompiler[\s.]*:?\s+
-                                   $cc_regex_full
-                                   (?:\s-std=[a-z0-9:+]+)?\s*$
-                                 /xo
-                        or $line =~ /^\s*(?:- )?(?:HOST_)?(?:CC|CXX)\s*=\s*$cc_regex_full\s*$/o
-                        or $line =~ /^\s*-- Check for working (?:C|CXX) compiler: /
-                        or $line =~ /^\s*(?:echo )?Using [A-Z_]+\s*=\s*/;
-                # `make` output.
-                next if $line =~ /^Making [a-z]+ in \S+/; # e.g. "[...] in c++"
+                                 /xo;
+                next if $line =~ /^\s*(?:- )?(?:HOST_)?(?:CC|CXX)\s*=\s*$cc_regex_full\s*$/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.
@@ -602,8 +615,12 @@ FILE: foreach my $file (@ARGV) {
     close $fh;
 
     if (scalar @input == 0) {
     close $fh;
 
     if (scalar @input == 0) {
-        print "No compiler commands!\n";
-        $exit |= 1;
+        if (not $option_buildd) {
+            print "No compiler commands!\n";
+        } else {
+            print "W-no-compiler-commands\n";
+        }
+        $exit |= $exit_code{no_compiler_commands};
         next FILE;
     }
 
         next FILE;
     }
 
@@ -673,7 +690,7 @@ FILE: foreach my $file (@ARGV) {
             } else {
                 $statistics{commands_nonverbose}++;
             }
             } else {
                 $statistics{commands_nonverbose}++;
             }
-            $exit |= 1 << 2;
+            $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.
@@ -762,7 +779,7 @@ FILE: foreach my $file (@ARGV) {
             } else {
                 $statistics{compile_missing}++;
             }
             } else {
                 $statistics{compile_missing}++;
             }
-            $exit |= 1 << 3;
+            $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
         } 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
@@ -775,7 +792,7 @@ FILE: foreach my $file (@ARGV) {
             } else {
                 $statistics{compile_cpp_missing}++;
             }
             } else {
                 $statistics{compile_cpp_missing}++;
             }
-            $exit |= 1 << 3;
+            $exit |= $exit_code{flags_missing};
         }
         if ($preprocess and not all_flags_used($line, \@missing, @cppflags)
                 # Assume dpkg-buildflags returns the correct flags.
         }
         if ($preprocess and not all_flags_used($line, \@missing, @cppflags)
                 # Assume dpkg-buildflags returns the correct flags.
@@ -785,7 +802,7 @@ FILE: foreach my $file (@ARGV) {
             } else {
                 $statistics{preprocess_missing}++;
             }
             } else {
                 $statistics{preprocess_missing}++;
             }
-            $exit |= 1 << 3;
+            $exit |= $exit_code{flags_missing};
         }
         if ($link and not all_flags_used($line, \@missing, @ldflags)
                 # Same here, -fPIC conflicts with -fPIE.
         }
         if ($link and not all_flags_used($line, \@missing, @ldflags)
                 # Same here, -fPIC conflicts with -fPIE.
@@ -797,7 +814,7 @@ FILE: foreach my $file (@ARGV) {
             } else {
                 $statistics{link_missing}++;
             }
             } else {
                 $statistics{link_missing}++;
             }
-            $exit |= 1 << 3;
+            $exit |= $exit_code{flags_missing};
         }
     }
 }
         }
     }
 }
@@ -850,16 +867,7 @@ blhc - build log hardening check, checks build logs for missing hardening flags
 
 =head1 SYNOPSIS
 
 
 =head1 SYNOPSIS
 
-B<blhc> [options] <dpkg-buildpackage build log file>..
-
-    --all                   force +all (+pie, +bindnow) check
-    --arch                  set architecture (autodetected)
-    --bindnow               force +bindbow check
-    --buildd                parser mode for buildds
-    --color                 use colored output
-    --pie                   force +pie check
-    --help                  available options
-    --version               version number and license
+B<blhc> [I<options>] I<E<lt>dpkg-buildpackage build log fileE<gt>..>
 
 =head1 DESCRIPTION
 
 
 =head1 DESCRIPTION
 
@@ -875,7 +883,7 @@ other important warnings. It's licensed under the GPL 3 or later.
 Force check for all +all (+pie, +bindnow) hardening flags. By default it's
 auto detected.
 
 Force check for all +all (+pie, +bindnow) hardening flags. By default it's
 auto detected.
 
-=item B<--arch>
+=item B<--arch> I<architecture>
 
 Set the specific architecture (e.g. amd64, armel, etc.), automatically
 disables hardening flags not available on this architecture. Is detected
 
 Set the specific architecture (e.g. amd64, armel, etc.), automatically
 disables hardening flags not available on this architecture. Is detected