diff --git a/jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java b/jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java index e04c5445772b2f2f611be1c92be0aadd53250283..09b208cc1fc71f1bf17e7b8e7dcf4cb41ff33aba 100644 --- a/jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java @@ -13,6 +13,7 @@ import java.nio.file.FileVisitOption; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; import java.security.MessageDigest; import java.util.ArrayList; import java.util.Comparator; @@ -228,7 +229,8 @@ public class FileUtils { public static void writeFile(Path file, String data) throws IOException { FileUtils.makeDirsForFile(file); - Files.write(file, data.getBytes(StandardCharsets.UTF_8)); + Files.write(file, data.getBytes(StandardCharsets.UTF_8), + StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); } public static String readFile(Path textFile) throws IOException { diff --git a/jadx-gui/src/main/java/jadx/gui/utils/codecache/disk/DiskCodeCache.java b/jadx-gui/src/main/java/jadx/gui/utils/codecache/disk/DiskCodeCache.java index a244ac6f22bdf3efe8d1783539c725e826f7dc20..4150298d99ecd24c6ad3137e4d6794da58456f8f 100644 --- a/jadx-gui/src/main/java/jadx/gui/utils/codecache/disk/DiskCodeCache.java +++ b/jadx-gui/src/main/java/jadx/gui/utils/codecache/disk/DiskCodeCache.java @@ -15,6 +15,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.FileTime; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -30,6 +31,7 @@ import jadx.api.ICodeCache; import jadx.api.ICodeInfo; import jadx.api.JadxArgs; import jadx.core.Jadx; +import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.RootNode; import jadx.core.utils.Utils; import jadx.core.utils.exceptions.JadxRuntimeException; @@ -42,7 +44,7 @@ import static java.nio.file.StandardOpenOption.WRITE; public class DiskCodeCache implements ICodeCache { private static final Logger LOG = LoggerFactory.getLogger(DiskCodeCache.class); - private static final int DATA_FORMAT_VERSION = 12; + private static final int DATA_FORMAT_VERSION = 13; private static final byte[] JADX_NAMES_MAP_HEADER = "jadxnm".getBytes(StandardCharsets.US_ASCII); @@ -55,6 +57,7 @@ public class DiskCodeCache implements ICodeCache { private final ExecutorService writePool; private final Map writeOps = new ConcurrentHashMap<>(); private final Map namesMap = new ConcurrentHashMap<>(); + private final Map allClsIds; public DiskCodeCache(RootNode root, Path baseDir) { srcDir = baseDir.resolve("sources"); @@ -65,6 +68,7 @@ public class DiskCodeCache implements ICodeCache { codeVersion = buildCodeVersion(args); writePool = Executors.newFixedThreadPool(args.getThreadsCount()); codeMetadataAdapter = new CodeMetadataAdapter(root); + allClsIds = buildClassIdsMap(root.getClasses()); if (checkCodeVersion()) { loadNamesMap(); } else { @@ -112,6 +116,7 @@ public class DiskCodeCache implements ICodeCache { public void add(String clsFullName, ICodeInfo codeInfo) { writeOps.put(clsFullName, codeInfo); int clsId = getClsId(clsFullName); + namesMap.put(clsFullName, clsId); writePool.execute(() -> { try { FileUtils.writeFile(getJavaFile(clsId), codeInfo.getCodeStr()); @@ -218,7 +223,11 @@ public class DiskCodeCache implements ICodeCache { } private int getClsId(String clsFullName) { - return namesMap.computeIfAbsent(clsFullName, n -> namesMap.size()); + Integer id = allClsIds.get(clsFullName); + if (id == null) { + throw new JadxRuntimeException("Unknown class name: " + clsFullName); + } + return id; } private void saveNamesMap() { @@ -250,6 +259,13 @@ public class DiskCodeCache implements ICodeCache { String clsName = in.readUTF(); int clsId = in.readInt(); namesMap.put(clsName, clsId); + Integer prevId = allClsIds.get(clsName); + if (prevId == null || prevId != clsId) { + LOG.debug("Unexpected class id, got: {}, expect: {}", clsId, prevId); + LOG.warn("Inconsistent disk cache, resetting..."); + reset(); + return; + } } LOG.info("Found {} classes in disk cache, dir: {}", count, metaDir.getParent()); } catch (Exception e) { @@ -271,6 +287,16 @@ public class DiskCodeCache implements ICodeCache { return Paths.get(firstByte, FileUtils.intToHex(clsId) + ext); } + private Map buildClassIdsMap(List classes) { + int clsCount = classes.size(); + Map map = new HashMap<>(clsCount); + for (int i = 0; i < clsCount; i++) { + ClassNode cls = classes.get(i); + map.put(cls.getRawName(), i); + } + return map; + } + @SuppressWarnings("ResultOfMethodCallIgnored") @Override public void close() throws IOException {