1 /* 2 * Copyright (C) 2016 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 #include "androidfw/Chunk.h" 18 19 #include "android-base/logging.h" 20 21 namespace android { 22 Next()23Chunk ChunkIterator::Next() { 24 CHECK(len_ != 0) << "called Next() after last chunk"; 25 26 const ResChunk_header* this_chunk = next_chunk_; 27 28 // We've already checked the values of this_chunk, so safely increment. 29 next_chunk_ = reinterpret_cast<const ResChunk_header*>( 30 reinterpret_cast<const uint8_t*>(this_chunk) + dtohl(this_chunk->size)); 31 len_ -= dtohl(this_chunk->size); 32 33 if (len_ != 0) { 34 // Prepare the next chunk. 35 if (VerifyNextChunkNonFatal()) { 36 VerifyNextChunk(); 37 } 38 } 39 return Chunk(this_chunk); 40 } 41 42 // TODO(b/111401637) remove this and have full resource file verification 43 // Returns false if there was an error. VerifyNextChunkNonFatal()44bool ChunkIterator::VerifyNextChunkNonFatal() { 45 if (len_ < sizeof(ResChunk_header)) { 46 last_error_ = "not enough space for header"; 47 last_error_was_fatal_ = false; 48 return false; 49 } 50 const size_t size = dtohl(next_chunk_->size); 51 if (size > len_) { 52 last_error_ = "chunk size is bigger than given data"; 53 last_error_was_fatal_ = false; 54 return false; 55 } 56 return true; 57 } 58 59 // Returns false if there was an error. VerifyNextChunk()60bool ChunkIterator::VerifyNextChunk() { 61 const uintptr_t header_start = reinterpret_cast<uintptr_t>(next_chunk_); 62 63 // This data must be 4-byte aligned, since we directly 64 // access 32-bit words, which must be aligned on 65 // certain architectures. 66 if (header_start & 0x03) { 67 last_error_ = "header not aligned on 4-byte boundary"; 68 return false; 69 } 70 71 if (len_ < sizeof(ResChunk_header)) { 72 last_error_ = "not enough space for header"; 73 return false; 74 } 75 76 const size_t header_size = dtohs(next_chunk_->headerSize); 77 const size_t size = dtohl(next_chunk_->size); 78 if (header_size < sizeof(ResChunk_header)) { 79 last_error_ = "header size too small"; 80 return false; 81 } 82 83 if (header_size > size) { 84 last_error_ = "header size is larger than entire chunk"; 85 return false; 86 } 87 88 if (size > len_) { 89 last_error_ = "chunk size is bigger than given data"; 90 return false; 91 } 92 93 if ((size | header_size) & 0x03) { 94 last_error_ = "header sizes are not aligned on 4-byte boundary"; 95 return false; 96 } 97 return true; 98 } 99 100 } // namespace android 101