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