1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dexfuzz.rawdex;
18 
19 import java.io.IOException;
20 
21 public class EncodedValue implements RawDexObject {
22   public byte valueArg;
23   public byte valueType;
24   public byte[] value;
25   public EncodedArray encodedArray;
26   public EncodedAnnotation encodedAnnotation;
27 
28   private static final byte VALUE_BYTE = 0x00;
29   private static final byte VALUE_ARRAY = 0x1c;
30   private static final byte VALUE_ANNOTATION = 0x1d;
31   private static final byte VALUE_NULL = 0x1e;
32   private static final byte VALUE_BOOLEAN = 0x1f;
33 
34   @Override
read(DexRandomAccessFile file)35   public void read(DexRandomAccessFile file) throws IOException {
36     int valueArgAndType = file.readUnsignedByte();
37 
38     // Get lower 5 bits.
39     valueType = (byte) (valueArgAndType & 0x1f);
40     // Get upper 3 bits.
41     valueArg = (byte) ((valueArgAndType & 0xe0) >> 5);
42 
43     int size = 0;
44 
45     switch (valueType) {
46       case VALUE_BYTE:
47         size = 1;
48         break;
49       case VALUE_ARRAY:
50         (encodedArray = new EncodedArray()).read(file);
51         size = 0; // So we don't read into value.
52         break;
53       case VALUE_ANNOTATION:
54         (encodedAnnotation = new EncodedAnnotation()).read(file);
55         size = 0; // So we don't read into value.
56         break;
57       case VALUE_NULL:
58       case VALUE_BOOLEAN:
59         // No value
60         size = 0;
61         break;
62       default:
63         // All others encode value_arg as (size - 1), so...
64         size = valueArg + 1;
65         break;
66     }
67 
68     if (size != 0) {
69       value = new byte[size];
70       for (int i = 0; i < size; i++) {
71         value[i] = file.readByte();
72       }
73     }
74   }
75 
76   @Override
write(DexRandomAccessFile file)77   public void write(DexRandomAccessFile file) throws IOException {
78     int valueArgAndType = ((valueType) | (valueArg << 5));
79     file.writeByte(valueArgAndType);
80 
81     if (encodedArray != null) {
82       encodedArray.write(file);
83     } else if (encodedAnnotation != null) {
84       encodedAnnotation.write(file);
85     } else if (value != null) {
86       file.write(value);
87     }
88   }
89 
90   @Override
incrementIndex(IndexUpdateKind kind, int insertedIdx)91   public void incrementIndex(IndexUpdateKind kind, int insertedIdx) {
92     if (encodedArray != null) {
93       encodedArray.incrementIndex(kind, insertedIdx);
94     } else if (encodedAnnotation != null) {
95       encodedAnnotation.incrementIndex(kind, insertedIdx);
96     }
97   }
98 }
99