From b3ca1d4a84ee65e9f9f1e1a4e6de9078279e2187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Fri, 5 Aug 2011 10:57:19 +0200 Subject: [PATCH] Use QStringBuilder when copying template for modification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/corelib/io/qtemporaryfile.cpp | 68 +++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index 5aaabfd14d..82f7d07549 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -45,6 +45,7 @@ #include "qplatformdefs.h" #include "qabstractfileengine.h" +#include "qstringbuilder.h" #include "private/qfile_p.h" #include "private/qabstractfileengine_p.h" #include "private/qfsfileengine_p.h" @@ -60,6 +61,38 @@ QT_BEGIN_NAMESPACE +struct Placeholder +{ + Placeholder(int size) + : size_(size) + { + } + + int size() const + { + return size_; + } + +private: + int size_; +}; + +template <> +struct QConcatenable +{ + typedef Placeholder type; + typedef QByteArray ConvertTo; + enum { ExactSize = true }; + static int size(const Placeholder &p) { return p.size(); } + + template + static inline void appendTo(const Placeholder &p, CharT *&out) + { + // Uninitialized + out += p.size(); + } +}; + /* * Copyright (c) 1987, 1993 * The Regents of the University of California. All rights reserved. @@ -258,7 +291,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) if (!filePathIsTemplate) return QFSFileEngine::open(openMode); - QString qfilename = d->fileEntry.filePath(); + const QString qfilename = d->fileEntry.filePath(); // Find placeholder string. uint phPos = qfilename.length(); @@ -281,22 +314,22 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) phLength = 0; } - QStringRef prefix, suffix; - if (phLength < 6) { - qfilename += QLatin1Char('.'); - prefix = QStringRef(&qfilename); - phLength = 6; - } else { - prefix = qfilename.leftRef(phPos); - suffix = qfilename.midRef(phPos + phLength); - } + QByteArray filename; - QByteArray filename = prefix.toLocal8Bit(); - phPos = filename.length(); - if (suffix.isEmpty()) - filename.resize(phPos + phLength); - else - filename.insert(phPos + phLength, suffix.toLocal8Bit()); + if (phLength < 6) { + filename = qfilename.toLocal8Bit(); + + phPos = filename.length() + 1; // Account for added dot in prefix + phLength = 6; + 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); @@ -323,14 +356,13 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) if (fd == -1) return false; - QString template_ = d->fileEntry.filePath(); d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(filename.constData(), filename.length())); if (QFSFileEngine::open(openMode)) { filePathIsTemplate = false; return true; } - d->fileEntry = QFileSystemEntry(template_, QFileSystemEntry::FromInternalPath()); + d->fileEntry = QFileSystemEntry(qfilename, QFileSystemEntry::FromInternalPath()); return false; #endif }