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