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>
This commit is contained in:
Fabian Kosmale 2022-05-25 09:07:37 +02:00
parent d83441340c
commit c46ee7df57
2 changed files with 82 additions and 4 deletions

View File

@ -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());

View File

@ -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");