[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: