diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 2603992..fba9f19 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -400,6 +400,7 @@ public: ClearStackOnExit scope(*this); SkipWhitespaceAndComments(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(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(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; if (is.Peek() == '}') { is.Take(); @@ -512,21 +526,27 @@ private: RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; if (is.Take() != ':') RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; ParseValue(is, handler); RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; ++memberCount; switch (is.Take()) { - case ',': SkipWhitespaceAndComments(is); break; + case ',': + SkipWhitespaceAndComments(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(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; if (is.Peek() == ']') { is.Take(); @@ -560,9 +581,13 @@ private: ++elementCount; SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; switch (is.Take()) { - case ',': SkipWhitespaceAndComments(is); break; + case ',': + SkipWhitespaceAndComments(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(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(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); } // Handle the end of file. diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 010a1a9..71d7113 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -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(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(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(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(s, h)); + EXPECT_EQ(kParseErrorUnspecificSyntaxError, reader.GetParseErrorCode()); +} + #ifdef __GNUC__ RAPIDJSON_DIAG_POP #endif