Files
plasma-next/packages/qt5compat/debian/patches/04-CVE-2026-107590-qt5compat-6.11.patch

105 lines
4.0 KiB
Diff

From 81cbf0a59c311ec17cae4d2e4d40bd93635f6d8f Mon Sep 17 00:00:00 2001
From: Ivan Solovev <ivan.solovev@qt.io>
Date: Fri, 21 Aug 2026 16:15:15 +0200
Subject: [PATCH] QTextCodec: fix OOB write in ICONV codec
The ICONV codec has a size miscalculation error when encoding continues
with a high surrogate kept in the state after encoding of the previous
chunk. The code was requesting a resize based on the length in UTF-16
code points instead of the length in bytes.
As a result, we were requesting half of the bytes that we actually
needed.
Note that since resize() allocates more than requested, the code could
sometimes execute successfully.
The test specifically adds a large tail to the input, so that memcpy()
clearly triggers an out-of-bounds write. The test was triggering ASAN
before the fix.
Disclaimer: the tests were developed with the help of AI.
Fixes: QTBUG-149214
Pick-to: 6.8 6.5 5.15
Change-Id: I8d32b737630efc092d3f99eb45982f30106e29d3
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
(cherry picked from commit cf3f5fbc8bae37cd358b8157cff11b329cca02aa)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 724025a7c05596961cc870ef703a2f2b14e55c88)
---
diff --git a/src/core5/codecs/qiconvcodec.cpp b/src/core5/codecs/qiconvcodec.cpp
index 2bfba5a..496a225 100644
--- a/src/core5/codecs/qiconvcodec.cpp
+++ b/src/core5/codecs/qiconvcodec.cpp
@@ -296,7 +296,7 @@
QByteArray in;
if (convState && convState->remainingChars) {
// we have one surrogate char to be prepended
- in.resize(sizeof(QChar) + len);
+ in.resize(sizeof(QChar) + inBytesLeft);
inBytes = in.data();
QChar remaining(convState->state_data[0]);
diff --git a/tests/auto/core5/codecs/qtextcodec/tst_qtextcodec.cpp b/tests/auto/core5/codecs/qtextcodec/tst_qtextcodec.cpp
index dcb5390..f2913f4 100644
--- a/tests/auto/core5/codecs/qtextcodec/tst_qtextcodec.cpp
+++ b/tests/auto/core5/codecs/qtextcodec/tst_qtextcodec.cpp
@@ -95,6 +95,8 @@
void tsciiEncoderDoesNotReadPastTheEnd_data();
void tsciiEncoderDoesNotReadPastTheEnd();
+
+ void iconvEncoderPendingSurrogateDoesNotOverflow();
};
void tst_QTextCodec::toUnicode_data()
@@ -2888,6 +2890,47 @@
QCOMPARE(stateless, expected);
}
+/*
+ This test catches a size miscalculation error in the Iconv codec
+ in the case when encoding continues with a high surrogate kept
+ in the state from the encoding of the previous chunk.
+*/
+void tst_QTextCodec::iconvEncoderPendingSurrogateDoesNotOverflow()
+{
+ constexpr char32_t Ucs4NonBmp = 0x10437; // DESERET SMALL LETTER YEE
+ // Before the fix such tail was leading to allocating 4096 bytes,
+ // while the full buffer required 4086 _QChars_ (so, almost twice more)
+ constexpr int IconvTailLength = 4064;
+
+ // QIconvCodec registers itself as "System", but it's only available
+ // when the configuration disables ICU and explicitly enables iconv.
+ QTextCodec *codec = QTextCodec::codecForName("System");
+ if (!codec)
+ QSKIP("QIconvCodec was not found (disable ICU and enable iconv explicitly)");
+
+ QString start(10, u'x');
+ start += QChar::highSurrogate(Ucs4NonBmp);
+
+ QString rest;
+ rest += QChar::lowSurrogate(Ucs4NonBmp);
+ rest += QString(IconvTailLength, u'x');
+
+ const QByteArray expected = codec->fromUnicode(start + rest);
+
+ // Encode the first block that ends with the high surrogate.
+ // It should be stored in the converter state.
+ QTextCodec::ConverterState state;
+ QByteArray continued = codec->fromUnicode(start.constData(), int(start.size()), &state);
+
+ // Encode the second block.
+ // Before the fix, this would cause an overrun in the QByteArray
+ // buffer. Detection left for an ASan or Valgrind-checked build.
+ continued += codec->fromUnicode(rest.constData(), int(rest.size()), &state);
+
+ QCOMPARE(continued, expected);
+ QCOMPARE(state.remainingChars, qsizetype(0));
+}
+
QT_END_NAMESPACE
QTEST_MAIN(tst_QTextCodec)