From 7c4e1357e49baebdd2d20710fccb5604cbb36c0d Mon Sep 17 00:00:00 2001
From: Fabian Kosmale <fabian.kosmale@qt.io>
Date: Thu, 18 Apr 2024 10:25:21 +0200
Subject: [PATCH] QStringConverterICU: Pass correct pointer to callback
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Pass the pointer to the current state, not a pointer to a pointer to it.

[ChangeLog][QtCore][QStringConverter] Fixed a bug involving moved
QStringEncoder/QStringDecoder objects accessing invalid state.

Amends 122270d6bea164e6df4357f4d4d77aacfa430470.

Done-with: Marc Mutz <marc.mutz@qt.io>
Pick-to: 6.5
Change-Id: I70d4dc00e3e0db6cad964579662bcf6d185a4c34
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
(cherry picked from commit 39bbfce9b675c9085ef49c9b9c52c146eca55e4a)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
---
 src/corelib/text/qstringconverter.cpp         |  4 +-
 .../qstringconverter/tst_qstringconverter.cpp | 72 +++++++++++--------
 2 files changed, 44 insertions(+), 32 deletions(-)

diff --git a/src/corelib/text/qstringconverter.cpp b/src/corelib/text/qstringconverter.cpp
index b57498439174..fd45ccf2fdd9 100644
--- a/src/corelib/text/qstringconverter.cpp
+++ b/src/corelib/text/qstringconverter.cpp
@@ -1954,7 +1954,7 @@ struct QStringConverterICU : QStringConverter
         const void *context;
         ucnv_getToUCallBack(icu_conv, &action, &context);
         if (context != state)
-             ucnv_setToUCallBack(icu_conv, action, &state, nullptr, nullptr, &err);
+             ucnv_setToUCallBack(icu_conv, action, state, nullptr, nullptr, &err);
 
         ucnv_toUnicode(icu_conv, &target, targetLimit, &source, sourceLimit, nullptr, flush, &err);
         // We did reserve enough space:
@@ -1987,7 +1987,7 @@ struct QStringConverterICU : QStringConverter
         const void *context;
         ucnv_getFromUCallBack(icu_conv, &action, &context);
         if (context != state)
-             ucnv_setFromUCallBack(icu_conv, action, &state, nullptr, nullptr, &err);
+             ucnv_setFromUCallBack(icu_conv, action, state, nullptr, nullptr, &err);
 
         ucnv_fromUnicode(icu_conv, &target, targetLimit, &source, sourceLimit, nullptr, flush, &err);
         // We did reserve enough space:
diff --git a/tests/auto/corelib/text/qstringconverter/tst_qstringconverter.cpp b/tests/auto/corelib/text/qstringconverter/tst_qstringconverter.cpp
index d5fff83321a0..cd4bd8d1b69b 100644
--- a/tests/auto/corelib/text/qstringconverter/tst_qstringconverter.cpp
+++ b/tests/auto/corelib/text/qstringconverter/tst_qstringconverter.cpp
@@ -571,11 +571,10 @@ void tst_QStringConverter::charByCharConsistency_data()
 
 void tst_QStringConverter::charByCharConsistency()
 {
-    QFETCH(QStringView, source);
-    QFETCH(QByteArray, codec);
+    QFETCH(const QStringView, source);
+    QFETCH(const QByteArray, codec);
 
-    {
-        QStringEncoder encoder(codec);
+    const auto check = [&](QStringEncoder encoder){
         if (!encoder.isValid())
             QSKIP("Unsupported codec");
 
@@ -586,19 +585,28 @@ void tst_QStringConverter::charByCharConsistency()
             stepByStepConverted += encoder.encode(codeUnit);
         }
         QCOMPARE(stepByStepConverted, fullyConverted);
-    }
+    };
+
+    check(QStringEncoder(codec));
+    if (QTest::currentTestResolved()) return;
+
+    check(QStringEncoder(codec, QStringConverter::Flag::ConvertInvalidToNull));
+    if (QTest::currentTestResolved()) return;
+
+    // moved codecs also work:
 
     {
-        QStringEncoder encoder(codec, QStringConverter::Flag::ConvertInvalidToNull);
+        QStringEncoder dec(codec);
+        check(std::move(dec));
+    }
+    if (QTest::currentTestResolved()) return;
 
-        QByteArray fullyConverted = encoder.encode(source);
-        encoder.resetState();
-        QByteArray stepByStepConverted;
-        for (const auto& codeUnit: source) {
-            stepByStepConverted += encoder.encode(codeUnit);
-        }
-        QCOMPARE(stepByStepConverted, fullyConverted);
+    {
+        QStringEncoder dec(codec, QStringConverter::Flag::ConvertInvalidToNull);
+        check(std::move(dec));
     }
+    if (QTest::currentTestResolved()) return;
+
 }
 
 void tst_QStringConverter::byteByByteConsistency_data()
@@ -615,11 +623,10 @@ void tst_QStringConverter::byteByByteConsistency_data()
 
 void tst_QStringConverter::byteByByteConsistency()
 {
-    QFETCH(QByteArray, source);
-    QFETCH(QByteArray, codec);
+    QFETCH(const QByteArray, source);
+    QFETCH(const QByteArray, codec);
 
-    {
-        QStringDecoder decoder(codec);
+    const auto check = [&](QStringDecoder decoder) {
         if (!decoder.isValid())
             QSKIP("Unsupported codec");
 
@@ -632,23 +639,28 @@ void tst_QStringConverter::byteByByteConsistency()
             stepByStepConverted += decoder.decode(singleChar);
         }
         QCOMPARE(stepByStepConverted, fullyConverted);
-    }
+    };
+
+    check(QStringDecoder(codec));
+    if (QTest::currentTestResolved()) return;
+
+    check(QStringDecoder(codec, QStringConverter::Flag::ConvertInvalidToNull));
+    if (QTest::currentTestResolved()) return;
+
+    // moved codecs also work:
 
     {
-        QStringDecoder decoder(codec, QStringConverter::Flag::ConvertInvalidToNull);
-        if (!decoder.isValid())
-            QSKIP("Unsupported codec");
+        QStringDecoder dec(codec);
+        check(std::move(dec));
+    }
+    if (QTest::currentTestResolved()) return;
 
-        QString fullyConverted = decoder.decode(source);
-        decoder.resetState();
-        QString stepByStepConverted;
-        for (const auto& byte: source) {
-            QByteArray singleChar;
-            singleChar.append(byte);
-            stepByStepConverted += decoder.decode(singleChar);
-        }
-        QCOMPARE(stepByStepConverted, fullyConverted);
+    {
+        QStringDecoder dec(codec, QStringConverter::Flag::ConvertInvalidToNull);
+        check(std::move(dec));
     }
+    if (QTest::currentTestResolved()) return;
+
 }
 
 void tst_QStringConverter::statefulPieceWise()
