Replace ZipInputstream by ZipFile
- ZipInputStream does not allow to read STORED entries that have data
descriptor and it raises a ZipException. ZipInputStream seems to be
compliant with an old PKZIP specification where this constraint was
relaxed in later revision. Using ZipFile does not raise this error.
Bug: 65010447
Change-Id: I38f8c417639f20df766cbd59b940fc312b50fd6b
diff --git a/src/main/java/com/android/tools/r8/compatdx/CompatDx.java b/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
index 0c33273..20b656e 100644
--- a/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
+++ b/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
@@ -36,11 +36,11 @@
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
+import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipInputStream;
+import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
@@ -529,16 +529,16 @@
// For each input archive file, add all class files within.
for (Path input : inputs) {
if (isArchive(input)) {
- try (ZipInputStream in = new ZipInputStream(Files.newInputStream(input))) {
- ZipEntry entry;
- while ((entry = in.getNextEntry()) != null) {
+ try (ZipFile zipFile = new ZipFile(input.toFile())) {
+ final Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
if (isClassFile(Paths.get(entry.getName()))) {
- addEntry(entry.getName(), in, out);
+ try (InputStream entryStream = zipFile.getInputStream(entry)) {
+ addEntry(entry.getName(), entryStream, out);
+ }
}
}
- } catch (ZipException e) {
- throw new CompilationError(
- "Zip error while reading '" + input + "': " + e.getMessage(), e);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/PreloadedClassFileProvider.java b/src/main/java/com/android/tools/r8/utils/PreloadedClassFileProvider.java
index 07c136d..5ea2a30 100644
--- a/src/main/java/com/android/tools/r8/utils/PreloadedClassFileProvider.java
+++ b/src/main/java/com/android/tools/r8/utils/PreloadedClassFileProvider.java
@@ -16,15 +16,16 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
+import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipInputStream;
+import java.util.zip.ZipFile;
/** Lazy Java class file resource provider based on preloaded/prebuilt context. */
public final class PreloadedClassFileProvider implements ClassFileResourceProvider {
@@ -52,17 +53,17 @@
public static ClassFileResourceProvider fromArchive(Path archive) throws IOException {
assert isArchive(archive);
Builder builder = builder();
- try (ZipInputStream stream = new ZipInputStream(new FileInputStream(archive.toFile()))) {
- ZipEntry entry;
- while ((entry = stream.getNextEntry()) != null) {
+ try (ZipFile zipFile = new ZipFile(archive.toFile())) {
+ final Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
String name = entry.getName();
if (isClassFile(Paths.get(name))) {
- builder.addResource(guessTypeDescriptor(name), ByteStreams.toByteArray(stream));
+ try (InputStream entryStream = zipFile.getInputStream(entry)) {
+ builder.addResource(guessTypeDescriptor(name), ByteStreams.toByteArray(entryStream));
+ }
}
}
- } catch (ZipException e) {
- throw new CompilationError(
- "Zip error while reading '" + archive + "': " + e.getMessage(), e);
}
return builder.build();
diff --git a/src/main/java/com/android/tools/r8/utils/ProgramFileArchiveReader.java b/src/main/java/com/android/tools/r8/utils/ProgramFileArchiveReader.java
index 8341921..79ab853 100644
--- a/src/main/java/com/android/tools/r8/utils/ProgramFileArchiveReader.java
+++ b/src/main/java/com/android/tools/r8/utils/ProgramFileArchiveReader.java
@@ -10,17 +10,18 @@
import com.android.tools.r8.Resource;
import com.android.tools.r8.errors.CompilationError;
import com.google.common.io.ByteStreams;
-import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
-import java.util.zip.ZipInputStream;
+import java.util.zip.ZipFile;
class ProgramFileArchiveReader {
@@ -38,21 +39,24 @@
assert isArchive(archive);
dexResources = new ArrayList<>();
classResources = new ArrayList<>();
- try (ZipInputStream stream = new ZipInputStream(new FileInputStream(archive.toFile()))) {
- ZipEntry entry;
- while ((entry = stream.getNextEntry()) != null) {
- Path name = Paths.get(entry.getName());
- if (isDexFile(name)) {
- if (!ignoreDexInArchive) {
- Resource resource =
- new OneShotByteResource(Resource.Kind.DEX, ByteStreams.toByteArray(stream), null);
- dexResources.add(resource);
+ try (ZipFile zipFile = new ZipFile(archive.toFile())) {
+ final Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ try (InputStream stream = zipFile.getInputStream(entry)) {
+ Path name = Paths.get(entry.getName());
+ if (isDexFile(name)) {
+ if (!ignoreDexInArchive) {
+ Resource resource =
+ new OneShotByteResource(Resource.Kind.DEX, ByteStreams.toByteArray(stream), null);
+ dexResources.add(resource);
+ }
+ } else if (isClassFile(name)) {
+ String descriptor = PreloadedClassFileProvider.guessTypeDescriptor(name);
+ Resource resource = new OneShotByteResource(Resource.Kind.CLASSFILE,
+ ByteStreams.toByteArray(stream), Collections.singleton(descriptor));
+ classResources.add(resource);
}
- } else if (isClassFile(name)) {
- String descriptor = PreloadedClassFileProvider.guessTypeDescriptor(name);
- Resource resource = new OneShotByteResource(Resource.Kind.CLASSFILE,
- ByteStreams.toByteArray(stream), Collections.singleton(descriptor));
- classResources.add(resource);
}
}
} catch (ZipException e) {
diff --git a/src/main/java/com/android/tools/r8/utils/ZipUtils.java b/src/main/java/com/android/tools/r8/utils/ZipUtils.java
index 47d8e01..ca9a404 100644
--- a/src/main/java/com/android/tools/r8/utils/ZipUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ZipUtils.java
@@ -6,27 +6,31 @@
import com.android.tools.r8.errors.CompilationError;
import com.google.common.io.ByteStreams;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.Enumeration;
import java.util.List;
import java.util.function.Predicate;
import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
+import java.util.zip.ZipFile;
public class ZipUtils {
public interface OnEntryHandler {
- void onEntry(ZipEntry entry, ZipInputStream input) throws IOException;
+ void onEntry(ZipEntry entry, InputStream input) throws IOException;
}
- public static void iter(String zipFile, OnEntryHandler handler) throws IOException {
- try (ZipInputStream input = new ZipInputStream(new FileInputStream(zipFile))){
- ZipEntry entry;
- while ((entry = input.getNextEntry()) != null) {
- handler.onEntry(entry, input);
+ public static void iter(String zipFileStr, OnEntryHandler handler) throws IOException {
+ try (ZipFile zipFile = new ZipFile(zipFileStr)) {
+ final Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ try (InputStream entryStream = zipFile.getInputStream(entry)) {
+ handler.onEntry(entry, entryStream);
+ }
}
}
}
diff --git a/src/test/java/com/android/tools/r8/shaking/includedescriptorclasses/IncludeDescriptorClassesTest.java b/src/test/java/com/android/tools/r8/shaking/includedescriptorclasses/IncludeDescriptorClassesTest.java
index a02a186..5ad5787 100644
--- a/src/test/java/com/android/tools/r8/shaking/includedescriptorclasses/IncludeDescriptorClassesTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/includedescriptorclasses/IncludeDescriptorClassesTest.java
@@ -13,15 +13,15 @@
import com.android.tools.r8.utils.DexInspector;
import com.google.common.collect.ImmutableList;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
+import java.util.zip.ZipFile;
import org.junit.Test;
public class IncludeDescriptorClassesTest extends TestBase {
@@ -51,14 +51,14 @@
private Set<String> readJarClasses(Path jar) throws IOException {
Set<String> result = new HashSet<>();
- try (ZipInputStream in = new ZipInputStream(new FileInputStream(jar.toFile()))) {
- ZipEntry entry = in.getNextEntry();
- while (entry != null) {
+ try (ZipFile zipFile = new ZipFile(jar.toFile())) {
+ final Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
String name = entry.getName();
if (name.endsWith(".class")) {
result.add(name.substring(0, name.length() - ".class".length()).replace('/', '.'));
}
- entry = in.getNextEntry();
}
}
return result;