| 1232 | } |
| 1233 | |
| 1234 | bool DexFileVerifier::CheckIntraCodeItem() { |
| 1235 | const DexFile::CodeItem* code_item = reinterpret_cast<const DexFile::CodeItem*>(ptr_); |
| 1236 | if (!CheckListSize(code_item, 1, sizeof(DexFile::CodeItem), "code")) { |
| 1237 | return false; |
| 1238 | } |
| 1239 | |
| 1240 | CodeItemDataAccessor accessor(*dex_file_, code_item); |
| 1241 | if (UNLIKELY(accessor.InsSize() > accessor.RegistersSize())) { |
| 1242 | ErrorStringPrintf("ins_size (%ud) > registers_size (%ud)", |
| 1243 | accessor.InsSize(), accessor.RegistersSize()); |
| 1244 | return false; |
| 1245 | } |
| 1246 | |
| 1247 | if (UNLIKELY(accessor.OutsSize() > 5 && accessor.OutsSize() > accessor.RegistersSize())) { |
| 1248 | /* |
| 1249 | * outs_size can be up to 5, even if registers_size is smaller, since the |
| 1250 | * short forms of method invocation allow repetitions of a register multiple |
| 1251 | * times within a single parameter list. However, longer parameter lists |
| 1252 | * need to be represented in-order in the register file. |
| 1253 | */ |
| 1254 | ErrorStringPrintf("outs_size (%ud) > registers_size (%ud)", |
| 1255 | accessor.OutsSize(), accessor.RegistersSize()); |
| 1256 | return false; |
| 1257 | } |
| 1258 | |
| 1259 | const uint16_t* insns = accessor.Insns(); |
| 1260 | uint32_t insns_size = accessor.InsnsSizeInCodeUnits(); |
| 1261 | if (!CheckListSize(insns, insns_size, sizeof(uint16_t), "insns size")) { |
| 1262 | return false; |
| 1263 | } |
| 1264 | |
| 1265 | // Grab the end of the insns if there are no try_items. |
| 1266 | uint32_t try_items_size = accessor.TriesSize(); |
| 1267 | if (try_items_size == 0) { |
| 1268 | ptr_ = reinterpret_cast<const uint8_t*>(&insns[insns_size]); |
| 1269 | return true; |
| 1270 | } |
| 1271 | |
| 1272 | // try_items are 4-byte aligned. Verify the spacer is 0. |
| 1273 | if (((reinterpret_cast<uintptr_t>(&insns[insns_size]) & 3) != 0) && (insns[insns_size] != 0)) { |
| 1274 | ErrorStringPrintf("Non-zero padding: %x", insns[insns_size]); |
| 1275 | return false; |
| 1276 | } |
| 1277 | |
| 1278 | const DexFile::TryItem* try_items = accessor.TryItems().begin(); |
| 1279 | if (!CheckListSize(try_items, try_items_size, sizeof(DexFile::TryItem), "try_items size")) { |
| 1280 | return false; |
| 1281 | } |
| 1282 | |
| 1283 | ptr_ = accessor.GetCatchHandlerData(); |
| 1284 | DECODE_UNSIGNED_CHECKED_FROM(ptr_, handlers_size); |
| 1285 | |
| 1286 | if (UNLIKELY((handlers_size == 0) || (handlers_size >= 65536))) { |
| 1287 | ErrorStringPrintf("Invalid handlers_size: %ud", handlers_size); |
| 1288 | return false; |
| 1289 | } |
| 1290 | |
| 1291 | std::unique_ptr<uint32_t[]> handler_offsets(new uint32_t[handlers_size]); |
nothing calls this directly
no test coverage detected