QCssParser: statically verify QCssKnownValue arrays
Port from explicit array sizes to implicit ones, followed by an explicit size check. This prevents mistakes where, due to missing initializers, value-constructed trailing elements cause lower_bound() to be called out-of-contract, such as the one 5d8f815e101da3ae9cd6a666cc097853f52b21da fixed. Also statically verify that the arrays are sorted. This doesn't work on GCC < 10, e.g. QNX, so guard it the same way we did in qhttpheaders.cpp in e3fe3997ebd2baaafdfa7aa3c1eb95e8048268f8. Task-number: QTBUG-103721 Pick-to: 6.8 6.5 Change-Id: Ia55149102013fa4e1619be68a69bc52b46e0f006 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io> (cherry picked from commit ddf69669d39919b20a2710211911587353fa3dce) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
8909279d3e
commit
18f0dd9bdf
@ -15,7 +15,7 @@
|
|||||||
#include <qimagereader.h>
|
#include <qimagereader.h>
|
||||||
#include <qtextformat.h>
|
#include <qtextformat.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <QtCore/q20algorithm.h>
|
||||||
|
|
||||||
#ifndef QT_NO_CSSPARSER
|
#ifndef QT_NO_CSSPARSER
|
||||||
|
|
||||||
@ -35,10 +35,30 @@ struct QCssKnownValue
|
|||||||
{
|
{
|
||||||
const char name[28];
|
const char name[28];
|
||||||
quint64 id;
|
quint64 id;
|
||||||
|
|
||||||
|
struct ByName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct QCssKnownValue::ByName
|
||||||
|
{
|
||||||
|
constexpr bool operator()(const QCssKnownValue &lhs, const QCssKnownValue &rhs) const noexcept
|
||||||
|
{ return std::string_view{lhs.name} < std::string_view{rhs.name}; }
|
||||||
|
};
|
||||||
|
#if !defined(Q_CC_GNU_ONLY) || Q_CC_GNU >= 1000
|
||||||
|
# define NOT_OLD_GCCs(...) __VA_ARGS__
|
||||||
|
#else
|
||||||
|
# define NOT_OLD_GCCs(...) /* nothing */
|
||||||
|
#endif
|
||||||
|
#define CHECK_ARRAY_IS_SORTED(array, Num) \
|
||||||
|
static_assert(std::size(array) == Num); \
|
||||||
|
NOT_OLD_GCCs( \
|
||||||
|
static_assert(q20::is_sorted(std::begin(array), std::end(array), \
|
||||||
|
QCssKnownValue::ByName{})); \
|
||||||
|
) /* NOT_OLD_GCCs */ \
|
||||||
|
/* end */
|
||||||
|
|
||||||
// This array is sorted alphabetically.
|
// This array is sorted alphabetically.
|
||||||
static const QCssKnownValue properties[NumProperties - 1] = {
|
static constexpr QCssKnownValue properties[] = {
|
||||||
{ "-qt-background-role", QtBackgroundRole },
|
{ "-qt-background-role", QtBackgroundRole },
|
||||||
{ "-qt-block-indent", QtBlockIndent },
|
{ "-qt-block-indent", QtBlockIndent },
|
||||||
{ "-qt-fg-texture-cachekey", QtForegroundTextureCacheKey },
|
{ "-qt-fg-texture-cachekey", QtForegroundTextureCacheKey },
|
||||||
@ -160,8 +180,9 @@ static const QCssKnownValue properties[NumProperties - 1] = {
|
|||||||
{ "width", Width },
|
{ "width", Width },
|
||||||
{ "word-spacing", WordSpacing }
|
{ "word-spacing", WordSpacing }
|
||||||
};
|
};
|
||||||
|
CHECK_ARRAY_IS_SORTED(properties, size_t(NumProperties) - 1)
|
||||||
|
|
||||||
static const QCssKnownValue values[NumKnownValues - 1] = {
|
static constexpr QCssKnownValue values[] = {
|
||||||
{ "accent", Value_Accent },
|
{ "accent", Value_Accent },
|
||||||
{ "active", Value_Active },
|
{ "active", Value_Active },
|
||||||
{ "alternate-base", Value_AlternateBase },
|
{ "alternate-base", Value_AlternateBase },
|
||||||
@ -248,6 +269,7 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
|
|||||||
{ "x-large", Value_XLarge },
|
{ "x-large", Value_XLarge },
|
||||||
{ "xx-large", Value_XXLarge }
|
{ "xx-large", Value_XXLarge }
|
||||||
};
|
};
|
||||||
|
CHECK_ARRAY_IS_SORTED(values, size_t(NumKnownValues) - 1)
|
||||||
|
|
||||||
//Map id to strings as they appears in the 'values' array above
|
//Map id to strings as they appears in the 'values' array above
|
||||||
static constexpr uchar indexOfId[] = {
|
static constexpr uchar indexOfId[] = {
|
||||||
@ -267,7 +289,7 @@ QString Value::toString() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const QCssKnownValue pseudos[NumPseudos - 1] = {
|
static constexpr QCssKnownValue pseudos[] = {
|
||||||
{ "active", PseudoClass_Active },
|
{ "active", PseudoClass_Active },
|
||||||
{ "adjoins-item", PseudoClass_Item },
|
{ "adjoins-item", PseudoClass_Item },
|
||||||
{ "alternate", PseudoClass_Alternate },
|
{ "alternate", PseudoClass_Alternate },
|
||||||
@ -313,44 +335,51 @@ static const QCssKnownValue pseudos[NumPseudos - 1] = {
|
|||||||
{ "vertical", PseudoClass_Vertical },
|
{ "vertical", PseudoClass_Vertical },
|
||||||
{ "window", PseudoClass_Window }
|
{ "window", PseudoClass_Window }
|
||||||
};
|
};
|
||||||
|
CHECK_ARRAY_IS_SORTED(pseudos, size_t(NumPseudos) - 1)
|
||||||
|
|
||||||
static const QCssKnownValue origins[NumKnownOrigins - 1] = {
|
static constexpr QCssKnownValue origins[] = {
|
||||||
{ "border", Origin_Border },
|
{ "border", Origin_Border },
|
||||||
{ "content", Origin_Content },
|
{ "content", Origin_Content },
|
||||||
{ "margin", Origin_Margin }, // not in css
|
{ "margin", Origin_Margin }, // not in css
|
||||||
{ "padding", Origin_Padding }
|
{ "padding", Origin_Padding }
|
||||||
};
|
};
|
||||||
|
CHECK_ARRAY_IS_SORTED(origins, size_t(NumKnownOrigins) - 1)
|
||||||
|
|
||||||
static const QCssKnownValue repeats[NumKnownRepeats - 1] = {
|
static constexpr QCssKnownValue repeats[] = {
|
||||||
{ "no-repeat", Repeat_None },
|
{ "no-repeat", Repeat_None },
|
||||||
{ "repeat-x", Repeat_X },
|
{ "repeat-x", Repeat_X },
|
||||||
{ "repeat-xy", Repeat_XY },
|
{ "repeat-xy", Repeat_XY },
|
||||||
{ "repeat-y", Repeat_Y }
|
{ "repeat-y", Repeat_Y }
|
||||||
};
|
};
|
||||||
|
CHECK_ARRAY_IS_SORTED(repeats, size_t(NumKnownRepeats) - 1)
|
||||||
|
|
||||||
static const QCssKnownValue tileModes[NumKnownTileModes - 1] = {
|
static constexpr QCssKnownValue tileModes[] = {
|
||||||
{ "repeat", TileMode_Repeat },
|
{ "repeat", TileMode_Repeat },
|
||||||
{ "round", TileMode_Round },
|
{ "round", TileMode_Round },
|
||||||
{ "stretch", TileMode_Stretch },
|
{ "stretch", TileMode_Stretch },
|
||||||
};
|
};
|
||||||
|
CHECK_ARRAY_IS_SORTED(tileModes, size_t(NumKnownTileModes) - 1)
|
||||||
|
|
||||||
static const QCssKnownValue positions[NumKnownPositionModes - 1] = {
|
static constexpr QCssKnownValue positions[] = {
|
||||||
{ "absolute", PositionMode_Absolute },
|
{ "absolute", PositionMode_Absolute },
|
||||||
{ "fixed", PositionMode_Fixed },
|
{ "fixed", PositionMode_Fixed },
|
||||||
{ "relative", PositionMode_Relative },
|
{ "relative", PositionMode_Relative },
|
||||||
{ "static", PositionMode_Static }
|
{ "static", PositionMode_Static }
|
||||||
};
|
};
|
||||||
|
CHECK_ARRAY_IS_SORTED(positions, size_t(NumKnownPositionModes) - 1)
|
||||||
|
|
||||||
static const QCssKnownValue attachments[NumKnownAttachments - 1] = {
|
static constexpr QCssKnownValue attachments[] = {
|
||||||
{ "fixed", Attachment_Fixed },
|
{ "fixed", Attachment_Fixed },
|
||||||
{ "scroll", Attachment_Scroll }
|
{ "scroll", Attachment_Scroll }
|
||||||
};
|
};
|
||||||
|
CHECK_ARRAY_IS_SORTED(attachments, size_t(NumKnownAttachments) - 1)
|
||||||
|
|
||||||
static const QCssKnownValue styleFeatures[NumKnownStyleFeatures - 1] = {
|
static constexpr QCssKnownValue styleFeatures[] = {
|
||||||
{ "background-color", StyleFeature_BackgroundColor },
|
{ "background-color", StyleFeature_BackgroundColor },
|
||||||
{ "background-gradient", StyleFeature_BackgroundGradient },
|
{ "background-gradient", StyleFeature_BackgroundGradient },
|
||||||
{ "none", StyleFeature_None }
|
{ "none", StyleFeature_None }
|
||||||
};
|
};
|
||||||
|
CHECK_ARRAY_IS_SORTED(styleFeatures, size_t(NumKnownStyleFeatures) - 1)
|
||||||
|
|
||||||
static bool operator<(const QString &name, const QCssKnownValue &prop)
|
static bool operator<(const QString &name, const QCssKnownValue &prop)
|
||||||
{
|
{
|
||||||
@ -362,6 +391,9 @@ static bool operator<(const QCssKnownValue &prop, const QString &name)
|
|||||||
return QString::compare(QLatin1StringView(prop.name), name, Qt::CaseInsensitive) < 0;
|
return QString::compare(QLatin1StringView(prop.name), name, Qt::CaseInsensitive) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef CHECK_ARRAY_IS_SORTED
|
||||||
|
#undef NOT_OLD_GCCs
|
||||||
|
|
||||||
static quint64 findKnownValue(const QString &name, const QCssKnownValue *start, int numValues)
|
static quint64 findKnownValue(const QString &name, const QCssKnownValue *start, int numValues)
|
||||||
{
|
{
|
||||||
const QCssKnownValue *end = start + (numValues - 1);
|
const QCssKnownValue *end = start + (numValues - 1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user