From fa0ee9c9276e18f2224a273919bd553d793fcd78 Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Thu, 8 Jan 2015 22:35:48 +0100 Subject: [PATCH 1/2] Fixed escaped quotes --- src/json.cc | 62 ++++++++++++++++++++++++++++------------------- test/json_unit.cc | 1 + 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/json.cc b/src/json.cc index e548366a3d..04483cca41 100644 --- a/src/json.cc +++ b/src/json.cc @@ -2042,34 +2042,46 @@ Parses a string after opening quotes (\p ") where read. */ std::string json::parser::parseString() { - // get position of closing quotes - auto quotepos_ = buffer_.find_first_of("\"", pos_); - - // if the closing quotes are escaped (character before the quotes is a - // backslash), we continue looking for the final quotes - while (quotepos_ != std::string::npos and buffer_[quotepos_ - 1] == '\\') - { - quotepos_ = buffer_.find_first_of("\"", quotepos_ + 1); - } + // remember the position where the first character of the string was + const auto startPos = pos_; + // true if and only if the amount of backslashes before the current + // character is even + bool evenAmountOfBackslashes = true; + + // iterate with pos_ over the whole string + for (;pos_ < buffer_.size(); pos_++) { + char currentChar = buffer_[pos_]; + + // currentChar is a quote, so we might have found the end of the string + if (currentChar == '"') { + // but only if the amount of backslashes before that quote is even + if (evenAmountOfBackslashes) { + + const auto stringLength = pos_ - startPos; + // set pos_ behind the trailing quote + pos_++; + // find next char to parse + next(); + + // return string inside the quotes + return buffer_.substr(startPos, stringLength); + } + } - // check if closing quotes were found - if (quotepos_ == std::string::npos) - { - error("expected '\"'"); + // remember if we have a even amount of backslashes before the current character + if (currentChar == '\\') { + // jump between even/uneven for each backslash we encounter + evenAmountOfBackslashes = !evenAmountOfBackslashes; + } else { + // zero backslashes are also a even number, so as soon as we encounter a non-backslash + // the chain of backslashes breaks and we start again from zero + evenAmountOfBackslashes = true; + } } - // store the coordinates of the string for the later return value - const auto stringBegin = pos_; - const auto stringLength = quotepos_ - pos_; - - // set buffer position to the position behind (+1) the closing quote - pos_ = quotepos_ + 1; - - // read next character - next(); - - // return the string value - return buffer_.substr(stringBegin, stringLength); + // we iterated over the whole string without finding a unescaped quote + // so the given string is malformed + error("expected '\"'"); } /*! diff --git a/test/json_unit.cc b/test/json_unit.cc index f820ffa892..7856bdd18f 100644 --- a/test/json_unit.cc +++ b/test/json_unit.cc @@ -1621,6 +1621,7 @@ TEST_CASE("Parser") // escape characters CHECK_THROWS_AS(json::parse("\"\\\""), std::invalid_argument); CHECK_NOTHROW(json::parse("\"\\\"\"")); + CHECK_NOTHROW(json::parse("\"\\\\\"")); // quotes must be closed CHECK_THROWS_AS(json::parse("\""), std::invalid_argument); From 4a39bfb17eaa67dba90654d673a88791d2a733e6 Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Fri, 9 Jan 2015 11:57:39 +0100 Subject: [PATCH 2/2] Fixed typo in comments --- src/json.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/json.cc b/src/json.cc index 04483cca41..5cec2d09a9 100644 --- a/src/json.cc +++ b/src/json.cc @@ -2068,12 +2068,12 @@ std::string json::parser::parseString() } } - // remember if we have a even amount of backslashes before the current character + // remember if we have an even amount of backslashes before the current character if (currentChar == '\\') { // jump between even/uneven for each backslash we encounter evenAmountOfBackslashes = !evenAmountOfBackslashes; } else { - // zero backslashes are also a even number, so as soon as we encounter a non-backslash + // zero backslashes are also an even number, so as soon as we encounter a non-backslash // the chain of backslashes breaks and we start again from zero evenAmountOfBackslashes = true; }