diff --git a/dexlib/src/main/java/org/jf/dexlib/DexFile.java b/dexlib/src/main/java/org/jf/dexlib/DexFile.java index bd9731b0..4ac21ff6 100644 --- a/dexlib/src/main/java/org/jf/dexlib/DexFile.java +++ b/dexlib/src/main/java/org/jf/dexlib/DexFile.java @@ -33,8 +33,7 @@ import org.jf.dexlib.*; import org.jf.dexlib.Item; import org.jf.dexlib.StringDataItem; -import java.io.File; -import java.io.UnsupportedEncodingException; +import java.io.*; import java.security.DigestException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -43,6 +42,9 @@ import java.util.Arrays; import java.util.Comparator; import java.util.Collections; import java.util.zip.Adler32; +import java.util.zip.ZipFile; +import java.util.zip.ZipException; +import java.util.zip.ZipEntry; /** *
getPreserveSignedRegisters()
+ * @throws IOException if an IOException occurs
*/
- public DexFile(String file, boolean preserveSignedRegisters) {
+ public DexFile(String file, boolean preserveSignedRegisters)
+ throws IOException {
this(new File(file), preserveSignedRegisters);
}
/**
* Construct a new DexFile instance by reading in the given dex file.
* @param file The dex file to read in
+ * @throws IOException if an IOException occurs
*/
- public DexFile(File file) {
+ public DexFile(File file)
+ throws IOException {
this(file, true);
}
@@ -270,14 +278,54 @@ public class DexFile
* @param preserveSignedRegisters If true, keep track of any registers in the debug information
* that are signed, so they will be written in the same format.
* @see #getPreserveSignedRegisters
+ * @throws IOException if an IOException occurs
*/
- public DexFile(File file, boolean preserveSignedRegisters) {
+ public DexFile(File file, boolean preserveSignedRegisters)
+ throws IOException {
this(preserveSignedRegisters);
+ long fileLength;
+ InputStream inputStream;
byte[] magic = FileUtils.readFile(file, 0, 8);
+
+ //do we have a zip file?
+ if (magic[0] == 0x50 && magic[1] == 0x4B) {
+ ZipFile zipFile = new ZipFile(file);
+ ZipEntry zipEntry = zipFile.getEntry("classes.dex");
+ if (zipEntry == null) {
+ throw new RuntimeException("zip file " + file.getName() + " does not contain a classes.dex file");
+ }
+ fileLength = zipEntry.getSize();
+ if (fileLength < 40) {
+ throw new RuntimeException("The classes.dex file in " + file.getName() + " is too small to be a" +
+ " valid dex file");
+ } else if (fileLength > Integer.MAX_VALUE) {
+ throw new RuntimeException("The classes.dex file in " + file.getName() + " is too large to read in");
+ }
+ inputStream = new BufferedInputStream(zipFile.getInputStream(zipEntry));
+
+ inputStream.mark(8);
+ for (int i=0; i<8; i++) {
+ magic[i] = (byte)inputStream.read();
+ }
+ inputStream.reset();
+
+ } else {
+ fileLength = file.length();
+ if (fileLength < 40) {
+ throw new RuntimeException(file.getName() + " is too small to be a valid dex file");
+ }
+ if (fileLength < 40) {
+ throw new RuntimeException(file.getName() + " is too small to be a valid dex file");
+ } else if (fileLength > Integer.MAX_VALUE) {
+ throw new RuntimeException(file.getName() + " is too large to read in");
+ }
+ inputStream = new FileInputStream(file);
+ }
+
byte[] dexMagic, odexMagic;
- dexMagic = HeaderItem.MAGIC;
+ dexMagic = org.jf.dexlib.HeaderItem.MAGIC;
odexMagic = OdexHeaderItem.MAGIC;
boolean isDex = true;
@@ -294,20 +342,18 @@ public class DexFile
Input in;
if (isOdex) {
- byte[] odexHeaderBytes = FileUtils.readFile(file, 0, 40);
+ byte[] odexHeaderBytes = FileUtils.readStream(inputStream, 40);
Input odexHeaderIn = new ByteArrayInput(odexHeaderBytes);
OdexHeaderItem odexHeader = new OdexHeaderItem(odexHeaderIn);
- in = new ByteArrayInput(FileUtils.readFile(file, odexHeader.dexOffset, odexHeader.dexLength));
+ in = new ByteArrayInput(FileUtils.readStream(inputStream, odexHeader.dexLength));
} else if (isDex) {
- in = new ByteArrayInput(FileUtils.readFile(file));
+ in = new ByteArrayInput(FileUtils.readStream(inputStream, (int)fileLength));
} else {
-
- StringBuilder sb = new StringBuilder();
- sb.append("bad magic value:");
+ StringBuffer sb = new StringBuffer("bad magic value:");
for (int i=0; i<8; i++) {
sb.append(" ");
- sb.append(magic[i]);
+ sb.append(Hex.u1(magic[i]));
}
throw new RuntimeException(sb.toString());
}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Util/FileUtils.java b/dexlib/src/main/java/org/jf/dexlib/Util/FileUtils.java
index e081a832..668a529f 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Util/FileUtils.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Util/FileUtils.java
@@ -19,6 +19,7 @@ package org.jf.dexlib.Util;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
/**
* File I/O utilities.
@@ -38,7 +39,8 @@ public final class FileUtils {
* @param fileName non-null; name of the file to read
* @return non-null; contents of the file
*/
- public static byte[] readFile(String fileName) {
+ public static byte[] readFile(String fileName)
+ throws IOException {
File file = new File(fileName);
return readFile(file);
}
@@ -50,7 +52,8 @@ public final class FileUtils {
* @param file non-null; the file to read
* @return non-null; contents of the file
*/
- public static byte[] readFile(File file) {
+ public static byte[] readFile(File file)
+ throws IOException {
return readFile(file, 0, -1);
}
@@ -64,7 +67,8 @@ public final class FileUtils {
* end of the file
* @return non-null; contents of the file
*/
- public static byte[] readFile(File file, int offset, int length) {
+ public static byte[] readFile(File file, int offset, int length)
+ throws IOException {
if (!file.exists()) {
throw new RuntimeException(file + ": file not found");
}
@@ -91,33 +95,38 @@ public final class FileUtils {
throw new RuntimeException(file + ": file too short");
}
- byte[] result = new byte[length];
+ FileInputStream in = new FileInputStream(file);
- try {
- FileInputStream in = new FileInputStream(file);
-
- int at = offset;
- while(at > 0) {
- long amt = in.skip(at);
- if (amt == -1) {
- throw new RuntimeException(file + ": unexpected EOF");
- }
- at -= amt;
+ int at = offset;
+ while(at > 0) {
+ long amt = in.skip(at);
+ if (amt == -1) {
+ throw new RuntimeException(file + ": unexpected EOF");
}
-
- while (length > 0) {
- int amt = in.read(result, at, length);
- if (amt == -1) {
- throw new RuntimeException(file + ": unexpected EOF");
- }
- at += amt;
- length -= amt;
- }
- in.close();
- } catch (IOException ex) {
- throw new RuntimeException(file + ": trouble reading", ex);
+ at -= amt;
}
+ byte[] result = readStream(in, length);
+
+ in.close();
+
+ return result;
+ }
+
+ public static byte[] readStream(InputStream in, int length)
+ throws IOException {
+ byte[] result = new byte[length];
+ int at=0;
+
+ while (length > 0) {
+ int amt = in.read(result, at, length);
+ if (amt == -1) {
+ throw new RuntimeException("unexpected EOF");
+ }
+ at += amt;
+ length -= amt;
+ }
+
return result;
}
}