summaryrefslogtreecommitdiffstats
path: root/libs/androidfw
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2013-02-15 09:37:11 -0800
committerKenny Root <kroot@google.com>2013-02-15 11:05:48 -0800
commitc6e35cb47a90a43b5a0009f526b695b2b5c87465 (patch)
treef7d7a151e46f6d13fc3568ec8b704d8a9c53d364 /libs/androidfw
parent9657ba0edc8bab5a36c26bcd94366149aed63331 (diff)
downloadframeworks_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.cpp24
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;