Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: Implemented parsing RES_TABLE_TYPE_LIBRARY chunks #1664

Merged
merged 2 commits into from
Sep 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions jadx-core/src/main/java/jadx/core/xmlgen/ParserConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ protected ParserConstants() {
protected static final int RES_XML_LAST_CHUNK_TYPE = 0x017f;
protected static final int RES_XML_RESOURCE_MAP_TYPE = 0x0180;

protected static final int RES_TABLE_PACKAGE_TYPE = 0x0200;
protected static final int RES_TABLE_TYPE_TYPE = 0x0201;
protected static final int RES_TABLE_TYPE_SPEC_TYPE = 0x0202;
protected static final int RES_TABLE_PACKAGE_TYPE = 0x0200; // 512
protected static final int RES_TABLE_TYPE_TYPE = 0x0201; // 513
protected static final int RES_TABLE_TYPE_SPEC_TYPE = 0x0202; // 514
protected static final int RES_TABLE_TYPE_LIBRARY = 0x0203; // 515
protected static final int RES_TABLE_TYPE_OVERLAY = 0x0204; // 516
protected static final int RES_TABLE_TYPE_STAGED_ALIAS = 0x0206; // 517

/**
* Type constants
Expand Down
64 changes: 54 additions & 10 deletions jadx-core/src/main/java/jadx/core/xmlgen/ResTableParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,28 @@ private PackageChunk parsePackage() throws IOException {
while (is.getPos() < endPos) {
long chunkStart = is.getPos();
int type = is.readInt16();
if (type == RES_NULL_TYPE) {
continue;
}
if (type == RES_TABLE_TYPE_SPEC_TYPE) {
parseTypeSpecChunk();
} else if (type == RES_TABLE_TYPE_TYPE) {
parseTypeChunk(chunkStart, pkg);
LOG.trace("res package chunk start at {} type {}", chunkStart, type);
switch (type) {
case RES_NULL_TYPE:
LOG.info("Null chunk type encountered at offset {}", chunkStart);
break;
case RES_TABLE_TYPE_TYPE: // 0x0201
parseTypeChunk(chunkStart, pkg);
break;
case RES_TABLE_TYPE_SPEC_TYPE: // 0x0202
parseTypeSpecChunk(chunkStart);
break;
case RES_TABLE_TYPE_LIBRARY: // 0x0203
parseLibraryTypeChunk(chunkStart);
break;
case RES_TABLE_TYPE_OVERLAY: // 0x0204
throw new IOException(
String.format("Encountered unsupported chunk type TYPE_OVERLAY at offset 0x%x ", chunkStart));
case RES_TABLE_TYPE_STAGED_ALIAS: // 0x0206
throw new IOException(
String.format("Encountered unsupported chunk type TYPE_STAGED_ALIAS at offset 0x%x ", chunkStart));
default:
LOG.warn("Unknown chunk type {} encountered at offset {}", type, chunkStart);
}
}
return pkg;
Expand Down Expand Up @@ -192,17 +207,39 @@ private String makeNewKeyName(int idx) {
}

@SuppressWarnings("unused")
private void parseTypeSpecChunk() throws IOException {
private void parseTypeSpecChunk(long chunkStart) throws IOException {
is.checkInt16(0x0010, "Unexpected type spec header size");
/* int size = */
is.readInt32();
int chunkSize = is.readInt32();
long expectedEndPos = chunkStart + chunkSize;

int id = is.readInt8();
is.skip(3);
int entryCount = is.readInt32();
for (int i = 0; i < entryCount; i++) {
int entryFlag = is.readInt32();
}
if (is.getPos() != expectedEndPos) {
throw new IOException(String.format("Error reading type spec chunk at offset 0x%x", chunkStart));
}
}

private void parseLibraryTypeChunk(long chunkStart) throws IOException {
LOG.trace("parsing library type chunk starting at offset {}", chunkStart);
is.checkInt16(12, "Unexpected header size");
int chunkSize = is.readInt32();
long expectedEndPos = chunkStart + chunkSize;
int count = is.readInt32();
for (int i = 0; i < count; i++) {
int packageId = is.readInt32();
String packageName = is.readString16Fixed(128);
LOG.info("Found resource shared library {}, pkgId: {}", packageName, packageId);
if (is.getPos() > expectedEndPos) {
throw new IOException("reading after chunk end");
}
}
if (is.getPos() != expectedEndPos) {
throw new IOException(String.format("Error reading library chunk at offset 0x%x", chunkStart));
}
}

private void parseTypeChunk(long start, PackageChunk pkg) throws IOException {
Expand Down Expand Up @@ -241,6 +278,13 @@ private void parseTypeChunk(long start, PackageChunk pkg) throws IOException {
parseEntry(pkg, id, i, config.getQualifiers());
}
}
if (chunkEnd > is.getPos()) {
// Skip remaining unknown data in this chunk (e.g. type 8 entries")
long skipSize = chunkEnd - is.getPos();
LOG.debug("Unknown data at the end of type chunk encountered, skipping {} bytes and continuing at offset {}", skipSize,
chunkEnd);
is.skip(skipSize);
}
}

private void parseEntry(PackageChunk pkg, int typeId, int entryId, String config) throws IOException {
Expand Down