fix(res): allow jumping backwards to an already processed position (PR #2344)

Use buffered stream to allow going backwards in stream in case the type chunk entries are not ordered properly (see #2343).
This commit is contained in:
Jan S. 2024-11-15 16:12:47 +01:00 committed by GitHub
parent 1e1036c049
commit fe9d3bcab7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 13 additions and 4 deletions

View File

@ -1,6 +1,5 @@
package jadx.cli.tools; package jadx.cli.tools;
import java.io.BufferedInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Files; import java.nio.file.Files;
@ -71,7 +70,7 @@ public class ConvertArscFile {
} }
} else { } else {
// Load resources.arsc from extracted file // Load resources.arsc from extracted file
try (InputStream inputStream = new BufferedInputStream(Files.newInputStream(resFile))) { try (InputStream inputStream = Files.newInputStream(resFile)) {
resTableParser.decode(inputStream); resTableParser.decode(inputStream);
} }
} }

View File

@ -18,6 +18,7 @@ public class ParserStream {
private final InputStream input; private final InputStream input;
private long readPos = 0; private long readPos = 0;
private long markPos = 0;
public ParserStream(@NotNull InputStream inputStream) { public ParserStream(@NotNull InputStream inputStream) {
this.input = inputStream; this.input = inputStream;
@ -143,10 +144,12 @@ public class ParserStream {
throw new IOException("Mark not supported for input stream " + input.getClass()); throw new IOException("Mark not supported for input stream " + input.getClass());
} }
input.mark(len); input.mark(len);
markPos = readPos;
} }
public void reset() throws IOException { public void reset() throws IOException {
input.reset(); input.reset();
readPos = markPos;
} }
public void readFully(byte[] b) throws IOException { public void readFully(byte[] b) throws IOException {

View File

@ -1,5 +1,6 @@
package jadx.core.xmlgen; package jadx.core.xmlgen;
import java.io.BufferedInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
@ -79,7 +80,7 @@ public class ResTableBinaryParser extends CommonBinaryParser implements IResTabl
@Override @Override
public void decode(InputStream inputStream) throws IOException { public void decode(InputStream inputStream) throws IOException {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
is = new ParserStream(inputStream); is = new ParserStream(new BufferedInputStream(inputStream, 32768));
resStorage = new ResourceStorage(root.getArgs().getSecurity()); resStorage = new ResourceStorage(root.getArgs().getSecurity());
decodeTableChunk(); decodeTableChunk();
resStorage.finish(); resStorage.finish();
@ -234,6 +235,7 @@ public class ResTableBinaryParser extends CommonBinaryParser implements IResTabl
/* int size = */ /* int size = */
long chunkSize = is.readUInt32(); long chunkSize = is.readUInt32();
long chunkEnd = start + chunkSize; long chunkEnd = start + chunkSize;
is.mark((int) chunkSize);
// The type identifier this chunk is holding. Type IDs start at 1 (corresponding // 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. // to the value of the type bits in a resource identifier). 0 is invalid.
@ -286,7 +288,12 @@ public class ResTableBinaryParser extends CommonBinaryParser implements IResTabl
LOG.warn("End of chunk reached - ignoring remaining {} entries", entryCount - index); LOG.warn("End of chunk reached - ignoring remaining {} entries", entryCount - index);
break; break;
} }
is.checkPos(entriesStart + offset, "Expected start of entry " + index); long entryStartOffset = entriesStart + offset;
if (entryStartOffset < is.getPos()) {
// workaround for issue #2343: if the entryStartOffset is located before our current position
is.reset();
}
is.skipToPos(entryStartOffset, "Expected start of entry " + index);
parseEntry(pkg, id, index, config.getQualifiers()); parseEntry(pkg, id, index, config.getQualifiers());
} }
if (chunkEnd > is.getPos()) { if (chunkEnd > is.getPos()) {