vcl/inc/qt5/QtTransferable.hxx |    1 -
 vcl/qt5/QtTransferable.cxx     |   35 +++++++++++++++++------------------
 2 files changed, 17 insertions(+), 19 deletions(-)

New commits:
commit 28b2020f276f12561252ea3a42555bfe88a0c1b6
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Fri Apr 26 14:39:14 2024 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Tue Apr 30 11:06:26 2024 +0200

    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.st...@allotropia.de>
    Tested-by: Jenkins
    (cherry picked from commit 8939999deef4f77f19d7b2d31df09260a34affe1)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166891

diff --git a/vcl/inc/qt5/QtTransferable.hxx b/vcl/inc/qt5/QtTransferable.hxx
index 38cb4d92005b..c58490e90460 100644
--- a/vcl/inc/qt5/QtTransferable.hxx
+++ b/vcl/inc/qt5/QtTransferable.hxx
@@ -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.
diff --git a/vcl/qt5/QtTransferable.cxx b/vcl/qt5/QtTransferable.cxx
index 18c2583e2e63..a6902824ab3a 100644
--- a/vcl/qt5/QtTransferable.cxx
+++ b/vcl/qt5/QtTransferable.cxx
@@ -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

Reply via email to