From 837bccd45057ff4b1620d1d64c9a7ed6d8ba5e82 Mon Sep 17 00:00:00 2001 From: REAndroid Date: Mon, 20 May 2024 14:03:15 +0200 Subject: [PATCH] [SMALI] Fix utf8 character encoding --- .../com/reandroid/dex/smali/SmaliReader.java | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/reandroid/dex/smali/SmaliReader.java b/src/main/java/com/reandroid/dex/smali/SmaliReader.java index 9c1778505..02c901814 100644 --- a/src/main/java/com/reandroid/dex/smali/SmaliReader.java +++ b/src/main/java/com/reandroid/dex/smali/SmaliReader.java @@ -84,6 +84,8 @@ public String readString(int length){ return new String(readBytes(length), StandardCharsets.UTF_8); } public String readEscapedString(char stopChar) throws IOException{ + int position = position(); + boolean utf8Detected = false; StringBuilder builder = new StringBuilder(); boolean skipped = false; while (true){ @@ -92,6 +94,9 @@ public String readEscapedString(char stopChar) throws IOException{ throw new SmaliParseException("Missing character '" + stopChar + "'", this); } char ch = readASCII(); + if(ch > 0x7f) { + utf8Detected = true; + } if(skipped){ builder.append(decodeSkipped(this, ch)); skipped = false; @@ -107,6 +112,11 @@ public String readEscapedString(char stopChar) throws IOException{ } builder.append(ch); } + if(utf8Detected) { + int len = position() - position; + position(position); + return decodeEscapedString(readString(len)); + } return builder.toString(); } public String readStringForNumber(){ @@ -505,6 +515,12 @@ private static boolean isLineEnd(byte b){ } } private static char decodeSkipped(SmaliReader reader, char ch){ + if(ch == 'u') { + return decodeFourHex(reader); + } + return decodeSkippedChar(ch); + } + private static char decodeSkippedChar(char ch){ switch (ch){ case 'b': return '\b'; @@ -516,8 +532,6 @@ private static char decodeSkipped(SmaliReader reader, char ch){ return '\r'; case 't': return '\t'; - case 'u': - return decodeFourHex(reader); default: return ch; } @@ -532,6 +546,44 @@ private static char decodeFourHex(SmaliReader reader){ i |= HexUtil.decodeHexChar(reader.read()); return (char) i; } + public static String decodeEscapedString(String text){ + StringBuilder builder = new StringBuilder(); + boolean skipped = false; + int length = text.length(); + for (int i = 0; i < length; i++){ + char ch = text.charAt(i); + if(skipped){ + if(ch == 'u') { + builder.append(decodeHex( + text.charAt(i + 1), + text.charAt(i + 2), + text.charAt(i + 3), + text.charAt(i + 4))); + i = i + 4; + }else { + builder.append(decodeSkippedChar(ch)); + } + skipped = false; + continue; + } + if(ch == '\\'){ + skipped = true; + continue; + } + builder.append(ch); + } + return builder.toString(); + } + private static char decodeHex(char c1, char c2, char c3, char c4){ + int i = HexUtil.decodeHexChar(c1); + i = i << 4; + i |= HexUtil.decodeHexChar(c2); + i = i << 4; + i |= HexUtil.decodeHexChar(c3); + i = i << 4; + i |= HexUtil.decodeHexChar(c4); + return (char) i; + } public static SmaliReader of(String text){ return new SmaliReader(text.getBytes(StandardCharsets.UTF_8)); }