Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8273401: Remove JarIndex support in URLClassPath #5383

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/java.base/share/classes/java/util/jar/JarFile.java
Original file line number Diff line number Diff line change
@@ -214,6 +214,11 @@ public class JarFile extends ZipFile {
*/
public static final String MANIFEST_NAME = META_INF + "MANIFEST.MF";

/**
* The index file name.
*/
static final String INDEX_NAME = "META-INF/INDEX.LIST";

/**
* Returns the version that represents the unversioned configuration of a
* multi-release jar file.
Original file line number Diff line number Diff line change
@@ -28,7 +28,6 @@
import java.util.zip.*;
import java.io.*;
import sun.security.util.ManifestEntryVerifier;
import jdk.internal.util.jar.JarIndex;

/**
* The {@code JarInputStream} class is used to read the contents of
@@ -133,7 +132,7 @@ public ZipEntry getNextEntry() throws IOException {
}
} else {
e = first;
if (first.getName().equalsIgnoreCase(JarIndex.INDEX_NAME))
if (first.getName().equalsIgnoreCase(JarFile.INDEX_NAME))
tryManifest = true;
first = null;
}
3 changes: 1 addition & 2 deletions src/java.base/share/classes/java/util/jar/JarVerifier.java
Original file line number Diff line number Diff line change
@@ -32,7 +32,6 @@
import java.security.cert.CertificateException;
import java.util.zip.ZipEntry;

import jdk.internal.util.jar.JarIndex;
import sun.security.util.ManifestDigester;
import sun.security.util.ManifestEntryVerifier;
import sun.security.util.SignatureFileVerifier;
@@ -145,7 +144,7 @@ public void beginEntry(JarEntry je, ManifestEntryVerifier mev)
}

if (uname.equals(JarFile.MANIFEST_NAME) ||
uname.equals(JarIndex.INDEX_NAME)) {
uname.equals(JarFile.INDEX_NAME)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be useful if someone from security-libs could comment on this. The interaction between signed JAR and JAR index isn't very clear. The change you have is safe but it might be that we can drop the checking for INDEX.LIST here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking this line should not be removed for compatibility with existing JARs that have indexes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still keep the code

return;
}

192 changes: 1 addition & 191 deletions src/java.base/share/classes/jdk/internal/loader/URLClassPath.java
Original file line number Diff line number Diff line change
@@ -70,8 +70,6 @@
import jdk.internal.access.JavaNetURLAccess;
import jdk.internal.access.JavaUtilZipFileAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.util.jar.InvalidJarIndexError;
import jdk.internal.util.jar.JarIndex;
import sun.net.util.URLUtil;
import sun.net.www.ParseUtil;
import sun.security.action.GetPropertyAction;
@@ -434,9 +432,7 @@ private synchronized Loader getLoader(int index) {
if (url == null)
return null;
}
// Skip this URL if it already has a Loader. (Loader
// may be null in the case where URL has not been opened
// but is referenced by a JAR index.)
// Skip this URL if it already has a Loader.
String urlNoFragString = URLUtil.urlNoFragString(url);
if (lmap.containsKey(urlNoFragString)) {
continue;
@@ -706,7 +702,6 @@ URL[] getClassPath() throws IOException {
private static class JarLoader extends Loader {
private JarFile jar;
private final URL csu;
private JarIndex index;
private URLStreamHandler handler;
private final HashMap<String, Loader> lmap;
@SuppressWarnings("removal")
@@ -765,27 +760,6 @@ public Void run() throws IOException {
}

jar = getJarFile(csu);
index = JarIndex.getJarIndex(jar);
if (index != null) {
String[] jarfiles = index.getJarFiles();
// Add all the dependent URLs to the lmap so that loaders
// will not be created for them by URLClassPath.getLoader(int)
// if the same URL occurs later on the main class path. We set
// Loader to null here to avoid creating a Loader for each
// URL until we actually need to try to load something from them.
for (int i = 0; i < jarfiles.length; i++) {
try {
URL jarURL = new URL(csu, jarfiles[i]);
// If a non-null loader already exists, leave it alone.
String urlNoFragString = URLUtil.urlNoFragString(jarURL);
if (!lmap.containsKey(urlNoFragString)) {
lmap.put(urlNoFragString, null);
}
} catch (MalformedURLException e) {
continue;
}
}
}
return null;
}
}, acc);
@@ -828,18 +802,6 @@ private JarFile getJarFile(URL url) throws IOException {
return checkJar(jarFile);
}

/*
* Returns the index of this JarLoader if it exists.
*/
JarIndex getIndex() {
try {
ensureOpen();
} catch (IOException e) {
throw new InternalError(e);
}
return index;
}

/*
* Creates the resource and if the check flag is set to true, checks if
* is its okay to return the resource.
@@ -887,33 +849,6 @@ public CodeSigner[] getCodeSigners()
};
}


/*
* Returns true iff at least one resource in the jar file has the same
* package name as that of the specified resource name.
*/
boolean validIndex(final String name) {
String packageName = name;
int pos;
if ((pos = name.lastIndexOf('/')) != -1) {
packageName = name.substring(0, pos);
}

String entryName;
ZipEntry entry;
Enumeration<JarEntry> enum_ = jar.entries();
while (enum_.hasMoreElements()) {
entry = enum_.nextElement();
entryName = entry.getName();
if ((pos = entryName.lastIndexOf('/')) != -1)
entryName = entryName.substring(0, pos);
if (entryName.equals(packageName)) {
return true;
}
}
return false;
}

/*
* Returns the URL for a resource with the specified name
*/
@@ -940,139 +875,14 @@ Resource getResource(final String name, boolean check) {
if (entry != null)
return checkResource(name, check, entry);

if (index == null)
return null;

HashSet<String> visited = new HashSet<>();
return getResource(name, check, visited);
}

/*
* Version of getResource() that tracks the jar files that have been
* visited by linking through the index files. This helper method uses
* a HashSet to store the URLs of jar files that have been searched and
* uses it to avoid going into an infinite loop, looking for a
* non-existent resource.
*/
@SuppressWarnings("removal")
Resource getResource(final String name, boolean check,
Set<String> visited) {
Resource res;
String[] jarFiles;
int count = 0;
List<String> jarFilesList;

/* If there no jar files in the index that can potential contain
* this resource then return immediately.
*/
if ((jarFilesList = index.get(name)) == null)
return null;

do {
int size = jarFilesList.size();
jarFiles = jarFilesList.toArray(new String[size]);
/* loop through the mapped jar file list */
while (count < size) {
String jarName = jarFiles[count++];
JarLoader newLoader;
final URL url;

try{
url = new URL(csu, jarName);
String urlNoFragString = URLUtil.urlNoFragString(url);
if ((newLoader = (JarLoader)lmap.get(urlNoFragString)) == null) {
/* no loader has been set up for this jar file
* before
*/
newLoader = AccessController.doPrivileged(
new PrivilegedExceptionAction<>() {
public JarLoader run() throws IOException {
return new JarLoader(url, handler,
lmap, acc);
}
}, acc);

/* this newly opened jar file has its own index,
* merge it into the parent's index, taking into
* account the relative path.
*/
JarIndex newIndex = newLoader.getIndex();
if (newIndex != null) {
int pos = jarName.lastIndexOf('/');
newIndex.merge(this.index, (pos == -1 ?
null : jarName.substring(0, pos + 1)));
}

/* put it in the global hashtable */
lmap.put(urlNoFragString, newLoader);
}
} catch (PrivilegedActionException pae) {
continue;
} catch (MalformedURLException e) {
continue;
}

/* Note that the addition of the url to the list of visited
* jars incorporates a check for presence in the hashmap
*/
boolean visitedURL = !visited.add(URLUtil.urlNoFragString(url));
if (!visitedURL) {
try {
newLoader.ensureOpen();
} catch (IOException e) {
throw new InternalError(e);
}
final JarEntry entry = newLoader.jar.getJarEntry(name);
if (entry != null) {
return newLoader.checkResource(name, check, entry);
}

/* Verify that at least one other resource with the
* same package name as the lookedup resource is
* present in the new jar
*/
if (!newLoader.validIndex(name)) {
/* the mapping is wrong */
throw new InvalidJarIndexError("Invalid index");
}
}

/* If newLoader is the current loader or if it is a
* loader that has already been searched or if the new
* loader does not have an index then skip it
* and move on to the next loader.
*/
if (visitedURL || newLoader == this ||
newLoader.getIndex() == null) {
continue;
}

/* Process the index of the new loader
*/
if ((res = newLoader.getResource(name, check, visited))
!= null) {
return res;
}
}
// Get the list of jar files again as the list could have grown
// due to merging of index files.
jarFilesList = index.get(name);

// If the count is unchanged, we are done.
} while (count < jarFilesList.size());
return null;
}


/*
* Returns the JAR file local class path, or null if none.
*/
@Override
URL[] getClassPath() throws IOException {
if (index != null) {
return null;
}

ensureOpen();

// Only get manifest when necessary
3 changes: 2 additions & 1 deletion src/java.base/share/classes/module-info.java
Original file line number Diff line number Diff line change
@@ -298,7 +298,8 @@
java.desktop,
java.security.jgss,
jdk.crypto.ec,
jdk.incubator.foreign;
jdk.incubator.foreign,
jdk.jartool;
exports sun.security.internal.interfaces to
jdk.crypto.cryptoki;
exports sun.security.internal.spec to
Original file line number Diff line number Diff line change
@@ -23,15 +23,14 @@
* questions.
*/

package jdk.internal.util.jar;

import sun.nio.cs.UTF_8;
package sun.tools.jar;

import java.io.*;
import java.util.*;
import java.util.jar.*;
import java.util.zip.*;

import static java.nio.charset.StandardCharsets.UTF_8;
import static sun.security.action.GetPropertyAction.privilegedGetProperty;

/**
@@ -67,7 +66,7 @@ public class JarIndex {

/**
* The index file name.
*/
*/
public static final String INDEX_NAME = "META-INF/INDEX.LIST";

/**
@@ -253,7 +252,7 @@ private void parseJars(String[] files) throws IOException {
*/
public void write(OutputStream out) throws IOException {
BufferedWriter bw = new BufferedWriter
(new OutputStreamWriter(out, UTF_8.INSTANCE));
(new OutputStreamWriter(out, UTF_8));
bw.write("JarIndex-Version: 1.0\n\n");

if (jarFiles != null) {
@@ -283,7 +282,7 @@ public void write(OutputStream out) throws IOException {
*/
public void read(InputStream is) throws IOException {
BufferedReader br = new BufferedReader
(new InputStreamReader(is, UTF_8.INSTANCE));
(new InputStreamReader(is, UTF_8));
String line;
String currentJar = null;

5 changes: 2 additions & 3 deletions src/jdk.jartool/share/classes/sun/tools/jar/Main.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -66,12 +66,11 @@
import jdk.internal.module.ModuleInfoExtender;
import jdk.internal.module.ModuleResolution;
import jdk.internal.module.ModuleTarget;
import jdk.internal.util.jar.JarIndex;

import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import static java.util.jar.JarFile.MANIFEST_NAME;
import static java.util.stream.Collectors.joining;
import static jdk.internal.util.jar.JarIndex.INDEX_NAME;
import static sun.tools.jar.JarIndex.INDEX_NAME;

/**
* This class implements a simple utility for creating files in the JAR
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,8 +24,8 @@
/*
* @test
* @bug 6901992
* @summary InvalidJarIndexException due to bug in sun.misc.JarIndex.merge()
* @modules java.base/jdk.internal.util.jar
* @summary InvalidJarIndexException due to bug in sun.tools.jar.JarIndex.merge()
* @modules jdk.jartool/sun.tools.jar
* @compile -XDignore.symbol.file JarIndexMergeTest.java
* @run main JarIndexMergeTest
* @author Diego Belfer
@@ -39,7 +39,7 @@
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
// implementation specific API
import jdk.internal.util.jar.JarIndex;
import sun.tools.jar.JarIndex;

public class JarIndexMergeTest {
static final String slash = File.separator;
215 changes: 0 additions & 215 deletions test/jdk/sun/misc/JarIndex/JarIndexMergeForClassLoaderTest.java

This file was deleted.

406 changes: 0 additions & 406 deletions test/jdk/sun/misc/JarIndex/metaInfFilenames/Basic.java

This file was deleted.

This file was deleted.

30 changes: 0 additions & 30 deletions test/jdk/sun/misc/JarIndex/metaInfFilenames/jarA/a/A.java

This file was deleted.

This file was deleted.

23 changes: 0 additions & 23 deletions test/jdk/sun/misc/JarIndex/metaInfFilenames/jarB/META-INF/JAVA2.DS

This file was deleted.

This file was deleted.

30 changes: 0 additions & 30 deletions test/jdk/sun/misc/JarIndex/metaInfFilenames/jarB/b/B.java

This file was deleted.

23 changes: 0 additions & 23 deletions test/jdk/sun/misc/JarIndex/metaInfFilenames/jarC/META-INF/fonts.mf

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.