feat(res): improve error message for unsupported ResTable flags (PR #2266)

This commit is contained in:
pubiqq
2024-09-05 21:13:26 +03:00
committed by GitHub
parent 5fbbf2150e
commit ea5e87560a
2 changed files with 33 additions and 4 deletions
@@ -145,8 +145,20 @@ public class ParserConstants {
protected static final int SORTED_FLAG = 1;
protected static final int UTF8_FLAG = 1 << 8;
/**
* ResTable_type
*/
protected static final int NO_ENTRY = 0xFFFFFFFF;
// If set, the entry is sparse, and encodes both the entry ID and offset into each entry,
// and a binary search is used to find the key. Only available on platforms >= O.
// Mark any types that use this with a v26 qualifier to prevent runtime issues on older
// platforms.
protected static final int FLAG_SPARSE = 0x01;
// If set, the offsets to the entries are encoded in 16-bit, real_offset = offset * 4u
// An 16-bit offset of 0xffffu means a NO_ENTRY
protected static final int FLAG_OFFSET16 = 0x02;
/**
* ResTable_entry
*/
@@ -158,6 +170,9 @@ public class ParserConstants {
// If set, this is a weak resource and may be overridden by strong resources of the same name/type.
// This is only useful during linking with other resource tables.
protected static final int FLAG_WEAK = 0x0004;
// If set, this is a compact entry with data type and value directly
// encoded in the entry, see ResTable_entry::compact
protected static final int FLAG_COMPACT = 0x0008;
/**
* ResTable_map
@@ -274,8 +274,14 @@ public class ResTableBinaryParser extends CommonBinaryParser implements IResTabl
// The type identifier this chunk is holding. Type IDs start at 1 (corresponding
// to the value of the type bits in a resource identifier). 0 is invalid.
int id = is.readInt8();
int flags = is.readInt8(); // 0 or 1
boolean flagSparse = flags == 1;
int flags = is.readInt8();
boolean isSparse = (flags & FLAG_SPARSE) != 0;
boolean isOffset16 = (flags & FLAG_OFFSET16) != 0;
if (isOffset16) {
throw new JadxRuntimeException("16-bit entry offsets are not supported yet");
}
is.checkInt16(0, "type chunk, reserved");
int entryCount = is.readInt32();
@@ -289,7 +295,7 @@ public class ResTableBinaryParser extends CommonBinaryParser implements IResTabl
}
Map<Integer, Integer> entryOffsetMap = new LinkedHashMap<>(entryCount);
if (flagSparse) {
if (isSparse) {
for (int i = 0; i < entryCount; i++) {
int idx = is.readInt16();
int offset = is.readInt16() * 4; // The offset in ResTable_sparseTypeEntry::offset is stored divided by 4.
@@ -357,7 +363,15 @@ public class ResTableBinaryParser extends CommonBinaryParser implements IResTabl
private void parseEntry(PackageChunk pkg, int typeId, int entryId, String config) throws IOException {
int size = is.readInt16();
int flags = is.readInt16();
boolean isComplex = (flags & FLAG_COMPLEX) != 0;
boolean isCompact = (flags & FLAG_COMPACT) != 0;
if (isCompact) {
throw new JadxRuntimeException("Compact resource entries are not supported yet");
}
int key = is.readInt32();
if (key == -1) {
return;
@@ -368,7 +382,7 @@ public class ResTableBinaryParser extends CommonBinaryParser implements IResTabl
String origKeyName = pkg.getKeyStrings().get(key);
ResourceEntry newResEntry = buildResourceEntry(pkg, config, resRef, typeName, origKeyName);
if ((flags & FLAG_COMPLEX) != 0 || size == 16) {
if (isComplex || size == 16) {
int parentRef = is.readInt32();
int count = is.readInt32();
newResEntry.setParentRef(parentRef);