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
wilder
Jos van den Oever 7 years ago
parent e4b002e7ae
commit 6a185285ae
  1. 29
      autotests/kconfigtest.cpp
  2. 1
      autotests/kconfigtest.h
  3. 2
      src/core/kconfigini.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

@ -63,6 +63,7 @@ private Q_SLOTS:
void testConfigCopyToSync();
void testReparent();
void testAnonymousConfig();
void testQByteArrayUtf8();
void testSubGroup();
void testAddConfigSources();

@ -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];

Loading…
Cancel
Save