Skip to content

Commit

Permalink
Issue #1797 - Safety checks for Java 9 and Multi-Release JARs during …
Browse files Browse the repository at this point in the history
…bytecode scanning
  • Loading branch information
joakime committed Sep 7, 2017
1 parent fb86b8e commit e3b628a
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,30 @@ public class AnnotationParser
{
private static final Logger LOG = Log.getLogger(AnnotationParser.class);

private static final int JVM_MAJOR_VER;

protected Set<String> _parsedClassNames = ConcurrentHashMap.newKeySet();

protected static int ASM_OPCODE_VERSION = Opcodes.ASM5; //compatibility of api


static
{
// Determine JVM spec version
// Using guidance from http://openjdk.java.net/jeps/223
String jvmSpecVer = System.getProperty("java.vm.specification.version");

if (jvmSpecVer.indexOf('.') >= 0)
{
// Old spec version (Java 1.8 and older)
String parts[] = jvmSpecVer.split("\\.");
JVM_MAJOR_VER = Integer.parseInt(parts[1]);
}
else
{
// Newer spec version (Java 9+)
JVM_MAJOR_VER = Integer.parseInt(jvmSpecVer);
}
}

/**
* Convert internal name to simple name
Expand Down Expand Up @@ -1017,10 +1037,61 @@ private boolean isValidClassFilePath (String path)
if (path == null || path.length()==0)
return false;

//skip any classfiles that are in a hidden directory
if (path.startsWith("META-INF/versions/"))
{
// Handle JEP 238 - Multi-Release Jars
if (JVM_MAJOR_VER < 9)
{
if (LOG.isDebugEnabled())
{
LOG.debug("JEP-238 Multi-Release JAR not supported on Java " +
System.getProperty("java.version") + ": " + path);
}
return false;
}

// Safety check for ASM bytecode support level.
// When ASM 6.0 is integrated, the below will start to work.
if (ASM_OPCODE_VERSION <= Opcodes.ASM5)

This comment has been minimized.

Copy link
@janbartel

janbartel Sep 8, 2017

Contributor

I don't think we need to check the jvm version. All we need to do is check the ASM version. If ASM < 6 then don't parse META-INF/versions.

{
// Cannot scan Java 9 classes with ASM version 5
if (LOG.isDebugEnabled())
{
LOG.debug("Unable to scan newer Java bytecode (Java 9?) with ASM 5 (skipping): " + path);
}
return false;
}

int idxStart = "META-INF/versions/".length();

This comment has been minimized.

Copy link
@janbartel

janbartel Sep 8, 2017

Contributor

Again, I don't think we need to check for this, simple skip all META-INF/versions iff asm < 6.

int idxEnd = path.indexOf('/', idxStart + 1);
try
{
int pathVersion = Integer.parseInt(path.substring(idxStart, idxEnd));
if (pathVersion < JVM_MAJOR_VER)
{
if (LOG.isDebugEnabled())
{
LOG.debug("JEP-238 Multi-Release JAR version " + pathVersion +
" not supported on Java " + System.getProperty("java.version") +
": " + path);
}
return false;
}
}
catch (NumberFormatException e)
{
if (LOG.isDebugEnabled())
{
LOG.debug("Not a valid JEP-238 Multi-Release path: " + path);
}
return false;
}
}

// skip any classfiles that are in a hidden directory
if (path.startsWith(".") || path.contains("/."))
{
if (LOG.isDebugEnabled()) LOG.debug("Contains hidden dirs: {}"+path);
if (LOG.isDebugEnabled()) LOG.debug("Contains hidden dirs: " + path);
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,26 @@ public void testHiddenFilesInJar() throws Exception
// only the valid classes inside bad-classes.jar should be parsed. If any invalid classes are parsed and exception would be thrown here
}

@Test
public void testModuleInfoClassInJar() throws Exception
{
File badClassesJar = MavenTestingUtils.getTestResourceFile("jdk9/slf4j-api-1.8.0-alpha2.jar");
AnnotationParser parser = new AnnotationParser();
Set<Handler> emptySet = Collections.emptySet();
parser.parse(emptySet, badClassesJar.toURI());
// Should throw no exceptions, and happily skip the module-info.class files
}

@Test
public void testJep238MultiReleaseInJar() throws Exception
{
File badClassesJar = MavenTestingUtils.getTestResourceFile("jdk9/log4j-api-2.9.0.jar");
AnnotationParser parser = new AnnotationParser();
Set<Handler> emptySet = Collections.emptySet();
parser.parse(emptySet, badClassesJar.toURI());
// Should throw no exceptions, and skip the META-INF/versions/9/* files
}

@Test
public void testBasedirExclusion() throws Exception
{
Expand Down
Binary file not shown.
Binary file not shown.

0 comments on commit e3b628a

Please sign in to comment.