Fix the fix for mmap() overflow check

The code I introduced in 4ee7425794 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 <marten.nordheim@qt.io>
bb10
Thiago Macieira 2018-06-28 18:36:36 -07:00 committed by Mårten Nordheim
parent fdb780b897
commit 9a04453b50
2 changed files with 6 additions and 7 deletions

View File

@ -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,
@ -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);
@ -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;

View File

@ -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()
{
@ -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
};