Skip to content

Commit

Permalink
Fix the fix for mmap() overflow check
Browse files Browse the repository at this point in the history
The code I introduced in 4ee7425 only
dealt with systems that reasonably used a 64-bit off_t parameter. Turns
out that we don't turn on largefile support on 32-bit Android, which
meant that the fix caused a regression.

[ChangeLog][QtCore][QFile] Fixed a regression that caused QFile::map()
to succeed or produce incorrect results when trying to map a file at an
offset beyond 4 GB on 32-bit Android systems and on some special Linux
configurations.

Task-number: QTBUG-69148
Change-Id: I2c133120577fa12a32d444488bac3e341966f8d7
Reviewed-by: Mårten Nordheim <[email protected]>
  • Loading branch information
thiagomacieira authored and Morten242 committed Jul 25, 2018
1 parent fdb780b commit 9a04453
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 7 deletions.
7 changes: 3 additions & 4 deletions src/corelib/io/qfsfileengine_unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,7 @@ bool QFSFileEngine::setFileTime(const QDateTime &newDate, FileTime time)

uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
{
qint64 maxFileOffset = std::numeric_limits<QT_OFF_T>::max();
#if (defined(Q_OS_LINUX) || defined(Q_OS_ANDROID)) && Q_PROCESSOR_WORDSIZE == 4
// The Linux mmap2 system call on 32-bit takes a page-shifted 32-bit
// integer so the maximum offset is 1 << (32+12) (the shift is always 12,
Expand All @@ -642,9 +643,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
// and Bionic): all of them do the right shift, but don't confirm that the
// result fits into the 32-bit parameter to the kernel.

static qint64 MaxFileOffset = (Q_INT64_C(1) << (32+12)) - 1;
#else
static qint64 MaxFileOffset = std::numeric_limits<QT_OFF_T>::max();
maxFileOffset = qMin((Q_INT64_C(1) << (32+12)) - 1, maxFileOffset);
#endif

Q_Q(QFSFileEngine);
Expand All @@ -653,7 +652,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
return 0;
}

if (offset < 0 || offset > MaxFileOffset
if (offset < 0 || offset > maxFileOffset
|| size < 0 || quint64(size) > quint64(size_t(-1))) {
q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL)));
return 0;
Expand Down
6 changes: 3 additions & 3 deletions tests/auto/corelib/io/largefile/tst_largefile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ void tst_LargeFile::mapFile()
//Mac: memory-mapping beyond EOF may succeed but it could generate bus error on access
//FreeBSD: same
//Linux: memory-mapping beyond EOF usually succeeds, but depends on the filesystem
// 32-bit: limited to 44-bit offsets
// 32-bit: limited to 44-bit offsets (when sizeof(off_t) == 8)
//Windows: memory-mapping beyond EOF is not allowed
void tst_LargeFile::mapOffsetOverflow()
{
Expand All @@ -521,9 +521,9 @@ void tst_LargeFile::mapOffsetOverflow()
#else
Succeeds = true,
# if (defined(Q_OS_LINUX) || defined(Q_OS_ANDROID)) && Q_PROCESSOR_WORDSIZE == 4
MaxOffset = 43
MaxOffset = sizeof(QT_OFF_T) > 4 ? 43 : 30
# else
MaxOffset = 63
MaxOffset = 8 * sizeof(QT_OFF_T) - 1
# endif
#endif
};
Expand Down

0 comments on commit 9a04453

Please sign in to comment.