mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-01-22 20:51:23 -05:00
Keep valid surrogate pairs in stripInvalidXml10Chars().
This commit is contained in:
parent
00f068b93e
commit
8a92cec03f
@ -552,11 +552,19 @@ QString KeePass2XmlWriter::colorPartToString(int value)
|
|||||||
QString KeePass2XmlWriter::stripInvalidXml10Chars(QString str)
|
QString KeePass2XmlWriter::stripInvalidXml10Chars(QString str)
|
||||||
{
|
{
|
||||||
for (int i = str.size() - 1; i >= 0; i--) {
|
for (int i = str.size() - 1; i >= 0; i--) {
|
||||||
const ushort uc = str.at(i).unicode();
|
const QChar ch = str.at(i);
|
||||||
|
const ushort uc = ch.unicode();
|
||||||
|
|
||||||
if ((uc < 0x20 && uc != 0x09 && uc != 0x0A && uc != 0x0D)
|
if (ch.isLowSurrogate() && i != 0 && str.at(i - 1).isHighSurrogate()) {
|
||||||
|| (uc > 0xD7FF && uc < 0xE000)
|
// keep valid surrogate pair
|
||||||
|| (uc > 0xFFFD))
|
i--;
|
||||||
|
}
|
||||||
|
else if ((uc < 0x20 && uc != 0x09 && uc != 0x0A && uc != 0x0D) // control chracters
|
||||||
|
|| (uc >= 0x7F && uc <= 0x84) // control chracters, valid but discouraged by XML
|
||||||
|
|| (uc >= 0x86 && uc <= 0x9F) // control chracters, valid but discouraged by XML
|
||||||
|
|| (uc > 0xFFFD) // noncharacter
|
||||||
|
|| ch.isLowSurrogate() // single low surrogate
|
||||||
|
|| ch.isHighSurrogate()) // single high surrogate
|
||||||
{
|
{
|
||||||
qWarning("Stripping invalid XML 1.0 codepoint %x", uc);
|
qWarning("Stripping invalid XML 1.0 codepoint %x", uc);
|
||||||
str.remove(i, 1);
|
str.remove(i, 1);
|
||||||
|
@ -68,6 +68,18 @@ QDateTime TestKeePass2XmlReader::genDT(int year, int month, int day, int hour, i
|
|||||||
return QDateTime(date, time, Qt::UTC);
|
return QDateTime(date, time, Qt::UTC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray TestKeePass2XmlReader::strToBytes(const QString& str)
|
||||||
|
{
|
||||||
|
QByteArray result;
|
||||||
|
|
||||||
|
for (int i = 0; i < str.size(); i++) {
|
||||||
|
result.append(str.at(i).unicode() >> 8);
|
||||||
|
result.append(str.at(i).unicode() & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void TestKeePass2XmlReader::initTestCase()
|
void TestKeePass2XmlReader::initTestCase()
|
||||||
{
|
{
|
||||||
QVERIFY(Crypto::init());
|
QVERIFY(Crypto::init());
|
||||||
@ -414,10 +426,35 @@ void TestKeePass2XmlReader::testInvalidXmlChars()
|
|||||||
{
|
{
|
||||||
QScopedPointer<Database> dbWrite(new Database());
|
QScopedPointer<Database> dbWrite(new Database());
|
||||||
|
|
||||||
|
QString strPlainInvalid = QString().append(QChar(0x02)).append(QChar(0x19))
|
||||||
|
.append(QChar(0xFFFE)).append(QChar(0xFFFF));
|
||||||
|
QString strPlainValid = QString().append(QChar(0x09)).append(QChar(0x0A))
|
||||||
|
.append(QChar(0x20)).append(QChar(0xD7FF))
|
||||||
|
.append(QChar(0xE000)).append(QChar(0xFFFD));
|
||||||
|
// U+10437 in UTF-16: D801 DC37
|
||||||
|
// high low surrogate
|
||||||
|
QString strSingleHighSurrogate1 = QString().append(QChar(0xD801));
|
||||||
|
QString strSingleHighSurrogate2 = QString().append(QChar(0x31)).append(QChar(0xD801)).append(QChar(0x32));
|
||||||
|
QString strHighHighSurrogate = QString().append(QChar(0xD801)).append(QChar(0xD801));
|
||||||
|
QString strSingleLowSurrogate1 = QString().append(QChar(0xDC37));
|
||||||
|
QString strSingleLowSurrogate2 = QString().append(QChar((0x31))).append(QChar(0xDC37)).append(QChar(0x32));
|
||||||
|
QString strLowLowSurrogate = QString().append(QChar(0xDC37)).append(QChar(0xDC37));
|
||||||
|
QString strSurrogateValid1 = QString().append(QChar(0xD801)).append(QChar(0xDC37));
|
||||||
|
QString strSurrogateValid2 = QString().append(QChar(0x31)).append(QChar(0xD801)).append(QChar(0xDC37)).append(QChar(0x32));
|
||||||
|
|
||||||
Entry* entry = new Entry();
|
Entry* entry = new Entry();
|
||||||
entry->setUuid(Uuid::random());
|
entry->setUuid(Uuid::random());
|
||||||
entry->setNotes(QString("a %1 b %2 c %3").arg(QChar(0x02)).arg(QChar(0xD800)).arg(QChar(0xFFFE)));
|
|
||||||
entry->setGroup(dbWrite->rootGroup());
|
entry->setGroup(dbWrite->rootGroup());
|
||||||
|
entry->attributes()->set("PlainInvalid", strPlainInvalid);
|
||||||
|
entry->attributes()->set("PlainValid", strPlainValid);
|
||||||
|
entry->attributes()->set("SingleHighSurrogate1", strSingleHighSurrogate1);
|
||||||
|
entry->attributes()->set("SingleHighSurrogate2", strSingleHighSurrogate2);
|
||||||
|
entry->attributes()->set("HighHighSurrogate", strHighHighSurrogate);
|
||||||
|
entry->attributes()->set("SingleLowSurrogate1", strSingleLowSurrogate1);
|
||||||
|
entry->attributes()->set("SingleLowSurrogate2", strSingleLowSurrogate2);
|
||||||
|
entry->attributes()->set("LowLowSurrogate", strLowLowSurrogate);
|
||||||
|
entry->attributes()->set("SurrogateValid1", strSurrogateValid1);
|
||||||
|
entry->attributes()->set("SurrogateValid2", strSurrogateValid2);
|
||||||
|
|
||||||
QBuffer buffer;
|
QBuffer buffer;
|
||||||
buffer.open(QIODevice::ReadWrite);
|
buffer.open(QIODevice::ReadWrite);
|
||||||
@ -435,8 +472,19 @@ void TestKeePass2XmlReader::testInvalidXmlChars()
|
|||||||
QVERIFY(!reader.hasError());
|
QVERIFY(!reader.hasError());
|
||||||
QVERIFY(!dbRead.isNull());
|
QVERIFY(!dbRead.isNull());
|
||||||
QCOMPARE(dbRead->rootGroup()->entries().size(), 1);
|
QCOMPARE(dbRead->rootGroup()->entries().size(), 1);
|
||||||
// check that the invalid codepoints have been stripped
|
Entry* entryRead = dbRead->rootGroup()->entries().at(0);
|
||||||
QCOMPARE(dbRead->rootGroup()->entries().first()->notes(), QString("a b c "));
|
EntryAttributes* attrRead = entryRead->attributes();
|
||||||
|
|
||||||
|
QCOMPARE(strToBytes(attrRead->value("PlainInvalid")), QByteArray());
|
||||||
|
QCOMPARE(strToBytes(attrRead->value("PlainValid")), strToBytes(strPlainValid));
|
||||||
|
QCOMPARE(strToBytes(attrRead->value("SingleHighSurrogate1")), QByteArray());
|
||||||
|
QCOMPARE(strToBytes(attrRead->value("SingleHighSurrogate2")), strToBytes(QString("12")));
|
||||||
|
QCOMPARE(strToBytes(attrRead->value("HighHighSurrogate")), QByteArray());
|
||||||
|
QCOMPARE(strToBytes(attrRead->value("SingleLowSurrogate1")), QByteArray());
|
||||||
|
QCOMPARE(strToBytes(attrRead->value("SingleLowSurrogate2")), strToBytes(QString("12")));
|
||||||
|
QCOMPARE(strToBytes(attrRead->value("LowLowSurrogate")), QByteArray());
|
||||||
|
QCOMPARE(strToBytes(attrRead->value("SurrogateValid1")), strToBytes(strSurrogateValid1));
|
||||||
|
QCOMPARE(strToBytes(attrRead->value("SurrogateValid2")), strToBytes(strSurrogateValid2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestKeePass2XmlReader::cleanupTestCase()
|
void TestKeePass2XmlReader::cleanupTestCase()
|
||||||
|
@ -47,6 +47,7 @@ private Q_SLOTS:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static QDateTime genDT(int year, int month, int day, int hour, int min, int second);
|
static QDateTime genDT(int year, int month, int day, int hour, int min, int second);
|
||||||
|
static QByteArray strToBytes(const QString& str);
|
||||||
|
|
||||||
Database* m_db;
|
Database* m_db;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user