Fix data corruption when reading byte arrays from QSettings

On macOS, the code that read the plist is using
QByteArray::fromRawCFData. When we return the data directly
we need to detach the QByteArray so that it does not point
CFData's data that will get deallocated just after the call.

Task-number: QTBUG-58531
Change-Id: If829a304b986c99c8fc2aeeb992f2d539a4eef3a
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
bb10
Thierry Bastian 2017-01-30 19:02:23 +01:00
parent c7762f1178
commit b8dbde10a0
4 changed files with 25 additions and 1 deletions

View File

@ -269,8 +269,10 @@ static QVariant qtValue(CFPropertyListRef cfvalue)
// Fast-path for QByteArray, so that we don't have to go
// though the expensive and lossy conversion via UTF-8.
if (!byteArray.startsWith('@'))
if (!byteArray.startsWith('@')) {
byteArray.detach();
return byteArray;
}
const QString str = QString::fromUtf8(byteArray.constData(), byteArray.size());
return QSettingsPrivate::stringToVariant(str);

View File

@ -5,6 +5,7 @@
<file>resourcefile3.ini</file>
<file>resourcefile4.ini</file>
<file>resourcefile5.ini</file>
<file>resourcefile6.plist</file>
<file>bom.ini</file>
</qresource>
</RCC>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>passwordData</key>
<data>
RBxVAAsDVsO/
</data>
</dict>
</plist>

View File

@ -178,6 +178,7 @@ private slots:
void testByteArray_data();
void testByteArray();
void testByteArrayNativeFormat();
void iniCodec();
void bom();
void embeddedZeroByte_data();
@ -670,6 +671,16 @@ void tst_QSettings::testByteArray()
}
}
void tst_QSettings::testByteArrayNativeFormat()
{
#ifndef Q_OS_MACOS
QSKIP("This test is specific to macOS plist reading.");
#else
QSettings settings(":/resourcefile6.plist", QSettings::NativeFormat);
QCOMPARE(settings.value("passwordData"), QVariant(QByteArray::fromBase64("RBxVAAsDVsO/")));
#endif
}
void tst_QSettings::iniCodec()
{
{