Bug#718349: lintian: Emits malformed-deb-archive on valid deb packages
On 2013-08-06 03:03, Guillem Jover wrote:
> Hi!
>
> [...]
>
> Actually, “_” members can be inserted before data.tar and after
> debian-binary (which is the only member with a hardcoded index), so
> control.tar.gz might not be the second (absolute) member. I guess this
> was not really clear from the deb(5) man page, so I'll try to clarify it.
>
> (I also just noticed dpkg-deb does not enforce control.tar > data.tar
> index order :/, I'll be fixing this for 1.17.2 too…)
>
> Thanks,
> Guillem
>
>
Okay, I got a revised patch that should be able to cope with "_" members
before control.tar.gz as well.
~Niels
>From 65369b07cd8e0d602c70a122a96016dbcfcb4d6f Mon Sep 17 00:00:00 2001
From: Niels Thykier <niels@thykier.net>
Date: Mon, 5 Aug 2013 23:39:01 +0200
Subject: [PATCH] c/deb-format: Add new tag for "extra" deb members
Add a separate tag for "extra" members in deb files that are permitted
by the format (as described by deb(5)).
Signed-off-by: Niels Thykier <niels@thykier.net>
---
checks/deb-format.desc | 7 +++
checks/deb-format.pm | 103 +++++++++++++++++++++++++++++++-----
data/deb-format/extra-members | 16 ++++++
debian/changelog | 10 +++-
t/debs/deb-format-extra-member/desc | 2 +-
t/debs/deb-format-extra-member/tags | 2 +-
t/debs/deb-format-wrong-order/tags | 2 +-
7 files changed, 125 insertions(+), 17 deletions(-)
create mode 100644 data/deb-format/extra-members
diff --git a/checks/deb-format.desc b/checks/deb-format.desc
index d28f615..8a4f214 100644
--- a/checks/deb-format.desc
+++ b/checks/deb-format.desc
@@ -17,6 +17,13 @@ Info: The binary package is not a correctly constructed archive. A binary
of 2.
Ref: deb(5)
+Tag: misplaced-extra-member-in-deb
+Severity: important
+Certainty: certain
+Info: The binary package contains an extra member that Lintian did not
+ expect or expected at a different position.
+Ref: deb(5)
+
Tag: lzma-deb-archive
Severity: serious
Certainty: certain
diff --git a/checks/deb-format.pm b/checks/deb-format.pm
index 5ea1995..6485f77 100644
--- a/checks/deb-format.pm
+++ b/checks/deb-format.pm
@@ -20,7 +20,10 @@ use strict;
use warnings;
use autodie;
+use List::MoreUtils qw(first_index none);
+
use Lintian::Command qw(spawn);
+use Lintian::Data;
use Lintian::Tags qw(tag);
# The files that contain error messages from tar, which we'll check and issue
@@ -33,6 +36,8 @@ our %ERRORS = (
'unpacked-errors' => 'tar-errors-from-data'
);
+my $EXTRA_MEMBERS = Lintian::Data->new('deb-format/extra-members');
+
sub run {
my (undef, $type, $info) = @_;
my $deb = $info->lab_data_path('deb');
@@ -43,25 +48,97 @@ sub run {
my $success = spawn($opts, ['ar', 't', $deb]);
if ($success) {
my @members = split("\n", ${ $opts->{out} });
- if (@members != 3) {
- my $count = scalar(@members);
- tag 'malformed-deb-archive',"found $count members instead of 3";
+ my $count = scalar(@members);
+ my ($ctrl_member, $data_member);
+ if ($count < 3) {
+ tag 'malformed-deb-archive',
+ "found only $count members instead of 3";
} elsif ($members[0] ne 'debian-binary') {
tag 'malformed-deb-archive',
"first member $members[0] not debian-binary";
- } elsif ($members[1] ne 'control.tar.gz') {
- tag 'malformed-deb-archive',
- "second member $members[1] not control.tar.gz";
- } elsif ($type eq 'udeb' && $members[2] !~ m/^data\.tar\.[gx]z$/) {
- tag 'udeb-uses-unsupported-compression-for-data-tarball';
- } elsif ($members[2] eq 'data.tar.lzma') {
- # Ubuntu's archive allows lzma packages.
- tag 'lzma-deb-archive';
- } elsif ($members[2] !~ /^data\.tar\.(?:gz|bz2|xz)\z/) {
+ } elsif ($count == 3 and none {
+ substr($_, 0, 1) eq '_';
+ }
+ @members
+ ) {
+ # Fairly common case - if there are only 3 members without
+ # "_", we can trivially determine their (expected)
+ # positions. We only use this case when there are no
+ # "extra" members, because they can trigger more tags
+ # (see below)
+ (undef, $ctrl_member, $data_member) = @members;
+ } else {
+ my $ctrl_index
+ = first_index { substr($_, 0, 1) ne '_' } @members[1..$#members];
+ my $data_index;
+
+ if ($ctrl_index != -1) {
+ # Since we searched only a sublist of @members, we have to
+ # add 1 to $ctrl_index
+ $ctrl_index++;
+ $ctrl_member = $members[$ctrl_index];
+ $data_index = first_index { substr($_, 0, 1) ne '_' }
+ @members[$ctrl_index..$#members];
+ if ($data_index != -1) {
+ # Since we searched only a sublist of @members, we
+ # have to adjust $data_index
+ $data_index += $ctrl_index + 1;
+ $data_member = $members[$data_index];
+ }
+ }
+
+ # Extra members
+ for my $i (1..$#members) {
+ my $member = $members[$i];
+ my $actual_index = $i;
+ my ($expected, $text);
+ next if $i == $ctrl_index or $i == $data_index;
+ $expected = $EXTRA_MEMBERS->value($member);
+ if (defined($expected)) {
+ next if $expected eq 'ANYWHERE';
+ next if $expected == $actual_index;
+ $text = "expected at position $expected, but appeared";
+ } else {
+ $text = 'unexpected member';
+ }
+ tag 'misplaced-extra-member-in-deb',
+ "$member ($text at position $actual_index)";
+ }
+ }
+ if (not defined($ctrl_member)) {
+ # Somehow I doubt we will ever get this far without a control
+ # file... :)
+ tag 'malformed-deb-archive', 'Missing control.tar.gz member';
+ } elsif ($ctrl_member ne 'control.tar.gz') {
tag 'malformed-deb-archive',
- "third member $members[2] not data.tar.(gz|bz2|xz)";
+ "second (official) member $ctrl_member not control.tar.gz";
+ } elsif (not defined($data_member)) {
+ # Somehow I doubt we will ever get this far without a data
+ # member (i.e. I suspect unpacked and index will fail), but
+ # mah
+ tag 'malformed-deb-archive', 'Missing data.tar member';
} else {
+ # Probably okay
$okay = 1;
+ if (
+ $data_member !~ m/\A
+ data\.tar(?:\.(?:gz|bz2|xz|lzma))? \Z/xsm
+ ) {
+ # wasn't okay after all
+ $okay = 0;
+ } elsif ($type eq 'udeb'
+ && $data_member !~ m/^data\.tar\.[gx]z$/) {
+ tag 'udeb-uses-unsupported-compression-for-data-tarball';
+ } elsif ($data_member eq 'data.tar.lzma') {
+ # Ubuntu's archive allows lzma packages.
+ tag 'lzma-deb-archive';
+ }
+ if (not $okay) {
+ tag 'malformed-deb-archive',
+ join(' ',
+ "third (official) member $data_member",
+ 'not data.tar.(gz|bz2|xz)');
+ }
}
} else {
# unpack will probably fail so we'll never get here, but may as well be
diff --git a/data/deb-format/extra-members b/data/deb-format/extra-members
new file mode 100644
index 0000000..23d298f
--- /dev/null
+++ b/data/deb-format/extra-members
@@ -0,0 +1,16 @@
+# List of extra members permitted in the .deb files
+#
+# Format is:
+# <name> => <position>
+#
+#
+# <position> is a 0-indexed position of where the extra member is
+# expected. It can be "ANYWHERE" if the order is not relevant. Note
+# despite of the value of <position>, any member appearing before the
+# data.tar member MUST have a name starting with "_". If not Lintian
+# will presume it is the control.tar or the data.tar member (depending
+# on how early it occurs). It is impossible for any valid "2.0" deb
+# file to have an extra member at position 0 (which is exclusively
+# reserved for the "debian-binary" member)
+#
+# For Debian, no extra members are defined, so the file is empty atm.
diff --git a/debian/changelog b/debian/changelog
index bbd923e..239c795 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -7,7 +7,15 @@ lintian (2.5.18) UNRELEASED; urgency=low
(Closes: #721252)
+ [BR] Extend tag description of the gfdl-invariants tag.
(Closes: #722102)
- * checks/files.{pm,desc}:
+ * checks/deb-format.{desc,pm}:
+ + [NT] Allow data.tar members in deb files. Thanks to
+ Guillem Jover for the report.
+ + [NT] Support (but tag) unofficial members after the
+ "debian-binary" member where allowed by dpkg. These
+ members will trigger misplaced-extra-member-in-deb tag.
+ Thanks to Guillem Jover for the report and the feedback.
+ (Closes: #718349)
+ * checks/files.{desc,pm}:
+ [BR] Fix false-positive dir-or-file-in-build-tree for
the sbuild source package. (Closes: #720910)
+ [NT] Add check for empty udeb packages. Thanks to Cyril
diff --git a/t/debs/deb-format-extra-member/desc b/t/debs/deb-format-extra-member/desc
index c5f24b7..3d55144 100644
--- a/t/debs/deb-format-extra-member/desc
+++ b/t/debs/deb-format-extra-member/desc
@@ -2,4 +2,4 @@ Testname: deb-format-extra-member
Sequence: 6000
Version: 1.0
Description: Test package for an ar archive in the wrong order
-Test-For: malformed-deb-archive
+Test-For: misplaced-extra-member-in-deb
diff --git a/t/debs/deb-format-extra-member/tags b/t/debs/deb-format-extra-member/tags
index 6e19acf..30c21d6 100644
--- a/t/debs/deb-format-extra-member/tags
+++ b/t/debs/deb-format-extra-member/tags
@@ -1 +1 @@
-E: deb-format-extra-member: malformed-deb-archive found 4 members instead of 3
+E: deb-format-extra-member: misplaced-extra-member-in-deb extra-stuff (unexpected member at position 3)
diff --git a/t/debs/deb-format-wrong-order/tags b/t/debs/deb-format-wrong-order/tags
index aafecf5..10abed7 100644
--- a/t/debs/deb-format-wrong-order/tags
+++ b/t/debs/deb-format-wrong-order/tags
@@ -1 +1 @@
-E: deb-format-wrong-order: malformed-deb-archive second member data.tar.gz not control.tar.gz
+E: deb-format-wrong-order: malformed-deb-archive second (official) member data.tar.gz not control.tar.gz
--
1.8.4.rc3
Reply to: