From 24284a6f3aec42bb3fe0505b93b4408afb396699 Mon Sep 17 00:00:00 2001 From: Skylot Date: Fri, 17 Feb 2023 17:51:15 +0000 Subject: [PATCH] fix: process manifest before other resources (#1740) --- .../src/main/java/jadx/api/JadxDecompiler.java | 16 ++++++++++++++-- .../java/jadx/core/xmlgen/BinaryXMLParser.java | 5 +++-- .../java/jadx/core/xmlgen/ResourcesSaver.java | 6 +++++- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java index d7f903b88..671188eab 100644 --- a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java +++ b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java @@ -309,9 +309,21 @@ public final class JadxDecompiler implements Closeable { if (args.isSkipFilesSave()) { return; } + // process AndroidManifest.xml first to load complete resource ids table + for (ResourceFile resourceFile : getResources()) { + if (resourceFile.getType() == ResourceType.MANIFEST) { + new ResourcesSaver(outDir, resourceFile).run(); + } + } + Set inputFileNames = args.getInputFiles().stream().map(File::getAbsolutePath).collect(Collectors.toSet()); for (ResourceFile resourceFile : getResources()) { - if (resourceFile.getType() != ResourceType.ARSC + ResourceType resType = resourceFile.getType(); + if (resType == ResourceType.MANIFEST) { + // already processed + continue; + } + if (resType != ResourceType.ARSC && inputFileNames.contains(resourceFile.getOriginalName())) { // ignore resource made from input file continue; @@ -382,7 +394,7 @@ public final class JadxDecompiler implements Closeable { return Utils.collectionMap(root.getClasses(), this::convertClassNode); } - public List getResources() { + public synchronized List getResources() { if (resources == null) { if (root == null) { return Collections.emptyList(); diff --git a/jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java b/jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java index 8f7fb8c5f..c3c3c169e 100644 --- a/jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java +++ b/jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java @@ -8,6 +8,7 @@ import java.util.Map; import java.util.Random; import java.util.Set; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,7 +52,7 @@ public class BinaryXMLParser extends CommonBinaryParser { private boolean isLastEnd = true; private boolean isOneLine = true; private int namespaceDepth = 0; - private int[] resourceIds; + private @Nullable int[] resourceIds; private final RootNode rootNode; private String appPackageName; @@ -358,7 +359,7 @@ public class BinaryXMLParser extends CommonBinaryParser { // As the outcome of https://github.com/skylot/jadx/issues/1208 // Android seems to favor entries from AndroidResMap and only if // there is no entry uses the values form the XML string pool - if (0 <= id && id < resourceIds.length) { + if (resourceIds != null && 0 <= id && id < resourceIds.length) { int resId = resourceIds[id]; String str = ValuesParser.getAndroidResMap().get(resId); if (str != null) { diff --git a/jadx-core/src/main/java/jadx/core/xmlgen/ResourcesSaver.java b/jadx-core/src/main/java/jadx/core/xmlgen/ResourcesSaver.java index 1bfa675f1..5e0d3b2e1 100644 --- a/jadx-core/src/main/java/jadx/core/xmlgen/ResourcesSaver.java +++ b/jadx-core/src/main/java/jadx/core/xmlgen/ResourcesSaver.java @@ -29,7 +29,11 @@ public class ResourcesSaver implements Runnable { @Override public void run() { - saveResources(resourceFile.loadContent()); + try { + saveResources(resourceFile.loadContent()); + } catch (Throwable e) { + LOG.warn("Failed to save resource: {}", resourceFile.getOriginalName(), e); + } } private void saveResources(ResContainer rc) {