1 /* 2 * Copyright 2012, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 package org.jf.dexlib2.dexbacked.value; 33 34 import org.jf.dexlib2.ValueType; 35 import org.jf.dexlib2.dexbacked.DexReader; 36 import org.jf.dexlib2.iface.value.EncodedValue; 37 import org.jf.dexlib2.immutable.value.*; 38 import org.jf.dexlib2.util.Preconditions; 39 import org.jf.util.ExceptionWithContext; 40 41 import javax.annotation.Nonnull; 42 43 public abstract class DexBackedEncodedValue { 44 @Nonnull readFrom(@onnull DexReader reader)45 public static EncodedValue readFrom(@Nonnull DexReader reader) { 46 int startOffset = reader.getOffset(); 47 48 try { 49 int b = reader.readUbyte(); 50 int valueType = b & 0x1f; 51 int valueArg = b >>> 5; 52 53 switch (valueType) { 54 case ValueType.BYTE: 55 Preconditions.checkValueArg(valueArg, 0); 56 return new ImmutableByteEncodedValue((byte)reader.readByte()); 57 case ValueType.SHORT: 58 Preconditions.checkValueArg(valueArg, 1); 59 return new ImmutableShortEncodedValue((short)reader.readSizedInt(valueArg + 1)); 60 case ValueType.CHAR: 61 Preconditions.checkValueArg(valueArg, 1); 62 return new ImmutableCharEncodedValue((char)reader.readSizedSmallUint(valueArg + 1)); 63 case ValueType.INT: 64 Preconditions.checkValueArg(valueArg, 3); 65 return new ImmutableIntEncodedValue(reader.readSizedInt(valueArg + 1)); 66 case ValueType.LONG: 67 Preconditions.checkValueArg(valueArg, 7); 68 return new ImmutableLongEncodedValue(reader.readSizedLong(valueArg + 1)); 69 case ValueType.FLOAT: 70 Preconditions.checkValueArg(valueArg, 3); 71 return new ImmutableFloatEncodedValue(Float.intBitsToFloat( 72 reader.readSizedRightExtendedInt(valueArg + 1))); 73 case ValueType.DOUBLE: 74 Preconditions.checkValueArg(valueArg, 7); 75 return new ImmutableDoubleEncodedValue(Double.longBitsToDouble( 76 reader.readSizedRightExtendedLong(valueArg + 1))); 77 case ValueType.STRING: 78 Preconditions.checkValueArg(valueArg, 3); 79 return new DexBackedStringEncodedValue(reader, valueArg); 80 case ValueType.TYPE: 81 Preconditions.checkValueArg(valueArg, 3); 82 return new DexBackedTypeEncodedValue(reader, valueArg); 83 case ValueType.FIELD: 84 Preconditions.checkValueArg(valueArg, 3); 85 return new DexBackedFieldEncodedValue(reader, valueArg); 86 case ValueType.METHOD: 87 Preconditions.checkValueArg(valueArg, 3); 88 return new DexBackedMethodEncodedValue(reader, valueArg); 89 case ValueType.ENUM: 90 Preconditions.checkValueArg(valueArg, 3); 91 return new DexBackedEnumEncodedValue(reader, valueArg); 92 case ValueType.ARRAY: 93 Preconditions.checkValueArg(valueArg, 0); 94 return new DexBackedArrayEncodedValue(reader); 95 case ValueType.ANNOTATION: 96 Preconditions.checkValueArg(valueArg, 0); 97 return new DexBackedAnnotationEncodedValue(reader); 98 case ValueType.NULL: 99 Preconditions.checkValueArg(valueArg, 0); 100 return ImmutableNullEncodedValue.INSTANCE; 101 case ValueType.BOOLEAN: 102 Preconditions.checkValueArg(valueArg, 1); 103 return ImmutableBooleanEncodedValue.forBoolean(valueArg == 1); 104 default: 105 throw new ExceptionWithContext("Invalid encoded_value type: 0x%x", valueType); 106 } 107 } catch (Exception ex) { 108 throw ExceptionWithContext.withContext(ex, "Error while reading encoded value at offset 0x%x", startOffset); 109 } 110 } 111 skipFrom(@onnull DexReader reader)112 public static void skipFrom(@Nonnull DexReader reader) { 113 int startOffset = reader.getOffset(); 114 115 try { 116 int b = reader.readUbyte(); 117 int valueType = b & 0x1f; 118 119 switch (valueType) { 120 case ValueType.BYTE: 121 reader.skipByte(); 122 break; 123 case ValueType.SHORT: 124 case ValueType.CHAR: 125 case ValueType.INT: 126 case ValueType.LONG: 127 case ValueType.FLOAT: 128 case ValueType.DOUBLE: 129 case ValueType.STRING: 130 case ValueType.TYPE: 131 case ValueType.FIELD: 132 case ValueType.METHOD: 133 case ValueType.ENUM: 134 int valueArg = b >>> 5; 135 reader.moveRelative(valueArg+1); 136 break; 137 case ValueType.ARRAY: 138 DexBackedArrayEncodedValue.skipFrom(reader); 139 break; 140 case ValueType.ANNOTATION: 141 DexBackedAnnotationEncodedValue.skipFrom(reader); 142 break; 143 case ValueType.NULL: 144 case ValueType.BOOLEAN: 145 break; 146 default: 147 throw new ExceptionWithContext("Invalid encoded_value type: 0x%x", valueType); 148 } 149 } catch (Exception ex) { 150 throw ExceptionWithContext.withContext(ex, "Error while skipping encoded value at offset 0x%x", 151 startOffset); 152 } 153 } 154 } 155