summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qfsfileengine_unix.cpp
diff options
context:
space:
mode:
authorFrans Englich <frans.englich@nokia.com>2009-11-16 11:52:15 (GMT)
committerFrans Englich <frans.englich@nokia.com>2009-11-16 11:52:15 (GMT)
commit15e2b2d753250bbe01a78d9ece37f0f0b08cd21c (patch)
treea37bb70124fdbecbbaf7e0e2a141a359eaf4f412 /src/corelib/io/qfsfileengine_unix.cpp
parent3328e0ee94b94c83fe9d64f741bede6725f5c952 (diff)
parent7fdfa58b958b658feb7b20dd7a7322d235fe4bea (diff)
downloadQt-15e2b2d753250bbe01a78d9ece37f0f0b08cd21c.zip
Qt-15e2b2d753250bbe01a78d9ece37f0f0b08cd21c.tar.gz
Qt-15e2b2d753250bbe01a78d9ece37f0f0b08cd21c.tar.bz2
Merge branch '4.6' into mmfphonon
Diffstat (limited to 'src/corelib/io/qfsfileengine_unix.cpp')
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp37
1 files changed, 27 insertions, 10 deletions
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index b0cddaa..05e6fab 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -1243,34 +1243,51 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
q->setError(QFile::PermissionsError, qt_error_string(int(EACCES)));
return 0;
}
- if (offset < 0) {
+
+ if (offset < 0 || offset != qint64(QT_OFF_T(offset))
+ || size < 0 || size > qint64(size_t(-1))) {
q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL)));
return 0;
}
+
+ // If we know the mapping will extend beyond EOF, fail early to avoid
+ // undefined behavior. Otherwise, let mmap have its say.
+ if (doStat()
+ && (QT_OFF_T(size) > st.st_size - QT_OFF_T(offset)))
+ return 0;
+
int access = 0;
if (openMode & QIODevice::ReadOnly) access |= PROT_READ;
if (openMode & QIODevice::WriteOnly) access |= PROT_WRITE;
- int pagesSize = getpagesize();
- int realOffset = offset / pagesSize;
- int extra = offset % pagesSize;
+ int pageSize = getpagesize();
+ int extra = offset % pageSize;
+
+ if (size + extra > (size_t)-1) {
+ q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL)));
+ return 0;
+ }
+
+ size_t realSize = (size_t)size + extra;
+ QT_OFF_T realOffset = QT_OFF_T(offset);
+ realOffset &= ~(QT_OFF_T(pageSize - 1));
#ifdef Q_OS_SYMBIAN
void *mapAddress;
- TRAPD(err, mapAddress = mmap((void*)0, (size_t)size + extra,
- access, MAP_SHARED, nativeHandle(), realOffset * pagesSize));
+ TRAPD(err, mapAddress = QT_MMAP((void*)0, realSize,
+ access, MAP_SHARED, nativeHandle(), realOffset));
if (err != KErrNone) {
qWarning("OpenC bug: leave from mmap %d", err);
mapAddress = MAP_FAILED;
errno = EINVAL;
}
#else
- void *mapAddress = mmap((void*)0, (size_t)size + extra,
- access, MAP_SHARED, nativeHandle(), realOffset * pagesSize);
+ void *mapAddress = QT_MMAP((void*)0, realSize,
+ access, MAP_SHARED, nativeHandle(), realOffset);
#endif
if (MAP_FAILED != mapAddress) {
uchar *address = extra + static_cast<uchar*>(mapAddress);
- maps[address] = QPair<int,int>(extra, size);
+ maps[address] = QPair<int,size_t>(extra, realSize);
return address;
}
@@ -1300,7 +1317,7 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr)
}
uchar *start = ptr - maps[ptr].first;
- int len = maps[ptr].second;
+ size_t len = maps[ptr].second;
if (-1 == munmap(start, len)) {
q->setError(QFile::UnspecifiedError, qt_error_string(errno));
return false;