Use QStringBuilder when copying template for modification

This avoids modifying the original string in the case where a
placeholder marker is not found. By marking the variable const we
further avoid checks on the reference count and detaches, also allowing
us to safely reuse it later in the function.

The new approach also fixes an issue where suffix wasn't empty, but the
toLocal8Bit conversion would be. This resulted in a buffer overflow
inside createFileFromTemplate.

Reviewed-by: Shane Kearns
(cherry picked from commit d71d3b1ce31ffc585258330d825ff8ea535254ef)

Change-Id: I6cb3fbc6c653d8a881426fddbc433826365d4816
Reviewed-by: João Abecasis <joao.abecasis@nokia.com>
This commit is contained in:
João Abecasis 2011-08-05 10:57:19 +02:00 committed by Qt by Nokia
parent 6d8963971a
commit b3ca1d4a84

View File

@ -45,6 +45,7 @@
#include "qplatformdefs.h" #include "qplatformdefs.h"
#include "qabstractfileengine.h" #include "qabstractfileengine.h"
#include "qstringbuilder.h"
#include "private/qfile_p.h" #include "private/qfile_p.h"
#include "private/qabstractfileengine_p.h" #include "private/qabstractfileengine_p.h"
#include "private/qfsfileengine_p.h" #include "private/qfsfileengine_p.h"
@ -60,6 +61,38 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
struct Placeholder
{
Placeholder(int size)
: size_(size)
{
}
int size() const
{
return size_;
}
private:
int size_;
};
template <>
struct QConcatenable<Placeholder>
{
typedef Placeholder type;
typedef QByteArray ConvertTo;
enum { ExactSize = true };
static int size(const Placeholder &p) { return p.size(); }
template <class CharT>
static inline void appendTo(const Placeholder &p, CharT *&out)
{
// Uninitialized
out += p.size();
}
};
/* /*
* Copyright (c) 1987, 1993 * Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
@ -258,7 +291,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
if (!filePathIsTemplate) if (!filePathIsTemplate)
return QFSFileEngine::open(openMode); return QFSFileEngine::open(openMode);
QString qfilename = d->fileEntry.filePath(); const QString qfilename = d->fileEntry.filePath();
// Find placeholder string. // Find placeholder string.
uint phPos = qfilename.length(); uint phPos = qfilename.length();
@ -281,22 +314,22 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
phLength = 0; phLength = 0;
} }
QStringRef prefix, suffix; QByteArray filename;
if (phLength < 6) {
qfilename += QLatin1Char('.');
prefix = QStringRef(&qfilename);
phLength = 6;
} else {
prefix = qfilename.leftRef(phPos);
suffix = qfilename.midRef(phPos + phLength);
}
QByteArray filename = prefix.toLocal8Bit(); if (phLength < 6) {
phPos = filename.length(); filename = qfilename.toLocal8Bit();
if (suffix.isEmpty())
filename.resize(phPos + phLength); phPos = filename.length() + 1; // Account for added dot in prefix
else phLength = 6;
filename.insert(phPos + phLength, suffix.toLocal8Bit()); filename = filename % '.' % Placeholder(phLength);
} else {
QByteArray prefix, suffix;
prefix = qfilename.leftRef(phPos).toLocal8Bit();
suffix = qfilename.midRef(phPos + phLength).toLocal8Bit();
phPos = prefix.length();
filename = prefix % Placeholder(phLength) % suffix;
}
int fd = createFileFromTemplate(filename, phPos, phLength); int fd = createFileFromTemplate(filename, phPos, phLength);
@ -323,14 +356,13 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
if (fd == -1) if (fd == -1)
return false; return false;
QString template_ = d->fileEntry.filePath();
d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(filename.constData(), filename.length())); d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(filename.constData(), filename.length()));
if (QFSFileEngine::open(openMode)) { if (QFSFileEngine::open(openMode)) {
filePathIsTemplate = false; filePathIsTemplate = false;
return true; return true;
} }
d->fileEntry = QFileSystemEntry(template_, QFileSystemEntry::FromInternalPath()); d->fileEntry = QFileSystemEntry(qfilename, QFileSystemEntry::FromInternalPath());
return false; return false;
#endif #endif
} }