From 2ece55abc7001962870f7ee4effbd1c852ee182e Mon Sep 17 00:00:00 2001 From: miloyip Date: Sat, 2 May 2015 20:44:30 +0800 Subject: [PATCH] Implement pointer parse error --- include/rapidjson/pointer.h | 114 ++++++++++++++++++++++------------ test/unittest/pointertest.cpp | 24 +++++++ 2 files changed, 97 insertions(+), 41 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index e470585..c0b7ba1 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -21,6 +21,13 @@ RAPIDJSON_NAMESPACE_BEGIN static const SizeType kPointerInvalidIndex = ~SizeType(0); +enum PointerParseErrorCode { + kPointerParseErrorNone = 0, + + kPointerParseErrorTokenMustBeginWithSolidus, + kPointerParseErrorInvalidEscape +}; + template class GenericPointer { public: @@ -33,55 +40,60 @@ public: SizeType index; //!< A valid index if not equal to kPointerInvalidIndex. }; - GenericPointer() - : allocator_(), + GenericPointer() : + allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), - valid_(true) + parseErrorOffset_(), + parseErrorCode_(kPointerParseErrorNone) { } - explicit GenericPointer(const Ch* source, Allocator* allocator = 0) - : allocator_(allocator), - ownAllocator_(), - nameBuffer_(), - tokens_(), - tokenCount_(), - valid_(true) + explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : + allocator_(allocator), + ownAllocator_(), + nameBuffer_(), + tokens_(), + tokenCount_(), + parseErrorOffset_(), + parseErrorCode_(kPointerParseErrorNone) { Parse(source, internal::StrLen(source)); } - GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) - : allocator_(allocator), - ownAllocator_(), - nameBuffer_(), - tokens_(), - tokenCount_(), - valid_(true) + GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : + allocator_(allocator), + ownAllocator_(), + nameBuffer_(), + tokens_(), + tokenCount_(), + parseErrorOffset_(), + parseErrorCode_(kPointerParseErrorNone) { Parse(source, length); } - GenericPointer(const Token* tokens, size_t tokenCount) - : allocator_(), - ownAllocator_(), - nameBuffer_(), - tokens_(const_cast(tokens)), - tokenCount_(tokenCount), - valid_(true) + GenericPointer(const Token* tokens, size_t tokenCount) : + allocator_(), + ownAllocator_(), + nameBuffer_(), + tokens_(const_cast(tokens)), + tokenCount_(tokenCount), + parseErrorOffset_(), + parseErrorCode_(kPointerParseErrorNone) { } - GenericPointer(const GenericPointer& rhs) - : allocator_(), - ownAllocator_(), - nameBuffer_(), - tokens_(), - tokenCount_(), - valid_() + GenericPointer(const GenericPointer& rhs) : + allocator_(), + ownAllocator_(), + nameBuffer_(), + tokens_(), + tokenCount_(), + parseErrorOffset_(), + parseErrorCode_(kPointerParseErrorNone) { *this = rhs; } @@ -98,7 +110,8 @@ public: this->~GenericPointer(); tokenCount_ = rhs.tokenCount_; - valid_ = rhs.valid_; + parseErrorOffset_ = rhs.parseErrorOffset_; + parseErrorCode_ = rhs.parseErrorCode_; if (rhs.nameBuffer_) { if (!allocator_) @@ -124,7 +137,11 @@ public: return *this; } - bool IsValid() const { return valid_; } + bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; } + + size_t GetParseErrorOffset() const { return parseErrorOffset_; } + + PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; } const Token* GetTokens() const { return tokens_; } @@ -276,9 +293,16 @@ private: tokenCount_ = 0; Ch* name = nameBuffer_; - for (size_t i = 0; i < length;) { - if (source[i++] != '/') // Consumes '/' - goto error; + size_t i = 0; + + if (length != 0 && source[i] != '/') { + parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus; + goto error; + } + + while (i < length) { + RAPIDJSON_ASSERT(source[i] == '/'); + i++; // consumes '/' Token& token = tokens_[tokenCount_++]; token.name = name; @@ -290,13 +314,19 @@ private: // Escaping "~0" -> '~', "~1" -> '/' if (c == '~') { if (i < length) { - c = source[i++]; + c = source[i]; if (c == '0') c = '~'; else if (c == '1') c = '/'; - else goto error; + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + i++; } - else + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; goto error; + } } // First check for index: all of characters are digit @@ -330,6 +360,7 @@ private: RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer tokens_ = (Token*)allocator_->Realloc(tokens_, length * sizeof(Token), tokenCount_ * sizeof(Token)); // Shrink tokens_ + parseErrorCode_ = kPointerParseErrorNone; return; error: @@ -338,7 +369,7 @@ private: nameBuffer_ = 0; tokens_ = 0; tokenCount_ = 0; - valid_ = false; + parseErrorOffset_ = i; return; } @@ -347,7 +378,8 @@ private: Ch* nameBuffer_; Token* tokens_; size_t tokenCount_; - bool valid_; + size_t parseErrorOffset_; + PointerParseErrorCode parseErrorCode_; }; template diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 3efa0ec..c58b858 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -139,6 +139,30 @@ TEST(Pointer, Parse) { EXPECT_STREQ("4294967296", p.GetTokens()[0].name); EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); } + + { + // kPointerParseErrorTokenMustBeginWithSolidus + Pointer p(" "); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorTokenMustBeginWithSolidus, p.GetParseErrorCode()); + EXPECT_EQ(0u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidEscape + Pointer p("/~"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidEscape + Pointer p("/~2"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } } TEST(Pointer, Stringify) {