diff --git a/include/rapidjson/prettywriter.h b/include/rapidjson/prettywriter.h index d663208a..b68b687d 100644 --- a/include/rapidjson/prettywriter.h +++ b/include/rapidjson/prettywriter.h @@ -136,8 +136,10 @@ public: bool EndObject(SizeType memberCount = 0) { (void)memberCount; - RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); - RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object + RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); // currently inside an Array, not Object + RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top()->valueCount % 2); // Object has a Key without a Value + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; if (!empty) { diff --git a/include/rapidjson/writer.h b/include/rapidjson/writer.h index 5b3004b0..43ec5dc6 100644 --- a/include/rapidjson/writer.h +++ b/include/rapidjson/writer.h @@ -221,8 +221,9 @@ public: bool EndObject(SizeType memberCount = 0) { (void)memberCount; - RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); - RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object + RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); // currently inside an Array, not Object + RAPIDJSON_ASSERT(0 == level_stack_.template Top()->valueCount % 2); // Object has a Key without a Value level_stack_.template Pop(1); return EndValue(WriteEndObject()); } diff --git a/test/unittest/prettywritertest.cpp b/test/unittest/prettywritertest.cpp index 13d1a8d9..2891c76c 100644 --- a/test/unittest/prettywritertest.cpp +++ b/test/unittest/prettywritertest.cpp @@ -207,6 +207,57 @@ TEST(PrettyWriter, RawValue) { buffer.GetString()); } +TEST(PrettyWriter, InvalidEventSequence) { + // {] + { + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.StartObject(); + EXPECT_THROW(writer.EndArray(), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } + + // [} + { + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.StartArray(); + EXPECT_THROW(writer.EndObject(), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } + + // { 1: + { + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.StartObject(); + EXPECT_THROW(writer.Int(1), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } + + // { 'a' } + { + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.StartObject(); + writer.Key("a"); + EXPECT_THROW(writer.EndObject(), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } + + // { 'a':'b','c' } + { + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.StartObject(); + writer.Key("a"); + writer.String("b"); + writer.Key("c"); + EXPECT_THROW(writer.EndObject(), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } +} + #if RAPIDJSON_HAS_CXX11_RVALUE_REFS static PrettyWriter WriterGen(StringBuffer &target) { diff --git a/test/unittest/writertest.cpp b/test/unittest/writertest.cpp index d346e0f3..398a63dc 100644 --- a/test/unittest/writertest.cpp +++ b/test/unittest/writertest.cpp @@ -442,6 +442,28 @@ TEST(Writer, InvalidEventSequence) { EXPECT_THROW(writer.Int(1), AssertException); EXPECT_FALSE(writer.IsComplete()); } + + // { 'a' } + { + StringBuffer buffer; + Writer writer(buffer); + writer.StartObject(); + writer.Key("a"); + EXPECT_THROW(writer.EndObject(), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } + + // { 'a':'b','c' } + { + StringBuffer buffer; + Writer writer(buffer); + writer.StartObject(); + writer.Key("a"); + writer.String("b"); + writer.Key("c"); + EXPECT_THROW(writer.EndObject(), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } } TEST(Writer, NaN) {