From 60d834f95104bcbe856f4100ec967f4aae67eb04 Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Sat, 2 Mar 2013 15:21:33 -0800 Subject: Annotate StringDataItems --- .../org/jf/dexlib2/dexbacked/BaseDexReader.java | 8 +++ .../org/jf/dexlib2/dexbacked/DexBackedDexFile.java | 3 +- .../org/jf/dexlib2/dexbacked/raw/RawDexFile.java | 1 + .../jf/dexlib2/dexbacked/raw/StringDataItem.java | 62 ++++++++++++++++++++++ util/src/main/java/org/jf/util/Utf8Utils.java | 28 ++++++++-- 5 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/StringDataItem.java diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexReader.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexReader.java index cf55cedb..85ae4c32 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexReader.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexReader.java @@ -32,6 +32,7 @@ package org.jf.dexlib2.dexbacked; import org.jf.util.ExceptionWithContext; +import org.jf.util.Utf8Utils; import javax.annotation.Nonnull; @@ -457,4 +458,11 @@ public class BaseDexReader { offset = o + bytes; return result; } + + public String readString(int utf16Length) { + int[] ret = new int[1]; + String value = Utf8Utils.utf8BytesWithUtf16LengthToString(dexBuf.buf, offset, utf16Length, ret); + offset += ret[0]; + return value; + } } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java index dd6cf24f..5ebceef8 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java @@ -35,7 +35,6 @@ import org.jf.dexlib2.dexbacked.raw.*; import org.jf.dexlib2.dexbacked.util.FixedSizeSet; import org.jf.dexlib2.iface.DexFile; import org.jf.util.ExceptionWithContext; -import org.jf.util.Utf8Utils; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -197,7 +196,7 @@ public abstract class DexBackedDexFile extends BaseDexBuffer implements DexFile int stringDataOffset = readSmallUint(stringOffset); DexReader reader = readerAt(stringDataOffset); int utf16Length = reader.readSmallUleb128(); - return Utf8Utils.utf8BytesWithUtf16LengthToString(buf, reader.getOffset(), utf16Length); + return reader.readString(utf16Length); } @Override diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/RawDexFile.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/RawDexFile.java index d9d95b8f..4a65fd02 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/RawDexFile.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/RawDexFile.java @@ -98,6 +98,7 @@ public class RawDexFile extends DexBackedDexFile.Impl { builder.put(ItemType.ANNOTATION_ITEM, AnnotationItem.getAnnotator()); builder.put(ItemType.CLASS_DATA_ITEM, ClassDataItem.getAnnotator()); builder.put(ItemType.CODE_ITEM, CodeItem.getAnnotator()); + builder.put(ItemType.STRING_DATA_ITEM, StringDataItem.getAnnotator()); annotators = builder.build(); } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/StringDataItem.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/StringDataItem.java new file mode 100644 index 00000000..ed13e11e --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/StringDataItem.java @@ -0,0 +1,62 @@ +/* + * Copyright 2013, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib2.dexbacked.raw; + +import org.jf.dexlib2.dexbacked.DexReader; +import org.jf.dexlib2.util.AnnotatedBytes; +import org.jf.util.StringUtils; + +import javax.annotation.Nonnull; + +public class StringDataItem { + @Nonnull + public static SectionAnnotator getAnnotator() { + return new SectionAnnotator() { + @Nonnull @Override public String getItemName() { + return "string_data_item"; + } + + @Override protected void annotateItem(@Nonnull AnnotatedBytes out, @Nonnull RawDexFile dexFile, + int itemIndex) { + + DexReader reader = dexFile.readerAt(out.getCursor()); + int mark = reader.getOffset(); + int utf16Length = reader.readSmallUleb128(); + out.annotate(reader.getOffset() - mark, "utf16_size = %d", utf16Length); + + mark = reader.getOffset(); + String value = reader.readString(utf16Length); + out.annotate(reader.getOffset() - mark + 1, "data = \"%s\"", StringUtils.escapeString(value)); + } + }; + } +} diff --git a/util/src/main/java/org/jf/util/Utf8Utils.java b/util/src/main/java/org/jf/util/Utf8Utils.java index 1931bb0f..957e535d 100644 --- a/util/src/main/java/org/jf/util/Utf8Utils.java +++ b/util/src/main/java/org/jf/util/Utf8Utils.java @@ -24,12 +24,13 @@ package org.jf.util; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Constants of type CONSTANT_Utf8_info. */ public final class Utf8Utils { - - /** * Converts a string into its Java-style UTF-8 form. Java-style UTF-8 * differs from normal UTF-8 in the handling of character '\0' and @@ -174,7 +175,21 @@ public final class Utf8Utils { * @param utf16Length the number of utf16 characters in the string to decode * @return non-null; the converted string */ - public static String utf8BytesWithUtf16LengthToString(byte[] bytes, int start, int utf16Length) { + public static String utf8BytesWithUtf16LengthToString(@Nonnull byte[] bytes, int start, int utf16Length) { + return utf8BytesWithUtf16LengthToString(bytes, start, utf16Length, null); + } + + /** + * Converts an array of UTF-8 bytes into a string. + * + * @param bytes non-null; the bytes to convert + * @param start the start index of the utf8 string to convert + * @param utf16Length the number of utf16 characters in the string to decode + * @param readLength If non-null, the first element will contain the number of bytes read after the method exits + * @return non-null; the converted string + */ + public static String utf8BytesWithUtf16LengthToString(@Nonnull byte[] bytes, int start, int utf16Length, + @Nullable int[] readLength) { char[] chars = localBuffer.get(); if (chars == null || chars.length < utf16Length) { chars = new char[utf16Length]; @@ -182,7 +197,8 @@ public final class Utf8Utils { } int outAt = 0; - for (int at = start; utf16Length > 0; utf16Length--) { + int at = 0; + for (at = start; utf16Length > 0; utf16Length--) { int v0 = bytes[at] & 0xFF; char out; switch (v0 >> 4) { @@ -247,6 +263,10 @@ public final class Utf8Utils { outAt++; } + if (readLength != null && readLength.length > 0) { + readLength[0] = at - start; + readLength[0] = at - start; + } return new String(chars, 0, outAt); } -- cgit v1.2.3