From de722e56dfbd3bf46ae30be6317e03391d424ae6 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Wed, 24 Sep 2014 13:06:35 -0700 Subject: [PATCH] Fix write past end of memory. The computed flattened size of the blob does not match the size used by the flatten function when the last cached entry size is not 4 byte aligned. Bug: 17873145 Change-Id: I9f9fc102d4bde4681ae977b6de5f263aaaf56708 --- libutils/BlobCache.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libutils/BlobCache.cpp b/libutils/BlobCache.cpp index 8edb4013d..0ea09cfa8 100644 --- a/libutils/BlobCache.cpp +++ b/libutils/BlobCache.cpp @@ -31,7 +31,7 @@ namespace android { static const uint32_t blobCacheMagic = ('_' << 24) + ('B' << 16) + ('b' << 8) + '$'; // BlobCache::Header::mBlobCacheVersion value -static const uint32_t blobCacheVersion = 1; +static const uint32_t blobCacheVersion = 2; // BlobCache::Header::mDeviceVersion value static const uint32_t blobCacheDeviceVersion = 1; @@ -165,14 +165,13 @@ static inline size_t align4(size_t size) { } size_t BlobCache::getFlattenedSize() const { - size_t size = sizeof(Header); + size_t size = align4(sizeof(Header)); for (size_t i = 0; i < mCacheEntries.size(); i++) { const CacheEntry& e(mCacheEntries[i]); sp keyBlob = e.getKey(); sp valueBlob = e.getValue(); - size = align4(size); - size += sizeof(EntryHeader) + keyBlob->getSize() + - valueBlob->getSize(); + size += align4(sizeof(EntryHeader) + keyBlob->getSize() + + valueBlob->getSize()); } return size; } @@ -200,7 +199,8 @@ status_t BlobCache::flatten(void* buffer, size_t size) const { size_t valueSize = valueBlob->getSize(); size_t entrySize = sizeof(EntryHeader) + keySize + valueSize; - if (byteOffset + entrySize > size) { + size_t totalSize = align4(entrySize); + if (byteOffset + totalSize > size) { ALOGE("flatten: not enough room for cache entries"); return BAD_VALUE; } @@ -213,7 +213,6 @@ status_t BlobCache::flatten(void* buffer, size_t size) const { memcpy(eheader->mData, keyBlob->getData(), keySize); memcpy(eheader->mData + keySize, valueBlob->getData(), valueSize); - size_t totalSize = align4(entrySize); if (totalSize > entrySize) { // We have padding bytes. Those will get written to storage, and contribute to the CRC, // so make sure we zero-them to have reproducible results. @@ -263,7 +262,8 @@ status_t BlobCache::unflatten(void const* buffer, size_t size) { size_t valueSize = eheader->mValueSize; size_t entrySize = sizeof(EntryHeader) + keySize + valueSize; - if (byteOffset + entrySize > size) { + size_t totalSize = align4(entrySize); + if (byteOffset + totalSize > size) { mCacheEntries.clear(); ALOGE("unflatten: not enough room for cache entry headers"); return BAD_VALUE; @@ -272,7 +272,7 @@ status_t BlobCache::unflatten(void const* buffer, size_t size) { const uint8_t* data = eheader->mData; set(data, keySize, data + keySize, valueSize); - byteOffset += align4(entrySize); + byteOffset += totalSize; } return OK;