qt: Avoid race on QtTransferable member

As Michael Stahl pointed out in [1], there is a data
race on `QtTransferable::m_bProvideUTF16FromOtherEncoding`.

Adjust the code a bit to no longer make use of the
member and drop it.

The QtClipboard case was fine because both methods making
use of the member always run in the main thread with the
SolarMutex held.

For anything else, the `m_pMimeData` doesn't change
don't change, so access to that member doesn't need
to be guarded by a mutex and thus dropping
`QtTransferable::m_bProvideUTF16FromOtherEncoding`
should be sufficient to address that race at least.
(Another one will be addressed separately.)

[1] https://gerrit.libreoffice.org/c/core/+/166140/comment/bc1c9f11_6ad630b7

Change-Id: Iaf2fb460b129493f5627c95b6968aa57da368b4c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166749
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Tested-by: Jenkins
This commit is contained in:
Michael Weghorn 2024-04-26 14:39:14 +02:00
parent ea93670372
commit 8939999dee
2 changed files with 17 additions and 19 deletions

View file

@ -34,7 +34,6 @@ class QtTransferable : public cppu::WeakImplHelper<css::datatransfer::XTransfera
QtTransferable(const QtTransferable&) = delete;
const QMimeData* m_pMimeData;
bool m_bProvideUTF16FromOtherEncoding;
protected:
/** Sets new mime data.

View file

@ -43,7 +43,6 @@ static bool lcl_textMimeInfo(std::u16string_view rMimeString, bool& bHaveNoChars
QtTransferable::QtTransferable(const QMimeData* pMimeData)
: m_pMimeData(pMimeData)
, m_bProvideUTF16FromOtherEncoding(false)
{
assert(pMimeData);
}
@ -94,8 +93,10 @@ css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL QtTransferable::getTr
nMimeTypeCount++;
}
m_bProvideUTF16FromOtherEncoding = (bHaveNoCharset || bHaveUTF8) && !bHaveUTF16;
if (m_bProvideUTF16FromOtherEncoding)
// in case of text/plain data, but no UTF-16 encoded one,
// QtTransferable::getTransferData converts from existing encoding to UTF-16
const bool bProvideUTF16FromOtherEncoding = (bHaveNoCharset || bHaveUTF8) && !bHaveUTF16;
if (bProvideUTF16FromOtherEncoding)
{
aFlavor.MimeType = "text/plain;charset=utf-16";
aFlavor.DataType = cppu::UnoType<OUString>::get();
@ -127,26 +128,24 @@ css::uno::Any SAL_CALL QtTransferable::getTransferData(const css::datatransfer::
if (rFlavor.MimeType == "text/plain;charset=utf-16")
{
OUString aString;
if (m_bProvideUTF16FromOtherEncoding)
{
if (m_pMimeData->hasFormat("text/plain;charset=utf-8"))
{
QByteArray aByteData(m_pMimeData->data(QStringLiteral("text/plain;charset=utf-8")));
aString = OUString::fromUtf8(reinterpret_cast<const char*>(aByteData.data()));
}
else
{
QByteArray aByteData(m_pMimeData->data(QStringLiteral("text/plain")));
aString = OUString(reinterpret_cast<const char*>(aByteData.data()),
aByteData.size(), osl_getThreadTextEncoding());
}
}
else
// use existing UTF-16 encoded text/plain or convert to UTF-16 as needed
if (m_pMimeData->hasFormat("text/plain;charset=utf-16"))
{
QByteArray aByteData(m_pMimeData->data(toQString(rFlavor.MimeType)));
aString = OUString(reinterpret_cast<const sal_Unicode*>(aByteData.data()),
aByteData.size() / 2);
}
else if (m_pMimeData->hasFormat("text/plain;charset=utf-8"))
{
QByteArray aByteData(m_pMimeData->data(QStringLiteral("text/plain;charset=utf-8")));
aString = OUString::fromUtf8(reinterpret_cast<const char*>(aByteData.data()));
}
else
{
QByteArray aByteData(m_pMimeData->data(QStringLiteral("text/plain")));
aString = OUString(reinterpret_cast<const char*>(aByteData.data()), aByteData.size(),
osl_getThreadTextEncoding());
}
aAny <<= aString;
}
else