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 case ValueType.METHOD_HANDLE: 105 Preconditions.checkValueArg(valueArg, 3); 106 return new DexBackedMethodHandleEncodedValue(reader, valueArg); 107 case ValueType.METHOD_TYPE: 108 Preconditions.checkValueArg(valueArg, 3); 109 return new DexBackedMethodTypeEncodedValue(reader, valueArg); 110 default: 111 throw new ExceptionWithContext("Invalid encoded_value type: 0x%x", valueType); 112 } 113 } catch (Exception ex) { 114 throw ExceptionWithContext.withContext(ex, "Error while reading encoded value at offset 0x%x", startOffset); 115 } 116 } 117 skipFrom(@onnull DexReader reader)118 public static void skipFrom(@Nonnull DexReader reader) { 119 int startOffset = reader.getOffset(); 120 121 try { 122 int b = reader.readUbyte(); 123 int valueType = b & 0x1f; 124 125 switch (valueType) { 126 case ValueType.BYTE: 127 reader.skipByte(); 128 break; 129 case ValueType.SHORT: 130 case ValueType.CHAR: 131 case ValueType.INT: 132 case ValueType.LONG: 133 case ValueType.FLOAT: 134 case ValueType.DOUBLE: 135 case ValueType.STRING: 136 case ValueType.TYPE: 137 case ValueType.FIELD: 138 case ValueType.METHOD: 139 case ValueType.ENUM: 140 case ValueType.METHOD_HANDLE: 141 case ValueType.METHOD_TYPE: 142 int valueArg = b >>> 5; 143 reader.moveRelative(valueArg+1); 144 break; 145 case ValueType.ARRAY: 146 DexBackedArrayEncodedValue.skipFrom(reader); 147 break; 148 case ValueType.ANNOTATION: 149 DexBackedAnnotationEncodedValue.skipFrom(reader); 150 break; 151 case ValueType.NULL: 152 case ValueType.BOOLEAN: 153 break; 154 default: 155 throw new ExceptionWithContext("Invalid encoded_value type: 0x%x", valueType); 156 } 157 } catch (Exception ex) { 158 throw ExceptionWithContext.withContext(ex, "Error while skipping encoded value at offset 0x%x", 159 startOffset); 160 } 161 } 162 } 163