From c69148c9468b02835803480fd204121f06c7530a Mon Sep 17 00:00:00 2001 From: Andrey Okoshkin Date: Fri, 12 Jan 2018 11:26:34 +0300 Subject: [PATCH] Fix Value::copyPayload() and Value::copy() (#704) Value copy constructor shares the same code with Value::copy() and Value::copyPayload(). New Value::releasePayload() is used to free payload memory. Fixes: #704 --- include/json/value.h | 1 + src/lib_json/json_value.cpp | 131 +++++++++++++++++++----------------- 2 files changed, 69 insertions(+), 63 deletions(-) diff --git a/include/json/value.h b/include/json/value.h index d1bf8ff..1643210 100644 --- a/include/json/value.h +++ b/include/json/value.h @@ -606,6 +606,7 @@ Json::Value obj_value(Json::objectValue); // {} private: void initBasic(ValueType type, bool allocated = false); + void releasePayload(); Value& resolveReference(const char* key); Value& resolveReference(const char* key, const char* end); diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp index 91d4802..eb7b6b0 100644 --- a/src/lib_json/json_value.cpp +++ b/src/lib_json/json_value.cpp @@ -441,48 +441,11 @@ Value::Value(bool value) { value_.bool_ = value; } -Value::Value(Value const& other) - : type_(other.type_), allocated_(false) - , - comments_(0), start_(other.start_), limit_(other.limit_) -{ - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - value_ = other.value_; - break; - case stringValue: - if (other.value_.string_ && other.allocated_) { - unsigned len; - char const* str; - decodePrefixedString(other.allocated_, other.value_.string_, - &len, &str); - value_.string_ = duplicateAndPrefixStringValue(str, len); - allocated_ = true; - } else { - value_.string_ = other.value_.string_; - allocated_ = false; - } - break; - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(*other.value_.map_); - break; - default: - JSON_ASSERT_UNREACHABLE; - } - if (other.comments_) { - comments_ = new CommentInfo[numberOfCommentPlacement]; - for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { - const CommentInfo& otherComment = other.comments_[comment]; - if (otherComment.comment_) - comments_[comment].setComment( - otherComment.comment_, strlen(otherComment.comment_)); - } - } +Value::Value(const Value& other) { + type_ = nullValue; + allocated_ = false; + comments_ = 0; + copy(other); } #if JSON_HAS_RVALUE_REFERENCES @@ -494,24 +457,7 @@ Value::Value(Value&& other) { #endif Value::~Value() { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue: - if (allocated_) - releasePrefixedStringValue(value_.string_); - break; - case arrayValue: - case objectValue: - delete value_.map_; - break; - default: - JSON_ASSERT_UNREACHABLE; - } + releasePayload(); delete[] comments_; @@ -534,9 +480,36 @@ void Value::swapPayload(Value& other) { } void Value::copyPayload(const Value& other) { + releasePayload(); type_ = other.type_; - value_ = other.value_; - allocated_ = other.allocated_; + allocated_ = false; + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + value_ = other.value_; + break; + case stringValue: + if (other.value_.string_ && other.allocated_) { + unsigned len; + char const* str; + decodePrefixedString(other.allocated_, other.value_.string_, + &len, &str); + value_.string_ = duplicateAndPrefixStringValue(str, len); + allocated_ = true; + } else { + value_.string_ = other.value_.string_; + } + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(*other.value_.map_); + break; + default: + JSON_ASSERT_UNREACHABLE; + } } void Value::swap(Value& other) { @@ -548,7 +521,18 @@ void Value::swap(Value& other) { void Value::copy(const Value& other) { copyPayload(other); - comments_ = other.comments_; + delete[] comments_; + if (other.comments_) { + comments_ = new CommentInfo[numberOfCommentPlacement]; + for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { + const CommentInfo& otherComment = other.comments_[comment]; + if (otherComment.comment_) + comments_[comment].setComment( + otherComment.comment_, strlen(otherComment.comment_)); + } + } else { + comments_ = 0; + } start_ = other.start_; limit_ = other.limit_; } @@ -1049,6 +1033,27 @@ void Value::initBasic(ValueType vtype, bool allocated) { limit_ = 0; } +void Value::releasePayload() { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + break; + case stringValue: + if (allocated_) + releasePrefixedStringValue(value_.string_); + break; + case arrayValue: + case objectValue: + delete value_.map_; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + // Access an object value by name, create a null member if it does not exist. // @pre Type of '*this' is object or null. // @param key is null-terminated.