fix: don't use FileChannel on ZipFs to avoid creation of temp files (#950)

This commit is contained in:
Skylot
2020-06-10 20:43:39 +03:00
parent 65553c156c
commit a83ca1f85b
3 changed files with 23 additions and 43 deletions
@@ -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
@@ -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;