From a63e83503a5872632f679ecbeae2f602edf60af3 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Wed, 2 Oct 2019 23:47:26 +0200 Subject: [PATCH 1/7] (WIP) add unit tests for Instrumenter --- .../jacoco/core/instr/InstrumenterTest.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java b/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java index 79f11c6c02..0fa42ecd5c 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java @@ -117,6 +117,23 @@ private static byte[] createClass(final int version) { return cw.toByteArray(); } + /** + * @see #instrumentAll_should_throw_exception_for_unsupported_class_file_version() + */ + @Test + public void instrument_should_throw_exception_for_unsupported_class_file_version() { + final byte[] bytes = createClass(Opcodes.V14 + 1); + try { + instrumenter.instrument(bytes, "UnsupportedVersion"); + fail("exception expected"); + } catch (final IOException e) { + assertEquals("Error while instrumenting UnsupportedVersion.", + e.getMessage()); + assertEquals("Unsupported class file major version 59", + e.getCause().getMessage()); + } + } + @Test public void testInstrumentClass() throws Exception { byte[] bytes = instrumenter.instrument( @@ -202,6 +219,24 @@ public void testSerialization() throws Exception { assertEquals("Hello42", obj2.toString()); } + /** + * @see #instrument_should_throw_exception_for_unsupported_class_file_version() + */ + @Test + public void instrumentAll_should_throw_exception_for_unsupported_class_file_version() { + final byte[] bytes = createClass(Opcodes.V14 + 1); + try { + instrumenter.instrumentAll(new ByteArrayInputStream(bytes), + new ByteArrayOutputStream(), "UnsupportedVersion"); + fail("exception expected"); + } catch (final IOException e) { + assertEquals("Error while instrumenting UnsupportedVersion.", + e.getMessage()); + assertEquals("Unsupported class file major version 59", + e.getCause().getMessage()); + } + } + @Test public void testInstrumentAll_Class() throws IOException { InputStream in = TargetLoader.getClassData(getClass()); From 9cb78b1423e29ee8e7aa7da2c5cf08cd160b800d Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Wed, 2 Oct 2019 23:49:30 +0200 Subject: [PATCH 2/7] (WIP) add unit tests for Analyzer --- .../jacoco/core/analysis/AnalyzerTest.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/org.jacoco.core.test/src/org/jacoco/core/analysis/AnalyzerTest.java b/org.jacoco.core.test/src/org/jacoco/core/analysis/AnalyzerTest.java index 0e979f6ce9..f2a79515cb 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/analysis/AnalyzerTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/analysis/AnalyzerTest.java @@ -125,6 +125,23 @@ private static byte[] createClass(final int version) { return cw.toByteArray(); } + /** + * @see #analyzeAll_should_throw_exception_for_unsupported_class_file_version() + */ + @Test + public void analyzeClass_should_throw_exception_for_unsupported_class_file_version() { + final byte[] bytes = createClass(Opcodes.V14 + 1); + try { + analyzer.analyzeClass(bytes, "UnsupportedVersion"); + fail("exception expected"); + } catch (IOException e) { + assertEquals("Error while analyzing UnsupportedVersion.", + e.getMessage()); + assertEquals("Unsupported class file major version 59", + e.getCause().getMessage()); + } + } + @Test public void testAnalyzeClassFromStream() throws IOException { analyzer.analyzeClass(TargetLoader.getClassData(AnalyzerTest.class), @@ -196,6 +213,24 @@ public void testAnalyzeClass_BrokenStream() throws IOException { } } + /** + * @see #analyzeClass_should_throw_exception_for_unsupported_class_file_version() + */ + @Test + public void analyzeAll_should_throw_exception_for_unsupported_class_file_version() { + final byte[] bytes = createClass(Opcodes.V14 + 1); + try { + analyzer.analyzeAll(new ByteArrayInputStream(bytes), + "UnsupportedVersion"); + fail("exception expected"); + } catch (IOException e) { + assertEquals("Error while analyzing UnsupportedVersion.", + e.getMessage()); + assertEquals("Unsupported class file major version 59", + e.getCause().getMessage()); + } + } + @Test public void testAnalyzeAll_Class() throws IOException { final int count = analyzer.analyzeAll( From bbfa48c3cd68ce1b64546aecb08d2212120dddbe Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Thu, 3 Oct 2019 00:24:16 +0200 Subject: [PATCH 3/7] (WIP) add unit tests for ContentTypeDetector --- .../core/internal/ContentTypeDetectorTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/ContentTypeDetectorTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/ContentTypeDetectorTest.java index d96c6683b8..a35c0e657f 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/ContentTypeDetectorTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/ContentTypeDetectorTest.java @@ -180,6 +180,21 @@ public void should_detect_java_14_with_preview_features() throws IOException { assertContent(); } + @Test + public void should_detect_java_42() throws IOException { + initData(0xCA, 0xFE, 0xBA, 0xBE, 0x00, 0x00, 0x00, 0x56); + assertEquals(ContentTypeDetector.CLASSFILE, detector.getType()); + assertContent(); + } + + @Test + public void should_not_detect_MachO_fat_binary_with_44_architectures() + throws IOException { + initData(0xCA, 0xFE, 0xBA, 0xBE, 0x00, 0x00, 0x00, 0x2C); + assertEquals(ContentTypeDetector.UNKNOWN, detector.getType()); + assertContent(); + } + @Test public void testMachObjectFile() throws IOException { initData(0xCA, 0xFE, 0xBA, 0xBE, 0x00, 0x00, 0x00, 0x02); From f444cbd7b2924214fc6df2b9bd176e038bf8c492 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Thu, 3 Oct 2019 14:05:42 +0200 Subject: [PATCH 4/7] (WIP) implement --- .../core/internal/ContentTypeDetector.java | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java b/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java index 9bf8ec2f6c..1f67c032ef 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java @@ -74,25 +74,8 @@ private static int determineType(final InputStream in) throws IOException { return PACK200FILE; case CLASSFILE: // also verify version to distinguish from Mach Object files: - switch (readInt(in)) { - case Opcodes.V1_1: - case Opcodes.V1_2: - case Opcodes.V1_3: - case Opcodes.V1_4: - case Opcodes.V1_5: - case Opcodes.V1_6: - case Opcodes.V1_7: - case Opcodes.V1_8: - case Opcodes.V9: - case Opcodes.V10: - case Opcodes.V11: - case Opcodes.V11 | Opcodes.V_PREVIEW: - case Opcodes.V12: - case Opcodes.V12 | Opcodes.V_PREVIEW: - case Opcodes.V13: - case Opcodes.V13 | Opcodes.V_PREVIEW: - case (Opcodes.V13 + 1): - case (Opcodes.V13 + 1) | Opcodes.V_PREVIEW: + final int majorVersion = readInt(in) & 0xFFFF; + if (majorVersion >= 45) { return CLASSFILE; } } From 20c2fea5203a8437abb1976e1d6b1748d8726e34 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Thu, 3 Oct 2019 22:40:39 +0200 Subject: [PATCH 5/7] (WIP) update comment and changelog --- .../src/org/jacoco/core/internal/ContentTypeDetector.java | 7 ++++++- org.jacoco.doc/docroot/doc/changes.html | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java b/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java index 1f67c032ef..ae2e055d66 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java @@ -73,7 +73,12 @@ private static int determineType(final InputStream in) throws IOException { case PACK200FILE: return PACK200FILE; case CLASSFILE: - // also verify version to distinguish from Mach Object files: + // Mach-O fat/universal binaries have the same magic header as Java + // class files, number of architectures is stored in unsigned 4 + // bytes in the same place and in the same big-endian order as major + // and minor version of class file. Hopefully on practice number of + // architectures in single executable is less than 45, which is + // major version of Java 1.1 class files: final int majorVersion = readInt(in) & 0xFFFF; if (majorVersion >= 45) { return CLASSFILE; diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 174ebe3e6e..aacd4f8094 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -70,6 +70,9 @@

API Changes

a coverage ratio limit is configured outside the range [0,1] to avoid common configuration mistakes (GitHub #783). +
  • Report generation and offline instrumentation now throw an exception for + class files of unsupported version instead of skipping them silently + (GitHub #952).
  • Release 0.8.4 (2019/05/08)

    From 0f8cf839011598c0ddd1e02b20f26ef9e839c9da Mon Sep 17 00:00:00 2001 From: "Marc R. Hoffmann" Date: Fri, 4 Oct 2019 05:18:32 +0200 Subject: [PATCH 6/7] WIP: Remove unused import --- .../src/org/jacoco/core/internal/ContentTypeDetector.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java b/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java index ae2e055d66..eefb9ef006 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java @@ -16,8 +16,6 @@ import java.io.IOException; import java.io.InputStream; -import org.objectweb.asm.Opcodes; - /** * Detector for content types of binary streams based on a magic headers. */ From c95cf9af840a3ee417b19c8b2de9815b753eac6a Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Fri, 4 Oct 2019 13:14:54 +0200 Subject: [PATCH 7/7] (WIP) update changelog entry --- org.jacoco.doc/docroot/doc/changes.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index aacd4f8094..ac3e861564 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -70,8 +70,9 @@

    API Changes

    a coverage ratio limit is configured outside the range [0,1] to avoid common configuration mistakes (GitHub #783). -
  • Report generation and offline instrumentation now throw an exception for - class files of unsupported version instead of skipping them silently +
  • Unsupported class file versions are now consistently reported as exceptions + by all methods of Analyzer and Instrumenter and + thus also during report generation and offline instrumentation (GitHub #952).