diff options
author | Jos van den Oever <jos@vandenoever.info> | 2018-12-18 13:55:56 +0100 |
---|---|---|
committer | Jos van den Oever <jos@vandenoever.info> | 2018-12-18 20:56:55 +0100 |
commit | 6a185285ae44ed182dbab9206b9092f78c7d3714 (patch) | |
tree | f85cb3e9f003d4383a938b9f7a342f91fa10508c | |
parent | e4b002e7ae07272cd63921d65ec299c66f5c36ab (diff) | |
download | kconfig-6a185285ae44ed182dbab9206b9092f78c7d3714.tar.gz kconfig-6a185285ae44ed182dbab9206b9092f78c7d3714.tar.bz2 |
Escape bytes that are larger than or equal to 127 in config files
Summary:
UserBase tells me that KDE configuration files are encoded in UTF-8.
https://userbase.kde.org/KDE_System_Administration/Configuration_Files
In practice some *rc files have bytes outside that encoding. In my home directory I found two files that are not valid UTF-8.
I searched with
find ~/.config/ -name '*rc' -exec file {} +
which gives these exceptions:
akonadiconsolerc: Non-ISO extended-ASCII text, with very long lines
kmail2rc: Non-ISO extended-ASCII text, with very long lines
In kmail2rc, the offending fields are
[AttachmentView]/State
[CollectionFolderView]/HeaderState
Both are QByteArray values saved from QHeaderView::saveState().
In the instance I found, the offending bytes were 0x81 and 0x84.
akonadiconsolerc had way more of these values. All seem related to saving widget state and hence probably QByteArrays.
The written QByteArray values look very strange. The bytes in the non-printable ASCII range are written as \xXX but the values above 127 are written literally.
The encoding is done by KConfigIniBackend::stringToPrintable. It does not currently escape bytes that are larger than or equal to 127.
Reviewers: dfaure, arichardson, apol
Reviewed By: apol
Subscribers: apol, kde-frameworks-devel
Tags: #frameworks
Differential Revision: https://phabricator.kde.org/D17651
-rw-r--r-- | autotests/kconfigtest.cpp | 29 | ||||
-rw-r--r-- | autotests/kconfigtest.h | 1 | ||||
-rw-r--r-- | src/core/kconfigini.cpp | 2 |
3 files changed, 31 insertions, 1 deletions
diff --git a/autotests/kconfigtest.cpp b/autotests/kconfigtest.cpp index 45fe8e53..a60ea57a 100644 --- a/autotests/kconfigtest.cpp +++ b/autotests/kconfigtest.cpp @@ -1719,6 +1719,35 @@ void KConfigTest::testAnonymousConfig() QCOMPARE(general.readEntry("Foo"), QString("Bar")); } +void KConfigTest::testQByteArrayUtf8() +{ + QTemporaryFile file; + QVERIFY(file.open()); + qWarning() << file.fileName(); + KConfig config(file.fileName(), KConfig::SimpleConfig); + KConfigGroup general(&config, "General"); + QByteArray bytes(256, '\0'); + for (int i = 0; i < 256; i++) { + bytes[i] = i; + } + general.writeEntry("Utf8", bytes); + config.sync(); + file.flush(); + file.close(); + QFile readFile(file.fileName()); + QVERIFY(readFile.open(QFile::ReadOnly)); +#ifndef Q_OS_WIN + QCOMPARE(readFile.readAll(), QByteArrayLiteral("[General]\nUtf8=\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\\x7f\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87\\x88\\x89\\x8a\\x8b\\x8c\\x8d\\x8e\\x8f\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\\x98\\x99\\x9a\\x9b\\x9c\\x9d\\x9e\\x9f\\xa0\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6\\xa7\\xa8\\xa9\\xaa\\xab\\xac\\xad\\xae\\xaf\\xb0\\xb1\\xb2\\xb3\\xb4\\xb5\\xb6\\xb7\\xb8\\xb9\\xba\\xbb\\xbc\\xbd\\xbe\\xbf\\xc0\\xc1\\xc2\\xc3\\xc4\\xc5\\xc6\\xc7\\xc8\\xc9\\xca\\xcb\\xcc\\xcd\\xce\\xcf\\xd0\\xd1\\xd2\\xd3\\xd4\\xd5\\xd6\\xd7\\xd8\\xd9\\xda\\xdb\\xdc\\xdd\\xde\\xdf\\xe0\\xe1\\xe2\\xe3\\xe4\\xe5\\xe6\\xe7\\xe8\\xe9\\xea\\xeb\\xec\\xed\\xee\\xef\\xf0\\xf1\\xf2\\xf3\\xf4\\xf5\\xf6\\xf7\\xf8\\xf9\\xfa\\xfb\\xfc\\xfd\\xfe\\xff\n")); +#else + QCOMPARE(readFile.readAll(), QByteArrayLiteral("[General]\r\nUtf8=\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\\x7f\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87\\x88\\x89\\x8a\\x8b\\x8c\\x8d\\x8e\\x8f\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\\x98\\x99\\x9a\\x9b\\x9c\\x9d\\x9e\\x9f\\xa0\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6\\xa7\\xa8\\xa9\\xaa\\xab\\xac\\xad\\xae\\xaf\\xb0\\xb1\\xb2\\xb3\\xb4\\xb5\\xb6\\xb7\\xb8\\xb9\\xba\\xbb\\xbc\\xbd\\xbe\\xbf\\xc0\\xc1\\xc2\\xc3\\xc4\\xc5\\xc6\\xc7\\xc8\\xc9\\xca\\xcb\\xcc\\xcd\\xce\\xcf\\xd0\\xd1\\xd2\\xd3\\xd4\\xd5\\xd6\\xd7\\xd8\\xd9\\xda\\xdb\\xdc\\xdd\\xde\\xdf\\xe0\\xe1\\xe2\\xe3\\xe4\\xe5\\xe6\\xe7\\xe8\\xe9\\xea\\xeb\\xec\\xed\\xee\\xef\\xf0\\xf1\\xf2\\xf3\\xf4\\xf5\\xf6\\xf7\\xf8\\xf9\\xfa\\xfb\\xfc\\xfd\\xfe\\xff\r\n")); +#endif + + // check that reading works + KConfig config2(file.fileName(), KConfig::SimpleConfig); + KConfigGroup general2(&config2, "General"); + QCOMPARE(bytes, general2.readEntry("Utf8", QByteArray())); +} + void KConfigTest::testNewlines() { // test that kconfig always uses the native line endings diff --git a/autotests/kconfigtest.h b/autotests/kconfigtest.h index 708da042..0715f45e 100644 --- a/autotests/kconfigtest.h +++ b/autotests/kconfigtest.h @@ -63,6 +63,7 @@ private Q_SLOTS: void testConfigCopyToSync(); void testReparent(); void testAnonymousConfig(); + void testQByteArrayUtf8(); void testSubGroup(); void testAddConfigSources(); diff --git a/src/core/kconfigini.cpp b/src/core/kconfigini.cpp index c7b36efd..39e59364 100644 --- a/src/core/kconfigini.cpp +++ b/src/core/kconfigini.cpp @@ -673,7 +673,7 @@ QByteArray KConfigIniBackend::stringToPrintable(const QByteArray &aString, Strin switch (s[i]) { default: // The \n, \t, \r cases (all < 32) are handled below; we can ignore them here - if (((unsigned char)s[i]) < 32) { + if (((unsigned char)s[i]) < 32 || ((unsigned char)s[i]) >= 127) { goto doEscape; } *data++ = s[i]; |