diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2018-11-08 14:16:33 -0800 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2018-12-12 16:36:09 +0000 |
commit | d20c9805763ab3dc504ebf2cefd33499d89ef22c (patch) | |
tree | d6c9b9f2694461ff0cfe41ce4801ad34cdc05a37 /src/corelib/io/qresource.cpp | |
parent | c820e0b11745750a18460f85b697230881438006 (diff) |
Resources: reject compressed content we can't decompress
This solution is composed of two features:
1) C++ code generated by RCC uses two symbols exported from QtCore that
are only present if the feature was compiled in. If the feature was not
compiled in, this will cause a linker error either at build time or at
load time (if they were functions, the error could be at runtime).
2) Binary files generated by RCC have a new header field containing
flags. We're currently using two flags, one for Zlib and one for
Zstandard.
This means we now have binary RCC format version 3.
Change-Id: I42a48bd64ccc41aebf84fffd156545fb6a4f72d9
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib/io/qresource.cpp')
-rw-r--r-- | src/corelib/io/qresource.cpp | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 52a20191a9..804029725a 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -77,6 +77,26 @@ QT_BEGIN_NAMESPACE +// Symbols used by code generated by RCC. +// They cause compilation errors if the RCC content couldn't +// be interpreted by this QtCore version. +#if defined(__ELF__) || defined(__APPLE__) // same as RCC generates +# define RCC_FEATURE_SYMBOL(feature) \ + extern Q_CORE_EXPORT const quint8 qt_resourceFeature ## feature; \ + const quint8 qt_resourceFeature ## feature = 0; +#else +# define RCC_FEATURE_SYMBOL(feature) \ + Q_CORE_EXPORT quint8 qResourceFeature ## feature() { return 0; } +#endif + +#ifndef QT_NO_COMPRESS +RCC_FEATURE_SYMBOL(Zlib) +#endif +#if QT_CONFIG(zstd) +RCC_FEATURE_SYMBOL(Zstd) +#endif + +#undef RCC_FEATURE_SYMBOL class QStringSplitter { @@ -109,6 +129,7 @@ public: //resource glue class QResourceRoot { +public: enum Flags { // must match rcc.h @@ -116,6 +137,7 @@ class QResourceRoot Directory = 0x02, CompressedZstd = 0x04 }; +private: const uchar *tree, *names, *payloads; int version; inline int findOffset(int node) const { return node * (14 + (version >= 0x02 ? 8 : 0)); } //sizeof each tree element @@ -917,7 +939,7 @@ Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree, const unsigned char *name, const unsigned char *data) { QMutexLocker lock(resourceMutex()); - if ((version == 0x01 || version == 0x2) && resourceList()) { + if (version >= 0x01 && version <= 0x3 && resourceList()) { bool found = false; QResourceRoot res(version, tree, name, data); for(int i = 0; i < resourceList()->size(); ++i) { @@ -943,7 +965,7 @@ Q_CORE_EXPORT bool qUnregisterResourceData(int version, const unsigned char *tre return false; QMutexLocker lock(resourceMutex()); - if ((version == 0x01 || version == 0x02) && resourceList()) { + if (version >= 0x01 && version <= 0x3 && resourceList()) { QResourceRoot res(version, tree, name, data); for(int i = 0; i < resourceList()->size(); ) { if(*resourceList()->at(i) == res) { @@ -1002,11 +1024,27 @@ public: const int name_offset = qFromBigEndian<qint32>(b + offset); offset += 4; + quint32 file_flags = 0; + if (version >= 3) { + file_flags = qFromBigEndian<qint32>(b + offset); + offset += 4; + } + // Some sanity checking for sizes. This is _not_ a security measure. if (size >= 0 && (tree_offset >= size || data_offset >= size || name_offset >= size)) return false; - if (version == 0x01 || version == 0x02) { + // And some sanity checking for features + quint32 acceptableFlags = 0; +#ifndef QT_NO_COMPRESS + acceptableFlags |= Compressed; +#endif + if (QT_CONFIG(zstd)) + acceptableFlags |= CompressedZstd; + if (file_flags & ~acceptableFlags) + return false; + + if (version >= 0x01 && version <= 0x03) { buffer = b; setSource(version, b+tree_offset, b+name_offset, b+data_offset); return true; |