diff options
author | Kenny Root <kroot@google.com> | 2013-02-15 09:37:11 -0800 |
---|---|---|
committer | Kenny Root <kroot@google.com> | 2013-02-15 11:05:48 -0800 |
commit | c6e35cb47a90a43b5a0009f526b695b2b5c87465 (patch) | |
tree | f7d7a151e46f6d13fc3568ec8b704d8a9c53d364 /libs/androidfw | |
parent | 9657ba0edc8bab5a36c26bcd94366149aed63331 (diff) | |
download | frameworks_base-c6e35cb47a90a43b5a0009f526b695b2b5c87465.zip frameworks_base-c6e35cb47a90a43b5a0009f526b695b2b5c87465.tar.gz frameworks_base-c6e35cb47a90a43b5a0009f526b695b2b5c87465.tar.bz2 |
StreamingZipInflater: fix mmap'd end of read
When reaching the end of a mmap'd segment, it was erroneously trying to
read more data. This is because we were reading data one character at a
time, so we never reached the Z_STREAM_END result without going through
the loop once more.
Bug: https://code.google.com/p/android/issues/detail?id=39041
Change-Id: I6c53b8187384a42217c32112d6a0c2857f471109
Diffstat (limited to 'libs/androidfw')
-rw-r--r-- | libs/androidfw/StreamingZipInflater.cpp | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/libs/androidfw/StreamingZipInflater.cpp b/libs/androidfw/StreamingZipInflater.cpp index d3fb98d..1dfec23 100644 --- a/libs/androidfw/StreamingZipInflater.cpp +++ b/libs/androidfw/StreamingZipInflater.cpp @@ -23,6 +23,23 @@ #include <string.h> #include <stddef.h> #include <assert.h> +#include <unistd.h> +#include <errno.h> + +/* + * TEMP_FAILURE_RETRY is defined by some, but not all, versions of + * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's + * not already defined, then define it here. + */ +#ifndef TEMP_FAILURE_RETRY +/* Used to retry syscalls that can return EINTR. */ +#define TEMP_FAILURE_RETRY(exp) ({ \ + typeof (exp) _rc; \ + do { \ + _rc = (exp); \ + } while (_rc == -1 && errno == EINTR); \ + _rc; }) +#endif static inline size_t min_of(size_t a, size_t b) { return (a < b) ? a : b; } @@ -135,7 +152,7 @@ ssize_t StreamingZipInflater::read(void* outBuf, size_t count) { // if we don't have any data to decode, read some in. If we're working // from mmapped data this won't happen, because the clipping to total size // will prevent reading off the end of the mapped input chunk. - if (mInflateState.avail_in == 0) { + if ((mInflateState.avail_in == 0) && (mDataMap == NULL)) { int err = readNextChunk(); if (err < 0) { ALOGE("Unable to access asset data: %d", err); @@ -191,11 +208,10 @@ int StreamingZipInflater::readNextChunk() { if (mInNextChunkOffset < mInTotalSize) { size_t toRead = min_of(mInBufSize, mInTotalSize - mInNextChunkOffset); if (toRead > 0) { - ssize_t didRead = ::read(mFd, mInBuf, toRead); + ssize_t didRead = TEMP_FAILURE_RETRY(::read(mFd, mInBuf, toRead)); //ALOGV("Reading input chunk, size %08x didread %08x", toRead, didRead); if (didRead < 0) { - // TODO: error - ALOGE("Error reading asset data"); + ALOGE("Error reading asset data: %s", strerror(errno)); return didRead; } else { mInNextChunkOffset += didRead; |