diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-12-15 00:26:10 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-12-15 00:26:10 +0000 |
commit | 8d3d8a8c9fee869479cfcf9ff59b87b90204dde5 (patch) | |
tree | 94c4c6f6bebe7d2aa1d923a2e8e8e97bc69c726e | |
parent | 6636513e5f52107c01c2483366a2c6f672f5aee0 (diff) | |
parent | 5b0a6ab86bd5d200d5f125ddb637915a855db869 (diff) | |
download | google-smali-8d3d8a8c9fee869479cfcf9ff59b87b90204dde5.tar.gz |
Snap for 11220357 from 5b0a6ab86bd5d200d5f125ddb637915a855db869 to 24Q1-release
Change-Id: Ib77796e6d429022d754e754f4551269a0164444b
-rw-r--r-- | dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/DexBackedDexFile.java | 89 | ||||
-rw-r--r-- | dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/ZipDexContainer.java | 93 |
2 files changed, 81 insertions, 101 deletions
diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/DexBackedDexFile.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/DexBackedDexFile.java index 653fb5db..7ea7c699 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/DexBackedDexFile.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/DexBackedDexFile.java @@ -74,6 +74,7 @@ public class DexBackedDexFile implements DexFile { @Nonnull private final Opcodes opcodes; + private final int fileSize; private final int stringCount; private final int stringStartOffset; private final int typeCount; @@ -90,6 +91,14 @@ public class DexBackedDexFile implements DexFile { private final int hiddenApiRestrictionsOffset; protected DexBackedDexFile(@Nullable Opcodes opcodes, @Nonnull byte[] buf, int offset, boolean verifyMagic) { + this(opcodes, buf, offset, verifyMagic, 0); + } + + protected DexBackedDexFile(@Nullable Opcodes opcodes, + @Nonnull byte[] buf, + int offset, + boolean verifyMagic, + int header_offset) { dexBuffer = new DexBuffer(buf, offset); dataBuffer = new DexBuffer(buf, offset + getBaseDataOffset()); @@ -101,19 +110,20 @@ public class DexBackedDexFile implements DexFile { this.opcodes = opcodes; } - stringCount = dexBuffer.readSmallUint(HeaderItem.STRING_COUNT_OFFSET); - stringStartOffset = dexBuffer.readSmallUint(HeaderItem.STRING_START_OFFSET); - typeCount = dexBuffer.readSmallUint(HeaderItem.TYPE_COUNT_OFFSET); - typeStartOffset = dexBuffer.readSmallUint(HeaderItem.TYPE_START_OFFSET); - protoCount = dexBuffer.readSmallUint(HeaderItem.PROTO_COUNT_OFFSET); - protoStartOffset = dexBuffer.readSmallUint(HeaderItem.PROTO_START_OFFSET); - fieldCount = dexBuffer.readSmallUint(HeaderItem.FIELD_COUNT_OFFSET); - fieldStartOffset = dexBuffer.readSmallUint(HeaderItem.FIELD_START_OFFSET); - methodCount = dexBuffer.readSmallUint(HeaderItem.METHOD_COUNT_OFFSET); - methodStartOffset = dexBuffer.readSmallUint(HeaderItem.METHOD_START_OFFSET); - classCount = dexBuffer.readSmallUint(HeaderItem.CLASS_COUNT_OFFSET); - classStartOffset = dexBuffer.readSmallUint(HeaderItem.CLASS_START_OFFSET); - mapOffset = dexBuffer.readSmallUint(HeaderItem.MAP_OFFSET); + fileSize = dexBuffer.readSmallUint(header_offset + HeaderItem.FILE_SIZE_OFFSET); + stringCount = dexBuffer.readSmallUint(header_offset + HeaderItem.STRING_COUNT_OFFSET); + stringStartOffset = dexBuffer.readSmallUint(header_offset + HeaderItem.STRING_START_OFFSET); + typeCount = dexBuffer.readSmallUint(header_offset + HeaderItem.TYPE_COUNT_OFFSET); + typeStartOffset = dexBuffer.readSmallUint(header_offset + HeaderItem.TYPE_START_OFFSET); + protoCount = dexBuffer.readSmallUint(header_offset + HeaderItem.PROTO_COUNT_OFFSET); + protoStartOffset = dexBuffer.readSmallUint(header_offset + HeaderItem.PROTO_START_OFFSET); + fieldCount = dexBuffer.readSmallUint(header_offset + HeaderItem.FIELD_COUNT_OFFSET); + fieldStartOffset = dexBuffer.readSmallUint(header_offset + HeaderItem.FIELD_START_OFFSET); + methodCount = dexBuffer.readSmallUint(header_offset + HeaderItem.METHOD_COUNT_OFFSET); + methodStartOffset = dexBuffer.readSmallUint(header_offset + HeaderItem.METHOD_START_OFFSET); + classCount = dexBuffer.readSmallUint(header_offset + HeaderItem.CLASS_COUNT_OFFSET); + classStartOffset = dexBuffer.readSmallUint(header_offset + HeaderItem.CLASS_START_OFFSET); + mapOffset = dexBuffer.readSmallUint(header_offset + HeaderItem.MAP_OFFSET); MapItem mapItem = getMapItemForSection(ItemType.HIDDENAPI_CLASS_DATA_ITEM); if (mapItem != null) { @@ -122,50 +132,12 @@ public class DexBackedDexFile implements DexFile { hiddenApiRestrictionsOffset = DexWriter.NO_OFFSET; } + int container_off = 0; if (dexVersion >= 41) { - // Reject non-trivial dex container (i.e. multiples dex files in the same physical file). - int container_off = dexBuffer.readSmallUint(HeaderItem.CONTAINER_OFF_OFFSET); - int container_size = dexBuffer.readSmallUint(HeaderItem.CONTAINER_SIZE_OFFSET); - int file_size = dexBuffer.readSmallUint(HeaderItem.FILE_SIZE_OFFSET); - if (container_off != 0 || container_size != file_size) { - throw new DexUtil.UnsupportedFile(String.format("Dex container is not supported")); - } + container_off = dexBuffer.readSmallUint(header_offset + HeaderItem.CONTAINER_OFF_OFFSET); } - } - - protected DexBackedDexFile(@Nullable Opcodes opcodes, @Nonnull DexBuffer dexBuffer, @Nonnull DexBuffer dataBuffer, int offset, boolean verifyMagic) { - this.dexBuffer = dexBuffer; - this.dataBuffer = dataBuffer; - - byte[] headerBuf = dexBuffer.readByteRange(offset, HeaderItem.ITEM_SIZE); - - int dexVersion = getVersion(headerBuf, offset, verifyMagic); - - if (opcodes == null) { - this.opcodes = getDefaultOpcodes(dexVersion); - } else { - this.opcodes = opcodes; - } - - stringCount = dexBuffer.readSmallUint(HeaderItem.STRING_COUNT_OFFSET); - stringStartOffset = dexBuffer.readSmallUint(HeaderItem.STRING_START_OFFSET); - typeCount = dexBuffer.readSmallUint(HeaderItem.TYPE_COUNT_OFFSET); - typeStartOffset = dexBuffer.readSmallUint(HeaderItem.TYPE_START_OFFSET); - protoCount = dexBuffer.readSmallUint(HeaderItem.PROTO_COUNT_OFFSET); - protoStartOffset = dexBuffer.readSmallUint(HeaderItem.PROTO_START_OFFSET); - fieldCount = dexBuffer.readSmallUint(HeaderItem.FIELD_COUNT_OFFSET); - fieldStartOffset = dexBuffer.readSmallUint(HeaderItem.FIELD_START_OFFSET); - methodCount = dexBuffer.readSmallUint(HeaderItem.METHOD_COUNT_OFFSET); - methodStartOffset = dexBuffer.readSmallUint(HeaderItem.METHOD_START_OFFSET); - classCount = dexBuffer.readSmallUint(HeaderItem.CLASS_COUNT_OFFSET); - classStartOffset = dexBuffer.readSmallUint(HeaderItem.CLASS_START_OFFSET); - mapOffset = dexBuffer.readSmallUint(HeaderItem.MAP_OFFSET); - - MapItem mapItem = getMapItemForSection(ItemType.HIDDENAPI_CLASS_DATA_ITEM); - if (mapItem != null) { - hiddenApiRestrictionsOffset = mapItem.getOffset(); - } else { - hiddenApiRestrictionsOffset = DexWriter.NO_OFFSET; + if (container_off != header_offset) { + throw new DexUtil.InvalidFile(String.format("Unexpected container offset in header")); } } @@ -177,6 +149,13 @@ public class DexBackedDexFile implements DexFile { return 0; } + /** + * @return Size of single dex file (out of potentially several dex files within a container). + */ + public int getFileSize() { + return fileSize; + } + protected int getVersion(byte[] buf, int offset, boolean verifyMagic) { if (verifyMagic) { return DexUtil.verifyDexHeader(buf, offset); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/ZipDexContainer.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/ZipDexContainer.java index 78c01786..ae8688fc 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/ZipDexContainer.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/ZipDexContainer.java @@ -40,16 +40,19 @@ import com.google.common.collect.Lists; import com.google.common.io.ByteStreams; import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile.NotADexFile; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Enumeration; import java.util.List; +import java.util.Map; +import java.util.TreeMap; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** * Represents a zip file that contains dex files (i.e. an apk or jar file) @@ -58,6 +61,7 @@ public class ZipDexContainer implements MultiDexContainer<DexBackedDexFile> { private final File zipFilePath; @Nullable private final Opcodes opcodes; + private TreeMap<String, DexBackedDexFile> entries; /** * Constructs a new ZipDexContainer for the given zip file @@ -75,7 +79,14 @@ public class ZipDexContainer implements MultiDexContainer<DexBackedDexFile> { * @return A list of the names of dex files in this zip file */ @Nonnull @Override public List<String> getDexEntryNames() throws IOException { - List<String> entryNames = Lists.newArrayList(); + return new ArrayList<>(getEntries().keySet()); + } + + private Map<String, DexBackedDexFile> getEntries() throws IOException { + if (entries != null) { + return entries; + } + entries = new TreeMap<String, DexBackedDexFile>(); ZipFile zipFile = getZipFile(); try { Enumeration<? extends ZipEntry> entriesEnumeration = zipFile.entries(); @@ -87,10 +98,21 @@ public class ZipDexContainer implements MultiDexContainer<DexBackedDexFile> { continue; } - entryNames.add(entry.getName()); + // There might be several dex files in zip entry since DEX v41. + InputStream inputStream = zipFile.getInputStream(entry); + try { + byte[] buf = ByteStreams.toByteArray(inputStream); + for (int offset = 0, i = 1; offset < buf.length; i++) { + DexBackedDexFile dex = new DexBackedDexFile(opcodes, buf, 0, true, offset); + entries.put(entry.getName() + (i > 1 ? ("/" + i) : ""), dex); + offset += dex.getFileSize(); + }; + } finally { + inputStream.close(); + } } - return entryNames; + return entries; } finally { zipFile.close(); } @@ -104,17 +126,26 @@ public class ZipDexContainer implements MultiDexContainer<DexBackedDexFile> { * @throws NotADexFile If the entry isn't a dex file */ @Nullable @Override public DexEntry<DexBackedDexFile> getEntry(@Nonnull String entryName) throws IOException { - ZipFile zipFile = getZipFile(); - try { - ZipEntry entry = zipFile.getEntry(entryName); - if (entry == null) { - return null; - } - - return loadEntry(zipFile, entry); - } finally { - zipFile.close(); - } + DexFile dexFile = getEntries().get(entryName); + return new DexEntry() { + @Nonnull + @Override + public String getEntryName() { + return entryName; + } + + @Nonnull + @Override + public DexFile getDexFile() { + return dexFile; + } + + @Nonnull + @Override + public MultiDexContainer getContainer() { + return ZipDexContainer.this; + } + }; } public boolean isZipFile() { @@ -161,36 +192,6 @@ public class ZipDexContainer implements MultiDexContainer<DexBackedDexFile> { } } - @Nonnull - protected DexEntry loadEntry(@Nonnull ZipFile zipFile, @Nonnull ZipEntry zipEntry) throws IOException { - InputStream inputStream = zipFile.getInputStream(zipEntry); - try { - byte[] buf = ByteStreams.toByteArray(inputStream); - - return new DexEntry() { - @Nonnull - @Override - public String getEntryName() { - return zipEntry.getName(); - } - - @Nonnull - @Override - public DexFile getDexFile() { - return new DexBackedDexFile(opcodes, buf); - } - - @Nonnull - @Override - public MultiDexContainer getContainer() { - return ZipDexContainer.this; - } - }; - } finally { - inputStream.close(); - } - } - public static class NotAZipFileException extends RuntimeException { } } |