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 { is.checkInt16(RES_STRING_POOL_TYPE, "String pool expected"); return parseStringPoolNoType(); } protected String[] parseStringPoolNoType() throws IOException { long start = is.getPos() - 2; is.checkInt16(0x001c, "String pool header size not 0x001c"); long size = is.readUInt32(); long chunkEnd = start + size; int stringCount = is.readInt32(); int styleCount = is.readInt32(); int flags = is.readInt32(); long stringsStart = is.readInt32(); long stylesStart = is.readInt32(); int[] stringsOffset = is.readInt32Array(stringCount); int[] stylesOffset = is.readInt32Array(styleCount); 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++) { strings[i] = extractString8(strArray, stringsOffset[i]); } } else { // UTF-16 for (int i = 0; i < stringCount; i++) { // don't trust specified string length, read until \0 // stringsOffset can be same for different indexes strings[i] = extractString16(strArray, stringsOffset[i]); } } if (stylesStart != 0) { is.checkPos(start + stylesStart, "Expected styles start"); if (styleCount != 0) { // TODO: implement styles parsing } } // skip padding zeroes is.skipToPos(chunkEnd, "Skip string pool padding"); 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 + skipStrLen16(strArray, offset); int end = start; while (true) { if (end + 1 >= len) { break; } if (strArray[end] == 0 && strArray[end + 1] == 0) { break; } end += 2; } 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 { throw new IOException("Decode error: " + message + ", position: 0x" + Long.toHexString(is.getPos())); } }