fix: don't use FileChannel on ZipFs to avoid creation of temp files (#950)
This commit is contained in:
+18
-22
@@ -1,8 +1,7 @@
|
||||
package jadx.plugins.input.dex;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.FileVisitResult;
|
||||
@@ -12,7 +11,6 @@ import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -35,11 +33,15 @@ public class DexFileLoader {
|
||||
}
|
||||
|
||||
private static List<DexReader> loadDexFromPath(Path path, int depth) {
|
||||
try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ)) {
|
||||
if (isDex(fileChannel)) {
|
||||
return Collections.singletonList(new DexReader(path, fileChannel));
|
||||
try (InputStream inputStream = Files.newInputStream(path, StandardOpenOption.READ)) {
|
||||
byte[] magic = new byte[DexConsts.MAX_MAGIC_SIZE];
|
||||
if (inputStream.read(magic) != magic.length) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (depth == 0 && isZip(fileChannel)) {
|
||||
if (isStartWithBytes(magic, DexConsts.DEX_FILE_MAGIC)) {
|
||||
return Collections.singletonList(new DexReader(path));
|
||||
}
|
||||
if (depth == 0 && isStartWithBytes(magic, DexConsts.ZIP_FILE_MAGIC)) {
|
||||
return collectDexFromZip(path, depth);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -64,22 +66,16 @@ public class DexFileLoader {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean isDex(FileChannel fileChannel) {
|
||||
return isStartWithBytes(fileChannel, DexConsts.DEX_FILE_MAGIC);
|
||||
}
|
||||
|
||||
private static boolean isZip(FileChannel fileChannel) {
|
||||
return isStartWithBytes(fileChannel, DexConsts.ZIP_FILE_MAGIC);
|
||||
}
|
||||
|
||||
private static boolean isStartWithBytes(FileChannel fileChannel, byte[] startBytes) {
|
||||
try {
|
||||
fileChannel.position(0);
|
||||
ByteBuffer buf = ByteBuffer.allocate(startBytes.length);
|
||||
fileChannel.read(buf);
|
||||
return Arrays.equals(startBytes, buf.array());
|
||||
} catch (Exception e) {
|
||||
private static boolean isStartWithBytes(byte[] fileMagic, byte[] expectedBytes) {
|
||||
int len = expectedBytes.length;
|
||||
if (fileMagic.length < len) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (fileMagic[i] != expectedBytes[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package jadx.plugins.input.dex;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -17,32 +17,15 @@ import jadx.plugins.input.dex.sections.annotations.AnnotationsParser;
|
||||
public class DexReader implements Closeable {
|
||||
|
||||
private final Path path;
|
||||
private final FileChannel fileChannel;
|
||||
private final ByteBuffer buf;
|
||||
private final DexHeader header;
|
||||
|
||||
public DexReader(Path path, FileChannel fileChannel) throws IOException {
|
||||
public DexReader(Path path) throws IOException {
|
||||
this.path = path;
|
||||
this.fileChannel = fileChannel;
|
||||
this.buf = loadIntoByteBuffer(fileChannel);
|
||||
this.buf = ByteBuffer.wrap(Files.readAllBytes(path));
|
||||
this.header = new DexHeader(new SectionReader(this, 0));
|
||||
}
|
||||
|
||||
private static ByteBuffer loadIntoByteBuffer(FileChannel fileChannel) throws IOException {
|
||||
long size = fileChannel.size();
|
||||
if (size > Integer.MAX_VALUE) {
|
||||
throw new IOException("File too big");
|
||||
}
|
||||
int readSize = (int) size;
|
||||
ByteBuffer buf = ByteBuffer.allocate(readSize);
|
||||
fileChannel.position(0);
|
||||
int read = fileChannel.read(buf);
|
||||
if (read != readSize) {
|
||||
throw new IOException("Failed to read whole file into buffer. Read: " + read + ", expected: " + readSize);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
public String getDexVersion() {
|
||||
return this.header.getVersion();
|
||||
}
|
||||
@@ -86,7 +69,6 @@ public class DexReader implements Closeable {
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
this.fileChannel.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
@@ -6,6 +6,8 @@ public class DexConsts {
|
||||
|
||||
public static final byte[] ZIP_FILE_MAGIC = { 0x50, 0x4B, 0x03, 0x04 };
|
||||
|
||||
public static final int MAX_MAGIC_SIZE = 4;
|
||||
|
||||
public static final int ENDIAN_CONSTANT = 0x12345678;
|
||||
|
||||
public static final int NO_INDEX = -1;
|
||||
|
||||
Reference in New Issue
Block a user