1 /*
2  * Copyright (C) 2008 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 /*
18  * Functions to deal with class definition structures in DEX files
19  */
20 
21 #include <stdlib.h>
22 #include <string.h>
23 #include "DexClass.h"
24 #include "Leb128.h"
25 
26 /* Helper for verification which reads and verifies a given number
27  * of uleb128 values. */
verifyUlebs(const u1 * pData,const u1 * pLimit,u4 count)28 static bool verifyUlebs(const u1* pData, const u1* pLimit, u4 count) {
29     bool okay = true;
30 
31     while (okay && (count-- != 0)) {
32         readAndVerifyUnsignedLeb128(&pData, pLimit, &okay);
33     }
34 
35     return okay;
36 }
37 
38 /* Read and verify the header of a class_data_item. This updates the
39  * given data pointer to point past the end of the read data and
40  * returns an "okay" flag (that is, false == failure). */
dexReadAndVerifyClassDataHeader(const u1 ** pData,const u1 * pLimit,DexClassDataHeader * pHeader)41 bool dexReadAndVerifyClassDataHeader(const u1** pData, const u1* pLimit,
42         DexClassDataHeader *pHeader) {
43     if (! verifyUlebs(*pData, pLimit, 4)) {
44         return false;
45     }
46 
47     dexReadClassDataHeader(pData, pHeader);
48     return true;
49 }
50 
51 /* Read and verify an encoded_field. This updates the
52  * given data pointer to point past the end of the read data and
53  * returns an "okay" flag (that is, false == failure).
54  *
55  * The lastIndex value should be set to 0 before the first field in
56  * a list is read. It is updated as fields are read and used in the
57  * decode process.
58  *
59  * The verification done by this function is of the raw data format
60  * only; it does not verify that access flags or indices
61  * are valid. */
dexReadAndVerifyClassDataField(const u1 ** pData,const u1 * pLimit,DexField * pField,u4 * lastIndex)62 bool dexReadAndVerifyClassDataField(const u1** pData, const u1* pLimit,
63         DexField* pField, u4* lastIndex) {
64     if (! verifyUlebs(*pData, pLimit, 2)) {
65         return false;
66     }
67 
68     dexReadClassDataField(pData, pField, lastIndex);
69     return true;
70 }
71 
72 /* Read and verify an encoded_method. This updates the
73  * given data pointer to point past the end of the read data and
74  * returns an "okay" flag (that is, false == failure).
75  *
76  * The lastIndex value should be set to 0 before the first method in
77  * a list is read. It is updated as fields are read and used in the
78  * decode process.
79  *
80  * The verification done by this function is of the raw data format
81  * only; it does not verify that access flags, indices, or offsets
82  * are valid. */
dexReadAndVerifyClassDataMethod(const u1 ** pData,const u1 * pLimit,DexMethod * pMethod,u4 * lastIndex)83 bool dexReadAndVerifyClassDataMethod(const u1** pData, const u1* pLimit,
84         DexMethod* pMethod, u4* lastIndex) {
85     if (! verifyUlebs(*pData, pLimit, 3)) {
86         return false;
87     }
88 
89     dexReadClassDataMethod(pData, pMethod, lastIndex);
90     return true;
91 }
92 
93 /* Read, verify, and return an entire class_data_item. This updates
94  * the given data pointer to point past the end of the read data. This
95  * function allocates a single chunk of memory for the result, which
96  * must subsequently be free()d. This function returns NULL if there
97  * was trouble parsing the data. If this function is passed NULL, it
98  * returns an initialized empty DexClassData structure.
99  *
100  * The verification done by this function is of the raw data format
101  * only; it does not verify that access flags, indices, or offsets
102  * are valid. */
dexReadAndVerifyClassData(const u1 ** pData,const u1 * pLimit)103 DexClassData* dexReadAndVerifyClassData(const u1** pData, const u1* pLimit) {
104     DexClassDataHeader header;
105     u4 lastIndex;
106 
107     if (*pData == NULL) {
108         DexClassData* result = (DexClassData*) malloc(sizeof(DexClassData));
109         memset(result, 0, sizeof(*result));
110         return result;
111     }
112 
113     if (! dexReadAndVerifyClassDataHeader(pData, pLimit, &header)) {
114         return NULL;
115     }
116 
117     size_t resultSize = sizeof(DexClassData) +
118         (header.staticFieldsSize * sizeof(DexField)) +
119         (header.instanceFieldsSize * sizeof(DexField)) +
120         (header.directMethodsSize * sizeof(DexMethod)) +
121         (header.virtualMethodsSize * sizeof(DexMethod));
122 
123     DexClassData* result = (DexClassData*) malloc(resultSize);
124     u1* ptr = ((u1*) result) + sizeof(DexClassData);
125     bool okay = true;
126     u4 i;
127 
128     if (result == NULL) {
129         return NULL;
130     }
131 
132     result->header = header;
133 
134     if (header.staticFieldsSize != 0) {
135         result->staticFields = (DexField*) ptr;
136         ptr += header.staticFieldsSize * sizeof(DexField);
137     } else {
138         result->staticFields = NULL;
139     }
140 
141     if (header.instanceFieldsSize != 0) {
142         result->instanceFields = (DexField*) ptr;
143         ptr += header.instanceFieldsSize * sizeof(DexField);
144     } else {
145         result->instanceFields = NULL;
146     }
147 
148     if (header.directMethodsSize != 0) {
149         result->directMethods = (DexMethod*) ptr;
150         ptr += header.directMethodsSize * sizeof(DexMethod);
151     } else {
152         result->directMethods = NULL;
153     }
154 
155     if (header.virtualMethodsSize != 0) {
156         result->virtualMethods = (DexMethod*) ptr;
157     } else {
158         result->virtualMethods = NULL;
159     }
160 
161     lastIndex = 0;
162     for (i = 0; okay && (i < header.staticFieldsSize); i++) {
163         okay = dexReadAndVerifyClassDataField(pData, pLimit,
164                 &result->staticFields[i], &lastIndex);
165     }
166 
167     lastIndex = 0;
168     for (i = 0; okay && (i < header.instanceFieldsSize); i++) {
169         okay = dexReadAndVerifyClassDataField(pData, pLimit,
170                 &result->instanceFields[i], &lastIndex);
171     }
172 
173     lastIndex = 0;
174     for (i = 0; okay && (i < header.directMethodsSize); i++) {
175         okay = dexReadAndVerifyClassDataMethod(pData, pLimit,
176                 &result->directMethods[i], &lastIndex);
177     }
178 
179     lastIndex = 0;
180     for (i = 0; okay && (i < header.virtualMethodsSize); i++) {
181         okay = dexReadAndVerifyClassDataMethod(pData, pLimit,
182                 &result->virtualMethods[i], &lastIndex);
183     }
184 
185     if (! okay) {
186         free(result);
187         return NULL;
188     }
189 
190     return result;
191 }
192