未验证 提交 35116d0b 编写于 作者: S Skylot

fix: load files also by extension (#1391)

上级 3b781e41
......@@ -13,9 +13,11 @@ import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.plugins.utils.CommonFileUtils;
import jadx.api.plugins.utils.ZipSecurity;
import jadx.plugins.input.dex.sections.DexConsts;
import jadx.plugins.input.dex.utils.DexCheckSum;
......@@ -45,31 +47,34 @@ public class DexFileLoader {
private List<DexReader> loadDexFromFile(File file) {
try (InputStream inputStream = new FileInputStream(file)) {
return checkFileMagic(file, inputStream, file.getAbsolutePath());
return load(file, inputStream, file.getAbsolutePath());
} catch (Exception e) {
LOG.error("File open error: {}", file.getAbsolutePath(), e);
return Collections.emptyList();
}
}
private List<DexReader> checkFileMagic(File file, InputStream inputStream, String inputFileName) throws IOException {
private List<DexReader> load(@Nullable File file, InputStream inputStream, String fileName) throws IOException {
try (InputStream in = inputStream.markSupported() ? inputStream : new BufferedInputStream(inputStream)) {
byte[] magic = new byte[DexConsts.MAX_MAGIC_SIZE];
in.mark(magic.length);
if (in.read(magic) != magic.length) {
return Collections.emptyList();
}
if (isStartWithBytes(magic, DexConsts.DEX_FILE_MAGIC)) {
if (isStartWithBytes(magic, DexConsts.DEX_FILE_MAGIC) || fileName.endsWith(".dex")) {
in.reset();
byte[] content = readAllBytes(in);
if (options.isVerifyChecksum()) {
DexCheckSum.verify(content);
}
DexReader dexReader = new DexReader(getNextUniqId(), inputFileName, content);
DexReader dexReader = new DexReader(getNextUniqId(), fileName, content);
return Collections.singletonList(dexReader);
}
if (file != null && isStartWithBytes(magic, DexConsts.ZIP_FILE_MAGIC)) {
return collectDexFromZip(file);
if (file != null) {
// allow only top level zip files
if (isStartWithBytes(magic, DexConsts.ZIP_FILE_MAGIC) || CommonFileUtils.isZipFileExt(fileName)) {
return collectDexFromZip(file);
}
}
return Collections.emptyList();
}
......@@ -80,7 +85,7 @@ public class DexFileLoader {
try {
ZipSecurity.readZipEntries(file, (entry, in) -> {
try {
result.addAll(checkFileMagic(null, in, entry.getName()));
result.addAll(load(null, in, entry.getName()));
} catch (Exception e) {
LOG.error("Failed to read zip entry: {}", entry, e);
}
......
......@@ -52,18 +52,20 @@ public class JavaFileLoader {
if (in.read(magic) != magic.length) {
return Collections.emptyList();
}
if (isStartWithBytes(magic, JAVA_CLASS_FILE_MAGIC)) {
if (isStartWithBytes(magic, JAVA_CLASS_FILE_MAGIC) || name.endsWith(".class")) {
byte[] data = CommonFileUtils.loadBytes(magic, in);
String source = concatSource(parentFileName, name);
JavaClassReader reader = new JavaClassReader(getNextUniqId(), source, data);
return Collections.singletonList(reader);
}
if (isStartWithBytes(magic, ZIP_FILE_MAGIC)) {
if (isStartWithBytes(magic, ZIP_FILE_MAGIC) || CommonFileUtils.isZipFileExt(name)) {
if (file != null) {
return collectFromZip(file, name);
}
File zipFile = CommonFileUtils.saveToTempFile(magic, in, ".zip").toFile();
return collectFromZip(zipFile, concatSource(parentFileName, name));
List<JavaClassReader> readers = collectFromZip(zipFile, concatSource(parentFileName, name));
CommonFileUtils.safeDeleteFile(zipFile);
return readers;
}
return Collections.emptyList();
}
......
......@@ -7,9 +7,15 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Set;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CommonFileUtils {
private static final Logger LOG = LoggerFactory.getLogger(CommonFileUtils.class);
public static final File CWD = getCWD();
public static final Path CWD_PATH = CWD.toPath();
......@@ -38,6 +44,15 @@ public class CommonFileUtils {
return tempFile;
}
public static boolean safeDeleteFile(File file) {
try {
return file.delete();
} catch (Exception e) {
LOG.warn("Failed to delete file: {}", file, e);
return false;
}
}
public static byte[] loadBytes(InputStream input) throws IOException {
return loadBytes(null, input);
}
......@@ -56,7 +71,7 @@ public class CommonFileUtils {
}
public static void copyStream(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[8 * 1024];
byte[] buffer = new byte[8192];
while (true) {
int count = input.read(buffer);
if (count == -1) {
......@@ -65,4 +80,23 @@ public class CommonFileUtils {
output.write(buffer, 0, count);
}
}
@Nullable
public static String getFileExtension(String fileName) {
int dotIndex = fileName.lastIndexOf('.');
if (dotIndex == -1) {
return null;
}
return fileName.substring(dotIndex + 1);
}
private static final Set<String> ZIP_FILE_EXTS = Utils.constSet("zip", "jar", "apk");
public static boolean isZipFileExt(String fileName) {
String ext = getFileExtension(fileName);
if (ext == null) {
return false;
}
return ZIP_FILE_EXTS.contains(ext);
}
}
package jadx.api.plugins.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
......@@ -87,4 +89,9 @@ public class Utils {
public static String formatOffset(int offset) {
return String.format("0x%04x", offset);
}
@SafeVarargs
public static <T> Set<T> constSet(T... arr) {
return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(arr)));
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册