Bug#620829: [new checks] implements parts of the java policy

April 04th, 2011 - 10:10 am ET by Vincent Fourmond | Report spam
This is a multi-part MIME message sent by reportbug.


MIME-Version: 1.0

Package: lintian
Version: 2.5.0~rc1
Severity: wishlist
Tags: patch

Hello,

Currently lintian does not cover at all the java packaging policy,
and that's probably one of the reasons why it is not very well
respected (especially since there are some quite devious tricks
there).

I have started an implementation of that in a clone of the git
repository. I have attached a patch containing some of my work. Please
note that this patch addresses #575447 but also a lot more.

I plan to go on working on that, if that's fine by you. Anyway,
there are a lot of things that still need to be implemented. What is
the workflow of the lintian team ? Shall I send you regularly batches
of git format-patch ? (which I haven't done this time). How can I
actually join the lintian team ?

Cheers,

Vincent

Debian Release: wheezy/sid
APT prefers unstable
APT policy: (500, 'unstable'), (500, 'testing'), (500, 'stable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.38-2-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_GB.utf8, LC_CTYPE=en_GB.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages lintian depends on:
ii binutils 2.21.0.20110327-2 The GNU assembler, linker and bina
ii diffstat 1.54-1 produces graph of changes introduc
ii dpkg-dev 1.16.0 Debian package development tools
ii file 5.04-5 Determines file type using "magic"
ii gettext 0.18.1.1-3 GNU Internationalization utilities
ii intltool-debian 0.35.0+20060710.1 Help i18n of RFC822 compliant conf
ii libapt-pkg-perl 0.1.24+b1 Perl interface to libapt-pkg
ii libclass-accessor-perl 0.34-1 Perl module that automatically gen
ii libemail-valid-perl 0.184-1 Perl module for checking the valid
ii libipc-run-perl 0.89-1 Perl module for running processes
ii libparse-debianchangel 1.1.1-2.1 parse Debian changelogs and output
ii libtimedate-perl 1.2000-1 collection of modules to manipulat
ii liburi-perl 1.58-1 module to manipulate and access UR
ii locales 2.11.2-13 Embedded GNU C Library: National L
ii man-db 2.5.9-4 on-line manual pager
ii perl [libdigest-sha-pe 5.10.1-19 Larry Wall's Practical Extraction

lintian recommends no packages.

Versions of packages lintian suggests:
pn binutils-multiarch <none> (no description available)
pn libtext-template-perl <none> (no description available)
ii man-db 2.5.9-4 on-line manual pager


MIME-Version: 1.0

diff --git a/checks/java b/checks/java
new file mode 100644
index 0000000..9aabf2a
/dev/null
+++ b/checks/java
@@ -0,0 +1,115 @@
+# java -- lintian check script -*- perl -*-
+
+# Copyright (C) 2011 Vincent Fourmond
+#
+# 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::java;
+use strict;
+use warnings;
+
+use lib "$ENV{'LINTIAN_ROOT'}/checks/";
+use common_data;
+
+use Lintian::Tags qw(tag);
+use Util;
+
+use File::Basename qw(fileparse);
+
+
+# The packages that are necessary to directly run an executable JAR
+# file.
+our @jarwrapper_or_equivalent = (
+ 'jarwrapper'
+ );
+
+sub run {
+
+my $pkg = shift;
+my $type = shift;
+my $info = shift;
+
+my $java_info = $info->java_info;
+my $missing_jarwrapper = 0;
+
+# We first loop over jar files to find problems
+
+for my $jar_file (keys %{$java_info}) {
+ my $manifest = $java_info->{$jar_file};
+
+ if($manifest->{'Manifest-Version'}) {
+ # We do have a real JAR with a real manifest.
+
+ my $operm = $info->{index}->{$jar_file}->{operm};
+ if(($operm & 01 or
+ $operm & 010 or $operm & 0100)) {
+ # Executable ?
+ tag "executable-jar-without-main-class", "$jar_file" unless
+ $manifest->{'Main-Class'};
+
+ # Here, we need to check that the package depends on
+ # jarwrapper.
+ my $ok = 0;
+
+ for my $p (@jarwrapper_or_equivalent) {
+ my $depends = Lintian::Relation->new($p);
+ if($info->relation('strong')->
+ implies($depends)) {
+ $ok = 1;
+ last;
+ }
+ }
+ $missing_jarwrapper = 1 unless ($ok);
+ }
+ elsif ($jar_file !~ m#^usr/share/(java|$pkg)/#) {
+ tag "jar-not-in-usr-share", "$jar_file";
+ }
+ }
+
+ my $cp = $manifest->{'Class-Path'};
+
+ my $relative = 0;
+ my $outside_usr_share = 0;
+ my @paths = split(/\s+/, $cp);
+ for my $p (@paths) {
+ if($p) {
+ if($p !~ m#^/#) {
+ $relative++;
+ }
+ elsif($p !~ m#/usr/share/#) {
+ $outside_usr_share++;
+ }
+ }
+ }
+
+ if($relative) {
+ tag "classpath-contains-relative-path", "$jar_file: $cp";
+ }
+
+ if($outside_usr_share) {
+ tag "classpath-contains-files-not-in-usr-share", "$jar_file: $cp";
+ }
+
+
+ }
+
+if($missing_jarwrapper) {
+ tag 'missing-dep-on-jarwrapper';
+}
+
+}
+1;
diff --git a/checks/java.desc b/checks/java.desc
new file mode 100644
index 0000000..e1781b9
/dev/null
+++ b/checks/java.desc
@@ -0,0 +1,44 @@
+Check-Script: java
+Author: Vincent Fourmond <fourmond@debian.org>
+Abbrev: java
+Type: binary
+Needs-Info: java-info
+Info: This script checks if the packages comply with various aspects of the
+ debian Java policy.
+
+Tag: classpath-contains-relative-path
+Severity: normal
+Certainty: certain
+Info: The classpath listed in some of the files references relative paths,
+ which should never be needed in a system JAR, especially as far as
+ security is concerned.
+
+Tag: classpath-contains-files-not-in-usr-share
+Severity: normal
+Certainty: certain
+Info: The classpath listed in some of the files references files outside
+ of /usr/share, while all installed JAR files must be within
+ /usr/share/java for libraries or /usr/share/<i>package</i> for JARs for
+ private use.
+
+Tag: jar-not-in-usr-share
+Severity: serious
+Certainty: certain
+Ref: java sub-policy 2.2 and 2.3
+Info: The classpath listed in some of the files references files outside
+ of /usr/share, while all installed JAR files must be within
+ /usr/share/java for libraries or /usr/share/<i>package</i> for JARs for
+ private use.
+
+Tag: executable-jar-without-main-class
+Severity: serious
+Certainty: certain
+Ref: java sub-policy 2.2
+Info: An executable JAR must have a Main-Class set in its manifest.
+
+Tag: missing-dep-on-jarwrapper
+Severity: serious
+Certainty: certain
+Ref: java sub-policy 2.2
+Info: Packages containing an executable JAR must depend on jarwrapper or
+ other packages providing similar functionalities.
\ No newline at end of file
diff --git a/collection/java-info b/collection/java-info
new file mode 100755
index 0000000..fb90739
/dev/null
+++ b/collection/java-info
@@ -0,0 +1,75 @@
+#!/usr/bin/perl -w
+# java-info -- lintian collection script
+
+# Copyright (C) 2011 Vincent Fourmond
+#
+# 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+use strict;
+use warnings;
+
+# Sanity check
+unless (-f 'fields/package') {
+ print STDERR 'error: collection script called in wrong directory!';
+ exit 2;
+}
+
+my $failed = 0;
+
+
+open (INDEX, '<', 'index')
+ or fail("cannot open index: $!");
+
+open (OUT, '>', 'java-info')
+ or fail("cannot open java-info: $!");
+
+chdir ('unpacked')
+ or fail ("unable to chdir to unpacked: $!");
+
+while (<INDEX>) {
+ chomp;
+ $_ = (split(' ', $_, 6))[5];
+ next if / -> .*/; # We skip symlinks.
+ if (m#(\S+).jar$#i) {
+ my $file = $_;
+
+ # This script needs unzip, there's no way around.
+ print OUT "-- $file";
+
+ open MANIFEST, "unzip -p \"$file\" META-INF/MANIFEST.MF | ";
+ my $first = 1;
+ while(my $line = <MANIFEST>) {
+ chomp $line;
+ $line =~ s///g;
+ if($line =~ /^(\S+:)\s*(.*)/) {
+ print OUT "" unless $first;
+ $first = 0;
+ print OUT " $1 $2";
+ }
+ if($line =~ /^ (.*)/) {
+ print OUT "$1";
+ }
+ }
+ close MANIFEST;
+ print OUT "" unless $first;
+ }
+}
+
+close INDEX;
+close OUT or fail("cannot write java-info: $!");
+
+exit $failed;
diff --git a/collection/java-info.desc b/collection/java-info.desc
new file mode 100644
index 0000000..6f93b69
/dev/null
+++ b/collection/java-info.desc
@@ -0,0 +1,6 @@
+Collector-Script: java-info
+Author: Vincent Fourmond <fourmond@debian.org>
+Info: This script extracts information from manifests of JAR files
+Type: binary, udeb
+Version: 1
+Needs-Info: unpacked
diff --git a/debian/control b/debian/control
index bf628cf..aebe7e5 100644
a/debian/control
+++ b/debian/control
@@ -51,6 +51,7 @@ Depends: ${misc:Depends},
diffstat,
dpkg-dev,
file,
+ unzip,
gettext,
intltool-debian,
libapt-pkg-perl,
diff --git a/lib/Lintian/Collect/Binary.pm b/lib/Lintian/Collect/Binary.pm
index 2dd6b58..0f328b9 100644
a/lib/Lintian/Collect/Binary.pm
+++ b/lib/Lintian/Collect/Binary.pm
@@ -287,6 +287,32 @@ sub objdump_info {
return $self->{objdump_info};
}

+
+# Returns the information from collect/objdump-info
+sub java_info {
+ my ($self) = @_;
+ return $self->{java_info} if exists $self->{java_info};
+
+ my %java_info;
+ open(my $idx, '<', 'java-info')
+ or fail("cannot open java-info: $!");
+ my $file;
+ while (<$idx>) {
+ chomp;
+ next if m/^\s*$/o;
+
+ if (m#^-- \./(.+)$#) {
+ $file = $1;
+ $java_info{$file} = {};
+ }
+ elsif (m#^ (\S+):\s(.*)$#) {
+ $java_info{$file}->{$1} = $2;
+ }
+ }
+ $self->{java_info} = \%java_info;
+ return $self->{java_info};
+}
+
# Return a Lintian::Relation object for the given relationship field. In
# addition to all the normal relationship fields, the following special
# field names are supported: all (pre-depends, depends, recommends, and





To UNSUBSCRIBE, email to debian-bugs-dist-REQUEST@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster@lists.debian.org
email Follow the discussionReplies 4 repliesReplies Make a reply

Replies

#1 Niels Thykier
April 05th, 2011 - 12:00 pm ET | Report spam
Hash: SHA256

On 2011-04-04 16:04, Vincent Fourmond wrote:
Package: lintian
Version: 2.5.0~rc1
Severity: wishlist
Tags: patch

Hello,




Hi Vincent

Currently lintian does not cover at all the java packaging policy,
and that's probably one of the reasons why it is not very well
respected (especially since there are some quite devious tricks
there).




Thanks for your interest in improving the coverage of the Java policy.
It was also my original intention when I joined Lintian (I admit being a
bit carried away :P ).

Have you also had a look at http://wiki.debian.org/Java/QATools ? It is
possibly a bit outdated, but I think most of the suggestions are still
worth considering.
Also feel free to add the things you are working on; hopefully that
will avoid duplicated work. :)

I have started an implementation of that in a clone of the git
repository. I have attached a patch containing some of my work. Please
note that this patch addresses #575447 but also a lot more.




What is classpath-contains-relative-path about? I have never heard any
security issues with related to relative classpaths (nor do I recall any
request to have the Java policy amended to take care of this). Could
you provide a reference to this issue?

Then there is the /usr/share/ part, which I am not too sure about
anymore. I originally thought that swt was the only one of its kind but
eclipse turned out to contain a lot of them actually. Of course this is
(in itself) no excuse for the rest of the arch independent jars to be
installed outside /usr/share. Maybe we can start with a lower
severity/certainty and then bump it to an error later.

Also you/we need to set up the java policy in
data/output/manual-references so we can use java 2.2 and java 2.3 in
checks/*.desc ref fields.

I plan to go on working on that, if that's fine by you. Anyway,
there are a lot of things that still need to be implemented. What is
the workflow of the lintian team ? Shall I send you regularly batches
of git format-patch ? (which I haven't done this time). How can I
actually join the lintian team ?




I am not too sure of the general work flow, but feel free to send
patches e.g. via bugs if you have more tags/changes. Personally I would
prefer if you used git format-patch (easier for me).
I believe you can test it by using:

LINTIAN_ROOT='.' frontend/lintian-info -t <tag>

Assuming you did not know it, you can also use frontend/lintian in a
similar fashion to test your changes without having to build and install
lintian.

Cheers,

Vincent




Comments on the patch itself (aside from the questions about some of the
tags above):

Why the "use" of common_data and File::Basename? The check does not
appear to use either.

Why is the check "binary only" but the collection "binary + udeb"? I
doubt we have any udebs with jar files, so I think it is safe to make
both "binary only".

I believe that the java_info sub in Lintian::Collect::Binary needs a
# sub java_info Needs-Info java-info
line. There is an automated test to check for this stuff. Secondly it
needs POD documentation (see the bottom of the file).

@jarwrapper_or_equivalent could be turned into a string - if we get
alternatives we can use "jarwrapper | alternative". This is what we do
with (e.g.) $PYTHON_DEV in checks/fields.

Please add automated tests for the tags (see t/tests/README or existing
tests for more information). We are trying to keep t/COVERAGE as empty
as possible. :) I have no strong preference to whether the tests should
be in the same patch or not, so do what is easiest for you.
You can test individual tests by using:

debian/rules runtests onlyrun=<name-of-test>
- OR -
debian/rules check-tag tag=<name-of-tag>

Note the name of the test is the one listed in its desc file - if you
copy/paste a desc file and forget to update the name in it, you may see
some "funny" results.

Please make sure that the test-scripts still pass with your patch. You
can check this by running:

debian/rules runtests

and wait for:

"""
t/scripts/<something> [...] ok
All tests successful.
Files7, Tests–40, [...]
Result: PASS
"""

You also ought to run the entire tests to ensure your new tags are not
triggered in the test suite (causing other tests to fail), but I have
feeling we do not have a lot of jar files in our test suite (yet). :)


Finally, we are planning to release 2.5.0~rc2 soon and I am hoping to
merge a branch shortly after the release. *If* this branch is merged
your collection will need to depend on two new collections (index and
fields), since these will provide the "index" file and the "fields/"
directory (respectively) in that branch.
If you check for the index file instead of fields/package, then you
can avoid the fields dep as far as I can see.
The check will also need a Needs-Info on fields ($info->relation).

~Niels




To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact

Similar topics