uic: Relax property name checks
Use an approximation of the "Unicode Standard Annex #31" for checking the property names and enumerations. Remove check for dynamic properties and use character literal formatting for them instead, which will escape offending characters. As a drive-by, use QStringView parameters for the check function. Amends 53c8d1fe7c59f3462b85193b688d02ff353b51d5. Task-number: QTBUG-126265 Task-number: QTBUG-126860 Pick-to: 6.7 6.5 6.2 5.15 Change-Id: I90fe555e64327e4164a17c1af0a734e4b1d834db Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io> (cherry picked from commit aae20da52a11e0ebb8c4f5fcfb95ce6744f659a3) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
bc28d6d48c
commit
0925c2d80a
@ -125,35 +125,65 @@ namespace {
|
|||||||
return iconHasStatePixmaps(i) || !i->attributeTheme().isEmpty();
|
return iconHasStatePixmaps(i) || !i->attributeTheme().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks on property names
|
// An approximation of "Unicode Standard Annex #31" for checking property
|
||||||
bool isIdentifier(QChar c) { return c.isLetterOrNumber() || c == u'_'; }
|
// and enumeration identifiers to prevent code injection attacks.
|
||||||
|
// FIXME 6.9: Simplify according to QTBUG-126860
|
||||||
bool checkPropertyName(const QString &name)
|
static bool isIdStart(QChar c)
|
||||||
{
|
{
|
||||||
return !name.isEmpty() && name.at(0).isLetter()
|
bool result = false;
|
||||||
&& std::all_of(name.cbegin(), name.cend(), isIdentifier);
|
switch (c.category()) {
|
||||||
|
case QChar::Letter_Uppercase:
|
||||||
|
case QChar::Letter_Lowercase:
|
||||||
|
case QChar::Letter_Titlecase:
|
||||||
|
case QChar::Letter_Modifier:
|
||||||
|
case QChar::Letter_Other:
|
||||||
|
case QChar::Number_Letter:
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = c == u'_';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Basic checks on enum/flag values
|
static bool isIdContinuation(QChar c)
|
||||||
static bool isValidEnumValue(QChar c)
|
|
||||||
{
|
{
|
||||||
if (c.isLetterOrNumber())
|
bool result = false;
|
||||||
return true;
|
switch (c.category()) {
|
||||||
switch (c.unicode()) {
|
case QChar::Letter_Uppercase:
|
||||||
case '|':
|
case QChar::Letter_Lowercase:
|
||||||
case ' ':
|
case QChar::Letter_Titlecase:
|
||||||
case ':':
|
case QChar::Letter_Modifier:
|
||||||
case '_':
|
case QChar::Letter_Other:
|
||||||
return true;
|
case QChar::Number_Letter:
|
||||||
|
case QChar::Mark_NonSpacing:
|
||||||
|
case QChar::Mark_SpacingCombining:
|
||||||
|
case QChar::Number_DecimalDigit:
|
||||||
|
case QChar::Punctuation_Connector: // '_'
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkEnumValue(const QString &value)
|
static bool isEnumIdContinuation(QChar c)
|
||||||
{
|
{
|
||||||
return std::all_of(value.cbegin(), value.cend(), isValidEnumValue);
|
return c == u':' || c == u'|' || c == u' ' || isIdContinuation(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkPropertyName(QStringView name)
|
||||||
|
{
|
||||||
|
return !name.isEmpty() && isIdStart(name.at(0))
|
||||||
|
&& std::all_of(name.cbegin() + 1, name.cend(), isIdContinuation);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkEnumValue(QStringView name)
|
||||||
|
{
|
||||||
|
return !name.isEmpty() && isIdStart(name.at(0))
|
||||||
|
&& std::all_of(name.cbegin() + 1, name.cend(), isEnumIdContinuation);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString msgInvalidValue(const QString &name, const QString &value)
|
QString msgInvalidValue(const QString &name, const QString &value)
|
||||||
@ -169,7 +199,8 @@ namespace {
|
|||||||
const DomProperty *p) {
|
const DomProperty *p) {
|
||||||
|
|
||||||
const QString &name = p->attributeName();
|
const QString &name = p->attributeName();
|
||||||
if (!checkPropertyName(name)) {
|
const bool isDynamicProperty = p->hasAttributeStdset() && p->attributeStdset() == 0;
|
||||||
|
if (!isDynamicProperty && !checkPropertyName(name)) {
|
||||||
qWarning("uic: Invalid property name: \"%s\".", qPrintable(name));
|
qWarning("uic: Invalid property name: \"%s\".", qPrintable(name));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1403,8 +1434,8 @@ void WriteInitialization::writeProperties(const QString &varName,
|
|||||||
str << language::derefPointer <<"set" << propertyName.at(0).toUpper()
|
str << language::derefPointer <<"set" << propertyName.at(0).toUpper()
|
||||||
<< QStringView{propertyName}.mid(1) << '(';
|
<< QStringView{propertyName}.mid(1) << '(';
|
||||||
} else {
|
} else {
|
||||||
str << language::derefPointer << "setProperty(\""_L1
|
str << language::derefPointer << "setProperty("_L1
|
||||||
<< propertyName << "\", ";
|
<< language::charliteral(propertyName) << ", ";
|
||||||
if (language::language() == Language::Cpp) {
|
if (language::language() == Language::Cpp) {
|
||||||
str << "QVariant";
|
str << "QVariant";
|
||||||
if (p->kind() == DomProperty::Enum)
|
if (p->kind() == DomProperty::Enum)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user