Commit f7960ac0 authored by Andrey's avatar Andrey

Comments parsing fixes.

* Comments parsing function correctly handles EOF.
* Since SkipWhitespaceAndComments can generate errors, its calls should be followed by RAPIDJSON_PARSE_ERROR_EARLY_RETURN macro.
* Some tests to make the bug never appear again.
parent 5ce78b13
......@@ -400,6 +400,7 @@ public:
ClearStackOnExit scope(*this);
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
if (is.Peek() == '\0') {
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
......@@ -411,6 +412,7 @@ public:
if (!(parseFlags & kParseStopWhenDoneFlag)) {
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
if (is.Peek() != '\0') {
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
......@@ -473,10 +475,21 @@ private:
if (is.Peek() == '*') {
is.Take();
while (is.Take() != '*' || is.Take() != '/') { }
while (true) {
if (is.Peek() == '\0')
RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
if (is.Take() == '*') {
if (is.Peek() == '\0')
RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
if (is.Take() == '/')
break;
}
}
} else if (is.Peek() == '/') {
is.Take();
while (is.Take() != '\n') { }
while (is.Peek() != '\0' && is.Take() != '\n') { }
} else {
RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
}
......@@ -496,6 +509,7 @@ private:
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
if (is.Peek() == '}') {
is.Take();
......@@ -512,21 +526,27 @@ private:
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
if (is.Take() != ':')
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
ParseValue<parseFlags>(is, handler);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
++memberCount;
switch (is.Take()) {
case ',': SkipWhitespaceAndComments<parseFlags>(is); break;
case ',':
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
break;
case '}':
if (!handler.EndObject(memberCount))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
......@@ -546,6 +566,7 @@ private:
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
if (is.Peek() == ']') {
is.Take();
......@@ -560,9 +581,13 @@ private:
++elementCount;
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
switch (is.Take()) {
case ',': SkipWhitespaceAndComments<parseFlags>(is); break;
case ',':
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
break;
case ']':
if (!handler.EndArray(elementCount))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
......@@ -1429,6 +1454,7 @@ private:
IterativeParsingState state = IterativeParsingStartState;
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
while (is.Peek() != '\0') {
Token t = Tokenize(is.Peek());
IterativeParsingState n = Predict(state, t);
......@@ -1446,6 +1472,7 @@ private:
break;
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
}
// Handle the end of file.
......
......@@ -1387,6 +1387,19 @@ TEST(Reader, ParseEmptyOnelineComment) {
EXPECT_EQ(20u, h.step_);
}
TEST(Reader, ParseMultipleCommentsInARow) {
const char* json =
"{/* first comment *//* second */\n"
"/* third */ /*fourth*/// last one\n"
"\"hello\" : \"world\", \"t\" : true, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }";
StringStream s(json);
ParseObjectHandler h;
Reader reader;
EXPECT_TRUE(reader.Parse<kParseCommentsFlag>(s, h));
EXPECT_EQ(20u, h.step_);
}
TEST(Reader, InlineCommentsAreDisabledByDefault) {
{
const char* json = "{/* Inline comment. */\"hello\" : \"world\", \"t\" : true, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }";
......@@ -1419,6 +1432,26 @@ TEST(Reader, OnelineCommentsAreDisabledByDefault) {
EXPECT_FALSE(reader.Parse<kParseDefaultFlags>(s, h));
}
TEST(Reader, EofAfterOneLineComment) {
const char* json = "{\"hello\" : \"world\" // EOF is here -->\0 \n}";
StringStream s(json);
ParseObjectHandler h;
Reader reader;
EXPECT_FALSE(reader.Parse<kParseCommentsFlag>(s, h));
EXPECT_EQ(kParseErrorObjectMissCommaOrCurlyBracket, reader.GetParseErrorCode());
}
TEST(Reader, IncompleteMultilineComment) {
const char* json = "{\"hello\" : \"world\" /* EOF is here -->\0 */}";
StringStream s(json);
ParseObjectHandler h;
Reader reader;
EXPECT_FALSE(reader.Parse<kParseCommentsFlag>(s, h));
EXPECT_EQ(kParseErrorUnspecificSyntaxError, reader.GetParseErrorCode());
}
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment