diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2022-05-25 09:07:37 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2022-05-25 16:38:35 +0200 |
commit | c46ee7df57c30c94107df8506d30d8872ffa3baa (patch) | |
tree | 74e2f1c109210ec38f634699ce879bf081a2cd02 | |
parent | d83441340c210056d25777ed59ec6dab6351a55f (diff) |
QStringConverter: Do not crash if invalid
Attempting to use an invalid QStringConverter would so far have resulted
in a crash, as we would dereference the null iface pointer.
Fix this by inserting adequate checks, and ensure that hasError returns
true if we attempt to en/decode with an invalid converter.
Pick-to: 6.2 6.3
Change-Id: Icf74bb88cd8c95685481cc0bd512da99b62f33e6
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r-- | src/corelib/text/qstringconverter.h | 30 | ||||
-rw-r--r-- | tests/auto/corelib/text/qstringconverter/tst_qstringconverter.cpp | 56 |
2 files changed, 82 insertions, 4 deletions
diff --git a/src/corelib/text/qstringconverter.h b/src/corelib/text/qstringconverter.h index 213de9fe55..c1645f0938 100644 --- a/src/corelib/text/qstringconverter.h +++ b/src/corelib/text/qstringconverter.h @@ -62,12 +62,23 @@ public: #endif qsizetype requiredSpace(qsizetype inputLength) const - { return iface->fromUtf16Len(inputLength); } + { return iface ? iface->fromUtf16Len(inputLength) : 0; } char *appendToBuffer(char *out, QStringView in) - { return iface->fromUtf16(out, in, &state); } + { + if (!iface) { + state.invalidChars = 1; + return out; + } + return iface->fromUtf16(out, in, &state); + } private: QByteArray encodeAsByteArray(QStringView in) { + if (!iface) { + // ensure that hasError returns true + state.invalidChars = 1; + return {}; + } QByteArray result(iface->fromUtf16Len(in.size()), Qt::Uninitialized); char *out = result.data(); out = iface->fromUtf16(out, in, &state); @@ -120,12 +131,23 @@ public: #endif qsizetype requiredSpace(qsizetype inputLength) const - { return iface->toUtf16Len(inputLength); } + { return iface ? iface->toUtf16Len(inputLength) : 0; } QChar *appendToBuffer(QChar *out, QByteArrayView ba) - { return iface->toUtf16(out, ba, &state); } + { + if (!iface) { + state.invalidChars = 1; + return out; + } + return iface->toUtf16(out, ba, &state); + } private: QString decodeAsString(QByteArrayView in) { + if (!iface) { + // ensure that hasError returns true + state.invalidChars = 1; + return {}; + } QString result(iface->toUtf16Len(in.size()), Qt::Uninitialized); const QChar *out = iface->toUtf16(result.data(), in, &state); result.truncate(out - result.constData()); diff --git a/tests/auto/corelib/text/qstringconverter/tst_qstringconverter.cpp b/tests/auto/corelib/text/qstringconverter/tst_qstringconverter.cpp index 6fe20b1453..231df0390e 100644 --- a/tests/auto/corelib/text/qstringconverter/tst_qstringconverter.cpp +++ b/tests/auto/corelib/text/qstringconverter/tst_qstringconverter.cpp @@ -120,6 +120,8 @@ private slots: void constructByName(); + void invalidConverter(); + void convertUtf8_data(); void convertUtf8(); void convertUtf8CharByChar_data() { convertUtf8_data(); } @@ -181,6 +183,60 @@ void tst_QStringConverter::constructByName() QVERIFY(!strcmp(decoder.name(), "UTF-16")); } +void tst_QStringConverter::invalidConverter() +{ + // QStringEncoder tests + { + QStringEncoder encoder; + QVERIFY(!encoder.isValid()); + QVERIFY(!encoder.name()); + QByteArray encoded = encoder(u"Some text"); + QVERIFY(encoded.isEmpty()); + QVERIFY(encoder.hasError()); + + encoder.resetState(); + QVERIFY(!encoder.hasError()); + + encoded = encoder.encode(u"More text"); + QVERIFY(encoded.isEmpty()); + QVERIFY(encoder.hasError()); + QCOMPARE(encoder.requiredSpace(42), 0); + + encoder.resetState(); + QVERIFY(!encoder.hasError()); + char buffer[100]; + char *position = encoder.appendToBuffer(buffer, u"Even more"); + QCOMPARE(position, buffer); + QVERIFY(encoder.hasError()); + } + + // QStringDecoder tests + { + QStringDecoder decoder; + QVERIFY(!decoder.name()); + QVERIFY(!decoder.isValid()); + QString decoded = decoder("Some text"); + QVERIFY(decoded.isEmpty()); + QVERIFY(decoder.hasError()); + + decoder.resetState(); + QVERIFY(!decoder.hasError()); + + decoded = decoder.decode("More text"); + QVERIFY(decoded.isEmpty()); + QVERIFY(decoder.hasError()); + + QCOMPARE(decoder.requiredSpace(42), 0); + + decoder.resetState(); + QVERIFY(!decoder.hasError()); + QChar buffer[100]; + QChar *position = decoder.appendToBuffer(buffer, "Even more"); + QCOMPARE(position, buffer); + QVERIFY(decoder.hasError()); + } +} + void tst_QStringConverter::convertUtf8_data() { QTest::addColumn<QStringConverter::Encoding>("encoding"); |