aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Mandrikov <138671+Godin@users.noreply.github.com>2019-10-04 15:24:53 +0200
committerMarc R. Hoffmann <hoffmann@mountainminds.com>2019-10-04 15:24:53 +0200
commitfba553424f9d49ecb1ac324548d50a3a19c1af7d (patch)
tree9066cfdfda70d8aa619308df12075badcd9931c0
parente1a9d4bd401b4bf9e20d03f4611e70b46ce66cdf (diff)
downloadplatform_external_jacoco-fba553424f9d49ecb1ac324548d50a3a19c1af7d.tar.gz
platform_external_jacoco-fba553424f9d49ecb1ac324548d50a3a19c1af7d.tar.bz2
platform_external_jacoco-fba553424f9d49ecb1ac324548d50a3a19c1af7d.zip
ContentTypeDetector should recognize future versions of Java class files (#952)
-rw-r--r--org.jacoco.core.test/src/org/jacoco/core/analysis/AnalyzerTest.java35
-rw-r--r--org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java35
-rw-r--r--org.jacoco.core.test/src/org/jacoco/core/internal/ContentTypeDetectorTest.java15
-rw-r--r--org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java30
-rw-r--r--org.jacoco.doc/docroot/doc/changes.html4
5 files changed, 97 insertions, 22 deletions
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 0e979f6c..f2a79515 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 @@ public class AnalyzerTest {
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 class AnalyzerTest {
}
}
+ /**
+ * @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(
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 79f11c6c..0fa42ecd 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 @@ public class InstrumenterTest {
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 class InstrumenterTest {
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());
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 d96c6683..a35c0e65 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
@@ -181,6 +181,21 @@ public class ContentTypeDetectorTest {
}
@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);
assertEquals(ContentTypeDetector.UNKNOWN, detector.getType());
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 9bf8ec2f..eefb9ef0 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.BufferedInputStream;
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.
*/
@@ -73,26 +71,14 @@ public class ContentTypeDetector {
case PACK200FILE:
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:
+ // 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 174ebe3e..ac3e8615 100644
--- a/org.jacoco.doc/docroot/doc/changes.html
+++ b/org.jacoco.doc/docroot/doc/changes.html
@@ -70,6 +70,10 @@
a coverage ratio limit is configured outside the range [0,1] to avoid
common configuration mistakes
(GitHub <a href="https://github.com/jacoco/jacoco/issues/783">#783</a>).</li>
+ <li>Unsupported class file versions are now consistently reported as exceptions
+ by all methods of <code>Analyzer</code> and <code>Instrumenter</code> and
+ thus also during report generation and offline instrumentation
+ (GitHub <a href="https://github.com/jacoco/jacoco/issues/952">#952</a>).</li>
</ul>
<h2>Release 0.8.4 (2019/05/08)</h2>