diff options
Diffstat (limited to 'src/corelib/io/qresource.cpp')
-rw-r--r-- | src/corelib/io/qresource.cpp | 150 |
1 files changed, 56 insertions, 94 deletions
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index af0b9429af..b76d2b6478 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Copyright (C) 2020 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// Copyright (C) 2020 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qresource.h" #include "qresource_p.h" @@ -69,7 +33,7 @@ # include <zstd.h> #endif -#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY) +#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY) # define QT_USE_MMAP # include <sys/mman.h> #endif @@ -78,6 +42,8 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + // Symbols used by code generated by RCC. // They cause compilation errors if the RCC content couldn't // be interpreted by this QtCore version. @@ -116,7 +82,7 @@ public: inline QStringView next() { - int start = m_pos; + const qsizetype start = m_pos; while (m_pos < m_len && m_data[m_pos] != m_splitChar) ++m_pos; return QStringView(m_data + start, m_pos - start); @@ -125,7 +91,7 @@ public: const QChar *m_data; qsizetype m_len; qsizetype m_pos = 0; - QChar m_splitChar = QLatin1Char('/'); + QChar m_splitChar = u'/'; }; // resource glue @@ -189,7 +155,7 @@ static QString cleanPath(const QString &_path) QString path = QDir::cleanPath(_path); // QDir::cleanPath does not remove two trailing slashes under _Windows_ // due to support for UNC paths. Remove those manually. - if (path.startsWith(QLatin1String("//"))) + if (path.startsWith("//"_L1)) path.remove(0, 1); return path; } @@ -201,7 +167,6 @@ struct QResourceGlobalData { QRecursiveMutex resourceMutex; ResourceList resourceList; - QStringList resourceSearchPaths; }; Q_GLOBAL_STATIC(QResourceGlobalData, resourceGlobalData) @@ -211,9 +176,6 @@ static inline QRecursiveMutex &resourceMutex() static inline ResourceList *resourceList() { return &resourceGlobalData->resourceList; } -static inline QStringList *resourceSearchPaths() -{ return &resourceGlobalData->resourceSearchPaths; } - /*! \class QResource \inmodule QtCore @@ -271,6 +233,19 @@ static inline QStringList *resourceSearchPaths() itself will be unmapped from memory when the last QResource that points to it is destroyed. + \section2 Corruption and Security + + The QResource class performs some checks on the file passed to determine + whether it is supported by the current version of Qt. Those tests are only + to check the file header does not request features (such as Zstandard + decompression) that have not been compiled in or that the file is not of a + future version of Qt. They do not confirm the validity of the entire file. + + QResource should not be used on files whose provenance cannot be trusted. + Applications should be designed to attempt to load only resource files + whose provenance is at least as trustworthy as that of the application + itself or its plugins. + \sa {The Qt Resource System}, QFile, QDir, QFileInfo */ @@ -381,29 +356,23 @@ void QResourcePrivate::ensureInitialized() const if (!related.isEmpty()) return; QResourcePrivate *that = const_cast<QResourcePrivate *>(this); - if (fileName == QLatin1String(":")) - that->fileName += QLatin1Char('/'); + if (fileName == ":"_L1) + that->fileName += u'/'; that->absoluteFilePath = fileName; - if (!that->absoluteFilePath.startsWith(QLatin1Char(':'))) - that->absoluteFilePath.prepend(QLatin1Char(':')); + if (!that->absoluteFilePath.startsWith(u':')) + that->absoluteFilePath.prepend(u':'); QStringView path(fileName); - if (path.startsWith(QLatin1Char(':'))) + if (path.startsWith(u':')) path = path.mid(1); - if (path.startsWith(QLatin1Char('/'))) { + if (path.startsWith(u'/')) { that->load(path.toString()); } else { - const auto locker = qt_scoped_lock(resourceMutex()); - QStringList searchPaths = *resourceSearchPaths(); - searchPaths << QLatin1String(""); - for (int i = 0; i < searchPaths.size(); ++i) { - const QString searchPath(searchPaths.at(i) + QLatin1Char('/') + path); - if (that->load(searchPath)) { - that->absoluteFilePath = QLatin1Char(':') + searchPath; - break; - } - } + // Should we search QDir::searchPath() before falling back to root ? + const QString searchPath(u'/' + path); + if (that->load(searchPath)) + that->absoluteFilePath = u':' + searchPath; } } @@ -414,7 +383,7 @@ void QResourcePrivate::ensureChildren() const return; QString path = absoluteFilePath, k; - if (path.startsWith(QLatin1Char(':'))) + if (path.startsWith(u':')) path = path.mid(1); QDuplicateTracker<QString> kids(related.size()); QString cleaned = cleanPath(path); @@ -797,7 +766,7 @@ inline QString QResourceRoot::name(int node) const ret.resize(name_length); QChar *strData = ret.data(); - qFromBigEndian<ushort>(names + name_offset, name_length, strData); + qFromBigEndian<char16_t>(names + name_offset, name_length, strData); return ret; } @@ -808,14 +777,14 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const QString root = mappingRoot(); if (!root.isEmpty()) { if (root == path) { - path = QLatin1Char('/'); + path = u'/'; } else { - if (!root.endsWith(QLatin1Char('/'))) - root += QLatin1Char('/'); + if (!root.endsWith(u'/')) + root += u'/'; if (path.size() >= root.size() && path.startsWith(root)) - path = path.mid(root.length() - 1); + path = path.mid(root.size() - 1); if (path.isEmpty()) - path = QLatin1Char('/'); + path = u'/'; } } } @@ -823,7 +792,7 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const qDebug() << "!!!!" << "START" << path << locale.territory() << locale.language(); #endif - if (path == QLatin1String("/")) + if (path == "/"_L1) return 0; // the root node is always first @@ -1228,7 +1197,7 @@ bool QDynamicFileResourceRoot::registerSelf(const QString &f) static QString qt_resource_fixResourceRoot(QString r) { if (!r.isEmpty()) { - if (r.startsWith(QLatin1Char(':'))) + if (r.startsWith(u':')) r = r.mid(1); if (!r.isEmpty()) r = QDir::cleanPath(r); @@ -1249,7 +1218,7 @@ static QString qt_resource_fixResourceRoot(QString r) bool QResource::registerResource(const QString &rccFilename, const QString &resourceRoot) { QString r = qt_resource_fixResourceRoot(resourceRoot); - if (!r.isEmpty() && r[0] != QLatin1Char('/')) { + if (!r.isEmpty() && r[0] != u'/') { qWarning("QDir::registerResource: Registering a resource [%ls] must be rooted in an " "absolute path (start with /) [%ls]", qUtf16Printable(rccFilename), qUtf16Printable(resourceRoot)); @@ -1318,7 +1287,7 @@ bool QResource::unregisterResource(const QString &rccFilename, const QString &re bool QResource::registerResource(const uchar *rccData, const QString &resourceRoot) { QString r = qt_resource_fixResourceRoot(resourceRoot); - if (!r.isEmpty() && r[0] != QLatin1Char('/')) { + if (!r.isEmpty() && r[0] != u'/') { qWarning("QDir::registerResource: Registering a resource [%p] must be rooted in an " "absolute path (start with /) [%ls]", rccData, qUtf16Printable(resourceRoot)); @@ -1512,7 +1481,7 @@ QAbstractFileEngine::FileFlags QResourceFileEngine::fileFlags(QAbstractFileEngin } if (type & FlagsMask) { ret |= ExistsFlag; - if (d->resource.absoluteFilePath() == QLatin1String(":/")) + if (d->resource.absoluteFilePath() == ":/"_L1) ret |= RootFlag; } return ret; @@ -1522,24 +1491,24 @@ QString QResourceFileEngine::fileName(FileName file) const { Q_D(const QResourceFileEngine); if (file == BaseName) { - int slash = d->resource.fileName().lastIndexOf(QLatin1Char('/')); + const qsizetype slash = d->resource.fileName().lastIndexOf(u'/'); if (slash == -1) return d->resource.fileName(); return d->resource.fileName().mid(slash + 1); } else if (file == PathName || file == AbsolutePathName) { const QString path = (file == AbsolutePathName) ? d->resource.absoluteFilePath() : d->resource.fileName(); - const int slash = path.lastIndexOf(QLatin1Char('/')); + const qsizetype slash = path.lastIndexOf(u'/'); if (slash == -1) - return QLatin1String(":"); + return ":"_L1; else if (slash <= 1) - return QLatin1String(":/"); + return ":/"_L1; return path.left(slash); } else if (file == CanonicalName || file == CanonicalPathName) { const QString absoluteFilePath = d->resource.absoluteFilePath(); if (file == CanonicalPathName) { - const int slash = absoluteFilePath.lastIndexOf(QLatin1Char('/')); + const qsizetype slash = absoluteFilePath.lastIndexOf(u'/'); if (slash != -1) return absoluteFilePath.left(slash); } @@ -1554,10 +1523,10 @@ uint QResourceFileEngine::ownerId(FileOwner) const return nobodyID; } -QDateTime QResourceFileEngine::fileTime(FileTime time) const +QDateTime QResourceFileEngine::fileTime(QFile::FileTime time) const { Q_D(const QResourceFileEngine); - if (time == ModificationTime) + if (time == QFile::FileModificationTime) return d->resource.lastModified(); return QDateTime(); } @@ -1565,18 +1534,11 @@ QDateTime QResourceFileEngine::fileTime(FileTime time) const /*! \internal */ -QAbstractFileEngine::Iterator *QResourceFileEngine::beginEntryList(QDir::Filters filters, - const QStringList &filterNames) -{ - return new QResourceFileEngineIterator(filters, filterNames); -} - -/*! - \internal -*/ -QAbstractFileEngine::Iterator *QResourceFileEngine::endEntryList() +QAbstractFileEngine::IteratorUniquePtr +QResourceFileEngine::beginEntryList(const QString &path, QDir::Filters filters, + const QStringList &filterNames) { - return nullptr; + return std::make_unique<QResourceFileEngineIterator>(path, filters, filterNames); } bool QResourceFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output) @@ -1608,7 +1570,7 @@ uchar *QResourceFileEnginePrivate::map(qint64 offset, qint64 size, QFile::Memory qint64 max = resource.uncompressedSize(); qint64 end; if (offset < 0 || size <= 0 || !resource.isValid() || - add_overflow(offset, size, &end) || end > max) { + qAddOverflow(offset, size, &end) || end > max) { q->setError(QFile::UnspecifiedError, QString()); return nullptr; } |