# Build log hardening check, checks build logs for missing hardening flags.
-# Copyright (C) 2012-2020 Simon Ruderich
+# Copyright (C) 2012-2021 Simon Ruderich
#
# 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
# FUNCTIONS
+sub split_line {
+ my ($line) = @_;
+
+ my @work = ($line);
+ foreach my $delim (';', '&&', '||') {
+ my @x;
+ foreach (@work) {
+ push @x, Text::ParseWords::parse_line(qr/\Q$delim\E/, 1, $_);
+ }
+ @work = @x;
+ }
+
+ return map {
+ # Ensure newline at the line end - necessary for
+ # correct parsing later.
+ $_ =~ s/\s+$//;
+ $_ .= "\n";
+ } @work;
+}
+
sub error_flags {
my ($message, $missing_flags_ref, $flag_renames_ref, $line, $number) = @_;
}
if ($option_version) {
print <<"EOF";
-blhc $VERSION Copyright (C) 2012-2020 Simon Ruderich
+blhc $VERSION Copyright (C) 2012-2021 Simon Ruderich
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
$non_verbose |= is_non_verbose_build($line, \$skip);
next if $skip;
- # One line may contain multiple commands (";"). Treat each one as
- # single line. parse_line() is slow, only use it when necessary.
- my @line = (index($line, ';') == -1)
+ # Treat each command as a single line so we don't ignore valid
+ # commands when handling false positives. split_line() is slow, only
+ # use it when necessary.
+ my @line = ($line !~ /(?:;|&&|\|\|)/)
? ($line)
- : map {
- # Ensure newline at the line end - necessary for
- # correct parsing later.
- $_ =~ s/\s+$//;
- $_ .= "\n";
- } Text::ParseWords::parse_line(';', 1, $line);
+ : split_line($line);
foreach my $line (@line) {
if ($continuation) {
$continuation = 0;
# optional compiler options, don't allow
# "everything" here to prevent false negatives
\s*(?:\s-\S+)*\s*$}xo;
+ # `echo` is never a compiler command
+ next if $line =~ /^\s*echo\s/;
+ # Ignore calls to `make` because they can contain environment
+ # variables which look like compiler commands, e.g. CC=).
+ next if $line =~ /^\s*make\s/;
# `moc-qt4`/`moc-qt5` contain '-I.../linux-g++' in their command
# line (or similar for other architectures) which gets recognized
# as a compiler line, but `moc-qt*` is only a preprocessor for Qt
next if $line =~ /^C\+\+ linker for the host machine: /;
# Embedded `gcc -print-*` commands
next if $line =~ /`$cc_regex_normal\s*[^`]*-print-\S+`/;
+ # cmake checking for compiler flags without setting CPPFLAGS
+ next if $line =~ m{^\s*/usr/(bin|lib)/(ccache/)?c\+\+ -dM -E -c /usr/share/cmake-\S+/Modules/CMakeCXXCompilerABI\.cpp};
# Check if additional hardening options were used. Used to ensure
# they are used for the complete build.
To generate this string simply use echo in C<debian/rules>; make sure to use @
to suppress the echo command itself as it could also trigger a false positive.
+If the build process takes a long time edit the C<.build> file in place and
+tweak the ignore string until B<blhc --all --debian package.build> no longer
+reports any false positives.
=head1 OPTIONS