Improve error offset in JSON parsing

Do not consume white-space after a token before the token has been
parsed, otherwise we end up with misleading offsets. This also fixes
a wrong error of illegal number in several cases.

Change-Id: I492ca4de0346a1d0ab73b1c23d7a72dba812664c
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2016-11-11 17:06:19 +01:00
parent 71d21ed500
commit e133f0cca4
2 changed files with 47 additions and 1 deletions

View File

@ -283,7 +283,6 @@ char Parser::nextToken()
case ValueSeparator:
case EndArray:
case EndObject:
eatSpace();
case Quote:
break;
default:
@ -469,6 +468,10 @@ bool Parser::parseMember(int baseOffset)
lastError = QJsonParseError::MissingNameSeparator;
return false;
}
if (!eatSpace()) {
lastError = QJsonParseError::UnterminatedObject;
return false;
}
QJsonPrivate::Value val;
if (!parseValue(&val, baseOffset))
return false;
@ -544,6 +547,10 @@ bool Parser::parseArray()
nextToken();
} else {
while (1) {
if (!eatSpace()) {
lastError = QJsonParseError::UnterminatedArray;
return false;
}
QJsonPrivate::Value val;
if (!parseValue(&val, arrayOffset))
return false;
@ -686,6 +693,12 @@ bool Parser::parseValue(QJsonPrivate::Value *val, int baseOffset)
DEBUG << "value: object";
END;
return true;
case ValueSeparator:
// Essentially missing value, but after a colon, not after a comma
// like the other MissingObject errors.
lastError = QJsonParseError::IllegalValue;
return false;
case EndObject:
case EndArray:
lastError = QJsonParseError::MissingObject;
return false;

View File

@ -139,6 +139,9 @@ private Q_SLOTS:
void removeNonLatinKey();
void documentFromVariant();
void parseErrorOffset_data();
void parseErrorOffset();
private:
QString testDataDir;
};
@ -2830,5 +2833,35 @@ void tst_QtJson::documentFromVariant()
QCOMPARE(do1.object(), do2.object());
}
void tst_QtJson::parseErrorOffset_data()
{
QTest::addColumn<QByteArray>("json");
QTest::addColumn<int>("errorOffset");
QTest::newRow("Trailing comma in object") << QByteArray("{ \"value\": false, }") << 19;
QTest::newRow("Trailing comma in object plus whitespace") << QByteArray("{ \"value\": false, } ") << 19;
QTest::newRow("Trailing comma in array") << QByteArray("[ false, ]") << 10;
QTest::newRow("Trailing comma in array plus whitespace") << QByteArray("[ false, ] ") << 10;
QTest::newRow("Missing value in object") << QByteArray("{ \"value\": , } ") << 12;
QTest::newRow("Missing value in array") << QByteArray("[ \"value\" , , ] ") << 13;
QTest::newRow("Leading comma in object") << QByteArray("{ , \"value\": false}") << 3;
QTest::newRow("Leading comma in array") << QByteArray("[ , false]") << 3;
QTest::newRow("Stray ,") << QByteArray(" , ") << 3;
QTest::newRow("Stray [") << QByteArray(" [ ") << 5;
QTest::newRow("Stray }") << QByteArray(" } ") << 3;
}
void tst_QtJson::parseErrorOffset()
{
QFETCH(QByteArray, json);
QFETCH(int, errorOffset);
QJsonParseError error;
QJsonDocument::fromJson(json, &error);
QVERIFY(error.error != QJsonParseError::NoError);
QCOMPARE(error.offset, errorOffset);
}
QTEST_MAIN(tst_QtJson)
#include "tst_qtjson.moc"