diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java index ee0fa50510..a650ec193a 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.logging.Logger; @@ -250,8 +251,7 @@ private ResType readTableType() throws IOException, AndrolibException { /* reserved */mIn.skipBytes(2); int entryCount = mIn.readInt(); int entriesStart = mIn.readInt(); - mMissingResSpecs = new boolean[entryCount]; - Arrays.fill(mMissingResSpecs, true); + mMissingResSpecMap = new LinkedHashMap(); ResConfigFlags flags = readConfigFlags(); int position = (mHeader.startPosition + entriesStart) - (entryCount * 4); @@ -263,10 +263,18 @@ private ResType readTableType() throws IOException, AndrolibException { mIn.skipBytes(position - mCountIn.getCount()); } - if (typeFlags == 1) { + if ((typeFlags & 0x01) != 0) { LOGGER.info("Sparse type flags detected: " + mTypeSpec.getName()); } - int[] entryOffsets = mIn.readIntArray(entryCount); + + HashMap entryOffsetMap = new LinkedHashMap(); + for (int i = 0; i < entryCount; i++) { + if ((typeFlags & 0x01) != 0) { + entryOffsetMap.put(mIn.readUnsignedShort(), mIn.readUnsignedShort()); + } else { + entryOffsetMap.put(i, mIn.readInt()); + } + } if (flags.isInvalid) { String resName = mTypeSpec.getName() + flags.getQualifiers(); @@ -278,23 +286,15 @@ private ResType readTableType() throws IOException, AndrolibException { } mType = flags.isInvalid && !mKeepBroken ? null : mPkg.getOrCreateConfig(flags); - HashMap offsetsToEntryData = new HashMap<>(); - for (int offset : entryOffsets) { - if (offset == -1 || offsetsToEntryData.containsKey(offset)) { + for (int i : entryOffsetMap.keySet()) { + int offset = entryOffsetMap.get(i); + if (offset == -1) { continue; } - - offsetsToEntryData.put(offset, readEntryData()); - } - - for (int i = 0; i < entryOffsets.length; i++) { - if (entryOffsets[i] != -1) { - mMissingResSpecs[i] = false; - mResId = (mResId & 0xffff0000) | i; - EntryData entryData = offsetsToEntryData.get(entryOffsets[i]); - readEntry(entryData); - } + mMissingResSpecMap.put(i, false); + mResId = (mResId & 0xffff0000) | i; + readEntry(readEntryData()); } return mType; @@ -533,14 +533,12 @@ private void addTypeSpec(ResTypeSpec resTypeSpec) { private void addMissingResSpecs() throws AndrolibException { int resId = mResId & 0xffff0000; - for (int i = 0; i < mMissingResSpecs.length; i++) { - if (!mMissingResSpecs[i]) { - continue; - } + for (int i : mMissingResSpecMap.keySet()) { + if (mMissingResSpecMap.get(i)) continue; ResResSpec spec = new ResResSpec(new ResID(resId | i), "APKTOOL_DUMMY_" + Integer.toHexString(i), mPkg, mTypeSpec); - // If we already have this resID dont add it again. + // If we already have this resID don't add it again. if (! mPkg.hasResSpec(new ResID(resId | i))) { mPkg.addResSpec(spec); mTypeSpec.addResSpec(spec); @@ -598,7 +596,7 @@ private void nextChunkCheckType(int expectedType) throws IOException, AndrolibEx private ResType mType; private int mResId; private int mTypeIdOffset = 0; - private boolean[] mMissingResSpecs; + private HashMap mMissingResSpecMap; private final HashMap mResTypeSpecs = new HashMap<>(); private final static short ENTRY_FLAG_COMPLEX = 0x0001;