From cada3b951fb54f04f9ae69243175ffbdbfbc445a Mon Sep 17 00:00:00 2001 From: Christopher Dunn Date: Fri, 6 Mar 2015 12:14:37 -0600 Subject: [PATCH 1/3] test for repeated key in strictMode https://sourceforge.net/p/jsoncpp/bugs/22/ --- src/test_lib_json/main.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp index 5e4c0de..c1960a9 100644 --- a/src/test_lib_json/main.cpp +++ b/src/test_lib_json/main.cpp @@ -1884,6 +1884,29 @@ JSONTEST_FIXTURE(CharReaderTest, parseWithStackLimit) { } } +struct CharReaderStrictModeTest : JsonTest::TestCase {}; + +JSONTEST_FIXTURE(CharReaderStrictModeTest, dupKeys) { + Json::CharReaderBuilder b; + Json::Value root; + char const doc[] = + "{ \"property\" : \"value\", \"key\" : \"val1\", \"key\" : \"val2\" }"; + { + b.strictMode(&b.settings_); + Json::CharReader* reader(b.newCharReader()); + std::string errs; + bool ok = reader->parse( + doc, doc + std::strlen(doc), + &root, &errs); + JSONTEST_ASSERT(!ok); + JSONTEST_ASSERT_STRING_EQUAL( + "* Line 1, Column 41\n" + " Duplicate key: 'key'\n", + errs); + JSONTEST_ASSERT_EQUAL("val1", root["key"]); // so far + delete reader; + } +} struct CharReaderFailIfExtraTest : JsonTest::TestCase {}; JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue164) { @@ -2305,6 +2328,8 @@ int main(int argc, const char* argv[]) { JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithDetailError); JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithStackLimit); + JSONTEST_REGISTER_FIXTURE(runner, CharReaderStrictModeTest, dupKeys); + JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, issue164); JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, issue107); JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, commentAfterObject); From 527332d5d5aae9fafa7caacc86e0455808b16f91 Mon Sep 17 00:00:00 2001 From: Christopher Dunn Date: Fri, 6 Mar 2015 12:18:59 -0600 Subject: [PATCH 2/3] add rejectDupKeys feature - not yet impld --- include/json/reader.h | 2 ++ src/lib_json/json_reader.cpp | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/include/json/reader.h b/include/json/reader.h index f983ce9..251d7c6 100644 --- a/include/json/reader.h +++ b/include/json/reader.h @@ -320,6 +320,8 @@ public: - `"failIfExtra": false or true` - If true, `parse()` returns false when extra non-whitespace trails the JSON value in the input string. + - `"rejectDupKeys": false or true` + - If true, `parse()` returns false when a key is duplicated within an object. You can examine 'settings_` yourself to see the defaults. You can also write and read them just like any diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index b04b60a..c79abdf 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -916,6 +916,7 @@ public: bool allowNumericKeys_; bool allowSingleQuotes_; bool failIfExtra_; + bool rejectDupKeys_; int stackLimit_; }; // OurFeatures @@ -1896,6 +1897,7 @@ CharReader* CharReaderBuilder::newCharReader() const features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); features.stackLimit_ = settings_["stackLimit"].asInt(); features.failIfExtra_ = settings_["failIfExtra"].asBool(); + features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); return new OurCharReader(collectComments, features); } static void getValidReaderKeys(std::set* valid_keys) @@ -1909,6 +1911,7 @@ static void getValidReaderKeys(std::set* valid_keys) valid_keys->insert("allowSingleQuotes"); valid_keys->insert("stackLimit"); valid_keys->insert("failIfExtra"); + valid_keys->insert("rejectDupKeys"); } bool CharReaderBuilder::validate(Json::Value* invalid) const { @@ -1941,6 +1944,7 @@ void CharReaderBuilder::strictMode(Json::Value* settings) (*settings)["allowNumericKeys"] = false; (*settings)["allowSingleQuotes"] = false; (*settings)["failIfExtra"] = true; + (*settings)["rejectDupKeys"] = true; //! [CharReaderBuilderStrictMode] } // static @@ -1955,6 +1959,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) (*settings)["allowSingleQuotes"] = false; (*settings)["stackLimit"] = 1000; (*settings)["failIfExtra"] = false; + (*settings)["rejectDupKeys"] = false; //! [CharReaderBuilderDefaults] } From 62ad140d1852ac6f90d16e4e03d168896f08d8a7 Mon Sep 17 00:00:00 2001 From: Christopher Dunn Date: Fri, 6 Mar 2015 12:35:58 -0600 Subject: [PATCH 3/3] rejectDupKeys --- src/lib_json/json_reader.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index c79abdf..9ceaf38 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -1432,6 +1432,11 @@ bool OurReader::readObject(Token& tokenStart) { "Missing ':' after object member name", colon, tokenObjectEnd); } if (name.length() >= (1U<<30)) throw std::runtime_error("keylength >= 2^30"); + if (features_.rejectDupKeys_ && currentValue().isMember(name)) { + std::string msg = "Duplicate key: '" + name + "'"; + return addErrorAndRecover( + msg, tokenName, tokenObjectEnd); + } Value& value = currentValue()[name]; nodes_.push(&value); bool ok = readValue();