Currently when given a broken commit hash we assume everything newer
than this is broken. If we are retroactively recording info on a flaw that
is already fixed in git though, we might know a fixed commit hash. Use
this info to know when to stop reporting broken tags and branches.
Note this only works for branches containing the original primary fixed
commit. This does not try to identify cherry-picks to branches.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
scripts/report-vulnerable-tags.pl | 74 +++++++++++++++++++++++++++----
1 file changed, 66 insertions(+), 8 deletions(-)
diff --git a/scripts/report-vulnerable-tags.pl b/scripts/report-vulnerable-tags.pl
index 8a6c2e4..431a7bf 100644
--- a/scripts/report-vulnerable-tags.pl
+++ b/scripts/report-vulnerable-tags.pl
@@ -5,15 +5,18 @@ use warnings;
use Sort::Versions;
-if (int(@ARGV) != 1) {
- die "syntax: $0 CHANGESET\n";
+if (int(@ARGV) != 1 && int(@ARGV) != 2) {
+ die "syntax: $0 BROKEN-CHANGESET [FIXED-CHANGESET]\n";
}
-my $changeset = shift @ARGV;
+my $broken = shift @ARGV;
+my $fixed = shift @ARGV;
# branch name to hash with keys
# - brokenchanges -> list of commit ids
# - brokentags -> hash of tag names to '1'
+# - fixedchanges -> list of commit ids
+# - fixedtags -> hash of tag names to '1'
my %branches;
# tag name to '0' (fixed) or '1' (broken)
@@ -68,11 +71,22 @@ sub add_branch {
return if exists $branches{$name};
$branches{$name} = {
- "brokenchanges" => [$changeset],
+ "brokenchanges" => [$broken],
"brokentags" => {},
+ "fixedchanges" => [],
+ "fixedtags" => {},
};
}
+sub delete_branch {
+ my $name = shift @_;
+
+ if (int(keys %{$branches{$name}->{"brokentags"}})) {
+ print "Branch $name shouldn't have broken tags\n";
+ }
+ delete $branches{$name};
+}
+
sub add_broken_tag {
my $branch = shift @_;
my $tag = shift @_;
@@ -81,16 +95,51 @@ sub add_broken_tag {
$branches{$branch}->{"brokentags"}->{$tag} = 1;
}
+sub add_fixed_tag {
+ my $branch = shift @_;
+ my $tag = shift @_;
+
+ $tags{$tag} = 0;
+ $branches{$branch}->{"fixedtags"}->{$tag} = 1;
+}
+
+sub add_fixed_commit {
+ my $branch = shift @_;
+ my $commit = shift @_;
+
+ push @{$branches{$branch}->{"fixedchanges"}}, $commit;
+}
+
add_branch("master");
+if (defined $fixed) {
+ # Mark any tags containing the fix as known so they
+ # get excluded when later finding vulnerable tags
+ for my $tag (get_tags("--contains", $fixed)) {
+ $tags{$tag} = 0;
+ }
+
+
+ # Record the first tag in master which has the fix, if any
+ my @fixedtags = sort versioncmp get_tags("--contains", $fixed,
"--merged", "master");
+ if (int(@fixedtags)) {
+ add_fixed_tag("master", $fixedtags[0]);
+ }
+
+ add_fixed_commit("master", $fixed);
+}
+
# Most tags live on master so lets get them first
-for my $tag (get_tags("--contains", $changeset, "--merged",
"master")) {
+for my $tag (get_tags("--contains", $broken, "--merged",
"master")) {
+
+ next if exists $tags{$tag};
+
add_broken_tag("master", $tag);
}
# Now we need slower work to find branches for
# few remaining tags
-for my $tag (get_tags("--contains", $changeset)) {
+for my $tag (get_tags("--contains", $broken)) {
next if exists $tags{$tag};
@@ -117,6 +166,12 @@ for my $branch (get_branches($broken)) {
add_branch($branch);
}
+if (defined $fixed) {
+ for my $branch (get_branches($fixed)) {
+ delete_branch($branch);
+ }
+}
+
foreach my $branch (sort versioncmp keys %branches) {
print " <branch>\n";
print " <name>$branch</name>\n";
@@ -127,8 +182,11 @@ foreach my $branch (sort versioncmp keys %branches) {
print " <change
state=\"vulnerable\">$commit</change>\n";
}
- if ($branch eq "master") {
- print " <change
state=\"fixed\">$fixed</change>\n";
+ foreach my $tag (sort versioncmp keys
%{$branches{$branch}->{"fixedtags"}}) {
+ print " <tag state=\"fixed\">$tag</tag>\n";
+ }
+ foreach my $commit (@{$branches{$branch}->{"fixedchanges"}}) {
+ print " <change
state=\"fixed\">$commit</change>\n";
}
print " </branch>\n";
}
--
2.21.0