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

[SCM] Debian package checker branch, master, updated. 2.5.9-10-ga85b306



The following commit has been merged in the master branch:
commit a85b306ae8168f71394f65f5405e980fd5fd7d5b
Author: Niels Thykier <niels@thykier.net>
Date:   Tue Jun 19 18:19:06 2012 +0200

    c/java: Catch bad Java Class versions
    
    Add experimental tag, which unconditionally flags Java7 byte code as
    bad.  There are possible cases where Java7 byte code is allowed, but
    it is does not handle for now.
    
    Add another tag for catching "unknown" Java Class versions (e.g.
    Java8), which is not supported by any officially released JVM.
    
    Signed-off-by: Niels Thykier <niels@thykier.net>

diff --git a/checks/java b/checks/java
index 0823475..054d103 100644
--- a/checks/java
+++ b/checks/java
@@ -36,6 +36,8 @@ my $missing_jarwrapper = 0;
 my $need_cp = 0;
 my $has_public_jars = 0;
 my $has_jars = 0;
+my $jmajlow = '-';
+
 
 my $depends = $info->relation('strong')->unparse();
 # Remove all libX-java-doc packages to avoid thinking they are java libs
@@ -49,11 +51,11 @@ $need_cp = 1 if @java_lib_depends;
 # We first loop over jar files to find problems
 
 for my $jar_file (sort keys %{$java_info}) {
-    my $file_list = $java_info->{$jar_file}->{files};
+    my $files = $java_info->{$jar_file}->{files};
     my $manifest = $java_info->{$jar_file}->{manifest};
     my $operm = $info->index->{$jar_file}->operm;
     my $jar_dir;
-    my $classes = 1;
+    my $classes = 0;
     my $datafiles = 1;
     my $cp = '';
     my $bsname = '';
@@ -71,9 +73,33 @@ for my $jar_file (sort keys %{$java_info}) {
         $has_public_jars = 1;
     }
     # check for common code files like .class or .clj (Clojure files)
-    $classes = 0 unless grep m/\.(?:class|clj)$/oi, @{$file_list};
+    foreach my $class (grep m/\.(?:class|clj)$/oi, sort keys %$files) {
+        my $mver = $files->{$class};
+        $classes = 1;
+        next if $class =~ m/\.clj$/;
+        # .class but no major version?
+        next if $mver eq '-';
+        if ($mver <= 44 or $mver >= 52) {
+            # First public major version was 45 (Java1), latest
+            # version is 51 (Java7).
+            tag 'unknown-java-class-version', $jar_file, "($class -> $mver)";
+            # Skip the rest of this Jar.
+            last;
+        }
+
+        # Collect the "lowest" Class version used.  We assume that
+        # mixed class formats implies special compat code for certain
+        # JVM cases.
+        if ($jmajlow eq '-') {
+            # first;
+            $jmajlow = $mver;
+        } else {
+            $jmajlow = $mver if $mver < $jmajlow;
+        }
+    }
+
     $datafiles = 0
-        unless grep m/\.(?:xml|properties|x?html|xhp)$/io, @{$file_list};
+        unless grep m/\.(?:xml|properties|x?html|xhp)$/io, keys %$files;
 
     if($operm & 0111) {
         # Executable ?
@@ -112,7 +138,7 @@ for my $jar_file (sort keys %{$java_info}) {
         $need_cp = 0 if $bsname;
         # Maybe it is a maven plugin?
         $need_cp = 0 if $need_cp
-            && grep { m,^META-INF/maven/plugin.xml$,io } @{$file_list};
+            && grep { m,^META-INF/maven/plugin.xml$,io } keys %$files;
     } else {
         # Only run the tests when a classpath is present
         my @relative = ();
@@ -152,6 +178,26 @@ for my $jar_file (sort keys %{$java_info}) {
 
 tag 'missing-dep-on-jarwrapper' if $missing_jarwrapper;
 
+if ($jmajlow ne '-') {
+    # Byte code numbers:
+    #  45-49 -> Java1 - Java5 (Always ok)
+    #     50 -> Java6
+    #     51 -> Java7
+    my $bad = 0;
+
+    # If the lowest version used is:
+    $bad = 1 if $jmajlow == 51; # Java7 - consider bad per request.
+
+    # Technically we ought to do some checks with Java6 class files and
+    # dependencies/package types, but for now just skip that.  (See #673276)
+
+    if ($bad) {
+        # Map the Class version to a Java version.
+        my $v = $jmajlow - 44;
+        tag 'incompatible-java-bytecode-format', "Java${v} version (Class format: $jmajlow)";
+    }
+}
+
 
 if($has_jars && $need_cp) {
     # Only tag if there is at least one jar file and one strong java dependency
diff --git a/checks/java.desc b/checks/java.desc
index c091106..dd652ba 100644
--- a/checks/java.desc
+++ b/checks/java.desc
@@ -85,3 +85,23 @@ Severity: normal
 Certainty: certain
 Info: The jar file contains a manifest but no code. This probably indicates
  that something went wrong at build-time.
+
+Tag: incompatible-java-bytecode-format
+Severity: normal
+Certainty: possible
+Experimental: yes
+Info: The package contains Java class files with a minimum requirement on the
+ listed Java version.  This Java version is not supported by the default JVM
+ in Debian and is therefore likely to be a mistake.
+Ref: #673276
+
+Tag: unknown-java-class-version
+Severity: normal
+Certainty: certain
+Info: The package contains a Jar file with Java class files compiled for an
+ unknown Java version.  Most likely the class file is corrupt or compiled
+ for a newer version of Java than Lintian knows about.  In the latter case,
+ please file a bug against Lintian.
+ .
+ Lastest class version known by Lintian is Java7 (Major version 51).
+
diff --git a/collection/java-info b/collection/java-info
index 3f64b6d..90e1556 100755
--- a/collection/java-info
+++ b/collection/java-info
@@ -69,12 +69,22 @@ foreach my $file ($info->sorted_index) {
         # First, the file list:
         foreach my $member ($azip->members) {
             my $name = $member->fileName;
+            my $jversion;
             next if $member->isDirectory;
             $manifest = $member if $name =~ m@^META-INF/MANIFEST.MF$@oi;
             if ($name =~ m/\.class$/o) {
                 # Collect the Major version of the class file.
+                my ($contents, $zerr) = $member->contents;
+                fail "Failed to decompress $name of $file: $zerr"
+                    unless $zerr == AZ_OK;
+                # translation of the unpack
+                #  NN NN NN NN, nn nn, nn nn   - bytes read (in hex, network order)
+                #     $magic  , __ __, $major  - variables
+                my ($magic, undef, $major) = unpack ('Nnn', $contents);
+                $jversion = $major if $magic == 0xCAFEBABE;
             }
-            print {$opts{pipe_in}} $name, "\n";
+            $jversion //= '-';
+            print {$opts{pipe_in}} $name, ": $jversion\n";
         }
 
         if ($manifest) {
diff --git a/collection/java-info.desc b/collection/java-info.desc
index 1fd441d..470b827 100644
--- a/collection/java-info.desc
+++ b/collection/java-info.desc
@@ -2,5 +2,5 @@ Collector-Script: java-info
 Author: Vincent Fourmond <fourmond@debian.org>
 Info: This script extracts information from manifests of JAR files
 Type: binary
-Version: 2
+Version: 3
 Needs-Info: index, file-info, unpacked
diff --git a/debian/changelog b/debian/changelog
index c7246d8..c578fcd 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,17 @@
 lintian (2.5.10) UNRELEASED; urgency=low
 
+  * Summary of tag changes:
+    + Added:
+      - incompatible-java-bytecode-format
+      - unknown-java-class-version
+
+  * checks/java{,.desc}:
+    + [NT] Catch unknown Java class versions.
+    + [NT] Catch uses of Java7 byte code as an experimental
+      check.  It lacks the proper checks for cases where
+      packages have the proper dependencies for Java7 byte
+      code.  (Closes: #673276)
+
   * collection/java-info{,.desc}:
     + [NT] Use Archive::Zip instead of zipinfo + unzip to
       extract information from Jar files.
diff --git a/lib/Lintian/Collect/Binary.pm b/lib/Lintian/Collect/Binary.pm
index d39e7aa..f58d3e3 100644
--- a/lib/Lintian/Collect/Binary.pm
+++ b/lib/Lintian/Collect/Binary.pm
@@ -287,7 +287,7 @@ sub java_info {
     open my $idx, '-|', 'gzip', '-dc', "$base_dir/java-info.gz"
         or fail "cannot open $base_dir/java-info.gz: $!";
     my $file;
-    my $file_list = 0;
+    my $file_list;
     my $manifest = 0;
     local $_;
     while (<$idx>) {
@@ -302,7 +302,7 @@ sub java_info {
         }
         elsif (m#^-- (?:\./)?(.+)$#o) {
             $file = $1;
-            $java_info{$file}->{files} = [];
+            $java_info{$file}->{files} = {};
             $file_list = $java_info{$file}->{files};
             $manifest = 0;
         }
@@ -310,8 +310,9 @@ sub java_info {
             if($manifest && m#^  (\S+):\s(.*)$#o) {
                 $manifest->{$1} = $2;
             }
-            elsif($file_list) {
-                push @{$file_list}, $_;
+            elsif ($file_list) {
+                my ($fname, $clmajor) = (m#^(.*):\s*([-\d]+)$#);
+                $file_list->{$fname} = $clmajor;
             }
 
         }
diff --git a/t/tests/debhelper-deprecated/debian/debian/control.in b/t/tests/java-class-format/debian/debian/control.in
similarity index 64%
copy from t/tests/debhelper-deprecated/debian/debian/control.in
copy to t/tests/java-class-format/debian/debian/control.in
index 16fc0b0..bfeae69 100644
--- a/t/tests/debhelper-deprecated/debian/debian/control.in
+++ b/t/tests/java-class-format/debian/debian/control.in
@@ -3,15 +3,13 @@ Priority: extra
 Section: {$section}
 Maintainer: {$author}
 Standards-Version: {$standards_version}
-Build-Depends: debhelper (>= 9), python-central, python-ply (>= 3.4-1~)
+Build-Depends: debhelper (>= 9), javahelper, default-jdk
 
-Package: {$srcpkg}
+Package: libtest-java
 Architecture: {$architecture}
 Depends: $\{misc:Depends\}
 Description: {$description}
  This is a test package designed to test various aspects of the
- debhelper-related QA code in lintian.  This may be a useless
- empty package.
+ java-related QA code in lintian. First part.
  .
  This package should not be installed.
-
diff --git a/t/tests/java-class-format/debian/debian/javabuild b/t/tests/java-class-format/debian/debian/javabuild
new file mode 100644
index 0000000..f13db32
--- /dev/null
+++ b/t/tests/java-class-format/debian/debian/javabuild
@@ -0,0 +1 @@
+test.jar src
diff --git a/t/tests/java-class-format/debian/debian/libtest-java.jlibs b/t/tests/java-class-format/debian/debian/libtest-java.jlibs
new file mode 100644
index 0000000..867ff3b
--- /dev/null
+++ b/t/tests/java-class-format/debian/debian/libtest-java.jlibs
@@ -0,0 +1,2 @@
+testa.jar
+testb.jar
diff --git a/t/tests/java-class-format/debian/debian/rules b/t/tests/java-class-format/debian/debian/rules
new file mode 100755
index 0000000..10d7678
--- /dev/null
+++ b/t/tests/java-class-format/debian/debian/rules
@@ -0,0 +1,19 @@
+#!/usr/bin/make -f
+%:
+	dh $@ --with javahelper
+
+override_jh_build:
+	jh_build
+	unzip test.jar
+	# Unknown class version
+	perl -i -pe 's/^(\xCA\xFE\xBA\xBE...)./$$1\x2A/' org/debian/lintian/TestA.class
+	# Java7 (unsupported)
+	perl -i -pe 's/^(\xCA\xFE\xBA\xBE...)./$$1\x33/' org/debian/lintian/TestB.class
+	# Put them in separate Jars because Lintian stops when the first
+	# "unknown class format" is seen
+	zip -r testa.jar META-INF/ org/debian/lintian/TestA.class
+	zip -r testb.jar META-INF/ org/debian/lintian/TestB.class
+
+override_dh_auto_clean:
+	rm -fr META-INF/ org/
+	rm -f *.jar
diff --git a/t/tests/java-class-format/desc b/t/tests/java-class-format/desc
new file mode 100644
index 0000000..8ca1b37
--- /dev/null
+++ b/t/tests/java-class-format/desc
@@ -0,0 +1,9 @@
+Testname: java-class-format
+Type: non-native
+Sequence: 6000
+Version: 1.0-1
+Description: Various checks for Java Class format
+Section: java
+Test-For:
+ incompatible-java-bytecode-format
+ unknown-java-class-version
diff --git a/t/tests/java-class-format/tags b/t/tests/java-class-format/tags
new file mode 100644
index 0000000..545d902
--- /dev/null
+++ b/t/tests/java-class-format/tags
@@ -0,0 +1,2 @@
+W: libtest-java: unknown-java-class-version usr/share/java/testa-1.0.jar (org/debian/lintian/TestA.class -> 42)
+X: libtest-java: incompatible-java-bytecode-format Java7 version (Class format: 51)
diff --git a/t/tests/java-classpath/upstream/src/org/debian/lintian/TestA.java b/t/tests/java-class-format/upstream/src/org/debian/lintian/TestA.java
similarity index 97%
copy from t/tests/java-classpath/upstream/src/org/debian/lintian/TestA.java
copy to t/tests/java-class-format/upstream/src/org/debian/lintian/TestA.java
index dacb2f2..fa9bad9 100644
--- a/t/tests/java-classpath/upstream/src/org/debian/lintian/TestA.java
+++ b/t/tests/java-class-format/upstream/src/org/debian/lintian/TestA.java
@@ -5,4 +5,4 @@ package org.debian.lintian;
  */
 public class TestA {
     // An empty class should do.
-};
\ No newline at end of file
+};
diff --git a/t/tests/java-classpath/upstream/src/org/debian/lintian/TestA.java b/t/tests/java-class-format/upstream/src/org/debian/lintian/TestB.java
similarity index 80%
copy from t/tests/java-classpath/upstream/src/org/debian/lintian/TestA.java
copy to t/tests/java-class-format/upstream/src/org/debian/lintian/TestB.java
index dacb2f2..eca69aa 100644
--- a/t/tests/java-classpath/upstream/src/org/debian/lintian/TestA.java
+++ b/t/tests/java-class-format/upstream/src/org/debian/lintian/TestB.java
@@ -3,6 +3,6 @@ package org.debian.lintian;
 /**
    A neat empty useless class.
  */
-public class TestA {
+public class TestB {
     // An empty class should do.
-};
\ No newline at end of file
+};
diff --git a/t/tests/java-classpath/debian/debian/rules b/t/tests/java-classpath/debian/debian/rules
index df489df..25e040d 100755
--- a/t/tests/java-classpath/debian/debian/rules
+++ b/t/tests/java-classpath/debian/debian/rules
@@ -2,3 +2,6 @@
 
 %:
 	dh $@ --with javahelper
+
+override_jh_build:
+	jh_build --javacopts='-target 1.5' --javacopts='-source 1.5'
diff --git a/t/tests/java-jars/debian/debian/rules b/t/tests/java-jars/debian/debian/rules
index 729215d..6bef5a7 100755
--- a/t/tests/java-jars/debian/debian/rules
+++ b/t/tests/java-jars/debian/debian/rules
@@ -3,7 +3,7 @@
 	dh $@ --with javahelper
 
 override_jh_build:
-	jh_build
+	jh_build --javacopts='-target 1.5' --javacopts='-source 1.5'
 	unzip testa.jar
 	zip -r codeless.jar META-INF/
 	zip -r manifestless.jar org/

-- 
Debian package checker


Reply to: