diff --git a/jadx-core/src/main/java/jadx/api/ResourcesLoader.java b/jadx-core/src/main/java/jadx/api/ResourcesLoader.java index d65fa2e08..2e46c699f 100644 --- a/jadx-core/src/main/java/jadx/api/ResourcesLoader.java +++ b/jadx-core/src/main/java/jadx/api/ResourcesLoader.java @@ -2,6 +2,7 @@ package jadx.api; import jadx.api.ResourceFile.ZipRef; import jadx.core.codegen.CodeWriter; +import jadx.core.utils.Utils; import jadx.core.utils.exceptions.JadxException; import jadx.core.utils.files.InputFile; import jadx.core.xmlgen.ResTableParser; @@ -61,7 +62,7 @@ public final class ResourcesLoader { inputStream = new BufferedInputStream(zipFile.getInputStream(entry)); return decoder.decode(entry.getSize(), inputStream); } catch (Exception e) { - throw new JadxException("Error load: " + zipRef, e); + throw new JadxException("Error decode: " + zipRef.getEntryName(), e); } finally { try { if (zipFile != null) { @@ -90,8 +91,11 @@ public final class ResourcesLoader { }); } catch (JadxException e) { LOG.error("Decode error", e); + CodeWriter cw = new CodeWriter(); + cw.add("Error decode ").add(rf.getType().toString().toLowerCase()); + cw.startLine(Utils.getStackTrace(e.getCause())); + return cw; } - return null; } private static CodeWriter loadContent(JadxDecompiler jadxRef, ResourceType type, 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 228a5d031..4d35a7abe 100644 --- a/jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java +++ b/jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java @@ -5,7 +5,6 @@ import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.nodes.DexNode; import jadx.core.dex.nodes.FieldNode; import jadx.core.dex.nodes.RootNode; -import jadx.core.utils.Utils; import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.xmlgen.entry.ValuesParser; @@ -75,20 +74,12 @@ public class BinaryXMLParser extends CommonBinaryParser { } } - public synchronized CodeWriter parse(InputStream inputStream) { + public synchronized CodeWriter parse(InputStream inputStream) throws IOException { writer = new CodeWriter(); writer.add(""); is = new ParserStream(inputStream); firstElement = true; - try { - decode(); - } catch (IOException e) { - LOG.debug("Binary xml decode failed", e); - CodeWriter cw = new CodeWriter(); - cw.add("Error decode binary xml"); - cw.startLine(Utils.getStackTrace(e)); - return cw; - } + decode(); writer.finish(); return writer; } diff --git a/jadx-core/src/main/java/jadx/core/xmlgen/CommonBinaryParser.java b/jadx-core/src/main/java/jadx/core/xmlgen/CommonBinaryParser.java index 8ebf011e7..63b7e49d4 100644 --- a/jadx-core/src/main/java/jadx/core/xmlgen/CommonBinaryParser.java +++ b/jadx-core/src/main/java/jadx/core/xmlgen/CommonBinaryParser.java @@ -1,9 +1,9 @@ package jadx.core.xmlgen; import java.io.IOException; +import java.util.Arrays; public class CommonBinaryParser extends ParserConstants { - protected ParserStream is; protected String[] parseStringPool() throws IOException { @@ -29,16 +29,14 @@ public class CommonBinaryParser extends ParserConstants { is.checkPos(start + stringsStart, "Expected strings start"); long stringsEnd = stylesStart == 0 ? chunkEnd : start + stylesStart; String[] strings = new String[stringCount]; + byte[] strArray = is.readInt8Array((int) (stringsEnd - is.getPos())); if ((flags & UTF8_FLAG) != 0) { // UTF-8 for (int i = 0; i < stringCount; i++) { - // is.checkPos(start + stringsStart + stringsOffset[i], "Expected string start"); - strings[i] = is.readString8(); + strings[i] = extractString8(strArray, stringsOffset[i]); } - is.skipToPos(stringsEnd, "Skip string8 padding"); } else { // UTF-16 - byte[] strArray = is.readInt8Array((int) (stringsEnd - is.getPos())); for (int i = 0; i < stringCount; i++) { // don't trust specified string length, read until \0 // stringsOffset can be same for different indexes @@ -56,9 +54,22 @@ public class CommonBinaryParser extends ParserConstants { return strings; } + private static String extractString8(byte[] strArray, int offset) { + int start = offset + skipStrLen8(strArray, offset); + int len = strArray[start++]; + if (len == 0) { + return ""; + } + if ((len & 0x80) != 0) { + len = ((len & 0x7F) << 8) | (strArray[start++] & 0xFF); + } + byte[] arr = Arrays.copyOfRange(strArray, start, start + len); + return new String(arr, ParserStream.STRING_CHARSET_UTF8); + } + private static String extractString16(byte[] strArray, int offset) { int len = strArray.length; - int start = offset + 2; + int start = offset + skipStrLen16(strArray, offset); int end = start; while (true) { if (end + 1 >= len) { @@ -69,7 +80,16 @@ public class CommonBinaryParser extends ParserConstants { } end += 2; } - return new String(strArray, start, end - start, ParserStream.STRING_CHARSET_UTF16); + byte[] arr = Arrays.copyOfRange(strArray, start, end); + return new String(arr, ParserStream.STRING_CHARSET_UTF16); + } + + private static int skipStrLen8(byte[] strArray, int offset) { + return (strArray[offset] & 0x80) == 0 ? 1 : 2; + } + + private static int skipStrLen16(byte[] strArray, int offset) { + return (strArray[offset + 1] & 0x80) == 0 ? 2 : 4; } protected void die(String message) throws IOException { diff --git a/jadx-core/src/main/java/jadx/core/xmlgen/ParserStream.java b/jadx-core/src/main/java/jadx/core/xmlgen/ParserStream.java index bc3b79ab4..0ca7a399d 100644 --- a/jadx-core/src/main/java/jadx/core/xmlgen/ParserStream.java +++ b/jadx-core/src/main/java/jadx/core/xmlgen/ParserStream.java @@ -9,6 +9,9 @@ public class ParserStream { protected static final Charset STRING_CHARSET_UTF16 = Charset.forName("UTF-16LE"); protected static final Charset STRING_CHARSET_UTF8 = Charset.forName("UTF-8"); + private static final int[] EMPTY_INT_ARRAY = new int[0]; + private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + private final InputStream input; private long readPos = 0; @@ -46,34 +49,14 @@ public class ParserStream { return readInt32() & 0xFFFFFFFFL; } - public String readString8Fixed(int len) throws IOException { - String str = new String(readInt8Array(len), STRING_CHARSET_UTF8); - return str.trim(); - } - public String readString16Fixed(int len) throws IOException { String str = new String(readInt8Array(len * 2), STRING_CHARSET_UTF16); return str.trim(); } - public String readString8() throws IOException { - decodeLength8(); - int len = decodeLength8(); - String str = new String(readInt8Array(len), STRING_CHARSET_UTF8); - checkInt8(0, "Not a trailing zero at string8 end"); - return str; - } - - public String readString16() throws IOException { - int len = decodeLength16(); - String str = new String(readInt8Array(len), STRING_CHARSET_UTF16); - checkInt16(0, "Not a trailing zero at string16 end"); - return str; - } - public int[] readInt32Array(int count) throws IOException { if (count == 0) { - return new int[0]; + return EMPTY_INT_ARRAY; } int[] arr = new int[count]; for (int i = 0; i < count; i++) { @@ -84,7 +67,7 @@ public class ParserStream { public byte[] readInt8Array(int count) throws IOException { if (count == 0) { - return new byte[0]; + return EMPTY_BYTE_ARRAY; } readPos += count; byte[] arr = new byte[count]; @@ -147,22 +130,6 @@ public class ParserStream { checkPos(expectedOffset, error); } - public int decodeLength8() throws IOException { - int len = readInt8(); - if ((len & 0x80) != 0) { - len = ((len & 0x7F) << 8) | readInt8(); - } - return len; - } - - public int decodeLength16() throws IOException { - int len = readInt16(); - if ((len & 0x8000) != 0) { - len = ((len & 0x7FFF) << 16) | readInt16(); - } - return len; - } - @Override public String toString() { return "pos: 0x" + Long.toHexString(readPos); diff --git a/jadx-core/src/main/java/jadx/core/xmlgen/ResTableParser.java b/jadx-core/src/main/java/jadx/core/xmlgen/ResTableParser.java index 8ed27be5c..6eabde16d 100644 --- a/jadx-core/src/main/java/jadx/core/xmlgen/ResTableParser.java +++ b/jadx-core/src/main/java/jadx/core/xmlgen/ResTableParser.java @@ -1,7 +1,6 @@ package jadx.core.xmlgen; import jadx.core.codegen.CodeWriter; -import jadx.core.utils.Utils; import jadx.core.xmlgen.entry.EntryConfig; import jadx.core.xmlgen.entry.RawNamedValue; import jadx.core.xmlgen.entry.RawValue; @@ -59,16 +58,8 @@ public class ResTableParser extends CommonBinaryParser { resStorage.finish(); } - public CodeWriter decodeToCodeWriter(InputStream inputStream) { - try { - decode(inputStream); - } catch (IOException e) { - LOG.debug("arsc decode failed", e); - CodeWriter cw = new CodeWriter(); - cw.add("Error decode arsc"); - cw.startLine(Utils.getStackTrace(e)); - return cw; - } + public CodeWriter decodeToCodeWriter(InputStream inputStream) throws IOException { + decode(inputStream); CodeWriter writer = new CodeWriter(); writer.add("app package: ").add(resStorage.getAppPackage());