diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-07-12 14:07:37 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-07-17 10:29:26 +0000 |
commit | ec02ee4181c49b61fce1c8fb99292dbb8139cc90 (patch) | |
tree | 25cde714b2b71eb639d1cd53f5a22e9ba76e14ef /chromium/base/json | |
parent | bb09965444b5bb20b096a291445170876225268d (diff) |
BASELINE: Update Chromium to 59.0.3071.134
Change-Id: Id02ef6fb2204c5fd21668a1c3e6911c83b17585a
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/base/json')
-rw-r--r-- | chromium/base/json/json_parser.cc | 63 | ||||
-rw-r--r-- | chromium/base/json/json_parser.h | 2 | ||||
-rw-r--r-- | chromium/base/json/json_parser_unittest.cc | 51 | ||||
-rw-r--r-- | chromium/base/json/json_perftest.cc | 2 | ||||
-rw-r--r-- | chromium/base/json/json_writer.cc | 4 | ||||
-rw-r--r-- | chromium/base/json/json_writer_unittest.cc | 18 |
6 files changed, 101 insertions, 39 deletions
diff --git a/chromium/base/json/json_parser.cc b/chromium/base/json/json_parser.cc index 1666c122b1c..064b3cb8f0a 100644 --- a/chromium/base/json/json_parser.cc +++ b/chromium/base/json/json_parser.cc @@ -279,27 +279,31 @@ bool JSONParser::EatComment() { if (*pos_ != '/' || !CanConsume(1)) return false; - char next_char = *NextChar(); - if (next_char == '/') { + NextChar(); + + if (!CanConsume(1)) + return false; + + if (*pos_ == '/') { // Single line comment, read to newline. while (CanConsume(1)) { - next_char = *NextChar(); - if (next_char == '\n' || next_char == '\r') + if (*pos_ == '\n' || *pos_ == '\r') return true; + NextChar(); } - } else if (next_char == '*') { + } else if (*pos_ == '*') { char previous_char = '\0'; // Block comment, read until end marker. while (CanConsume(1)) { - next_char = *NextChar(); - if (previous_char == '*' && next_char == '/') { + if (previous_char == '*' && *pos_ == '/') { // EatWhitespaceAndComments will inspect pos_, which will still be on // the last / of the comment, so advance once more (which may also be // end of input). NextChar(); return true; } - previous_char = next_char; + previous_char = *pos_; + NextChar(); } // If the comment is unterminated, GetNextToken will report T_END_OF_INPUT. @@ -344,7 +348,7 @@ std::unique_ptr<Value> JSONParser::ConsumeDictionary() { return nullptr; } - std::unique_ptr<DictionaryValue> dict(new DictionaryValue); + std::vector<Value::DictStorage::value_type> dict_storage; NextChar(); Token token = GetNextToken(); @@ -376,7 +380,7 @@ std::unique_ptr<Value> JSONParser::ConsumeDictionary() { return nullptr; } - dict->SetWithoutPathExpansion(key.AsStringPiece(), std::move(value)); + dict_storage.emplace_back(key.DestructiveAsString(), std::move(value)); NextChar(); token = GetNextToken(); @@ -393,7 +397,8 @@ std::unique_ptr<Value> JSONParser::ConsumeDictionary() { } } - return std::move(dict); + return MakeUnique<Value>( + Value::DictStorage(std::move(dict_storage), KEEP_LAST_OF_DUPES)); } std::unique_ptr<Value> JSONParser::ConsumeList() { @@ -444,7 +449,7 @@ std::unique_ptr<Value> JSONParser::ConsumeString() { if (!ConsumeStringRaw(&string)) return nullptr; - return base::MakeUnique<StringValue>(string.DestructiveAsString()); + return base::MakeUnique<Value>(string.DestructiveAsString()); } bool JSONParser::ConsumeStringRaw(StringBuilder* out) { @@ -453,15 +458,29 @@ bool JSONParser::ConsumeStringRaw(StringBuilder* out) { return false; } + // Strings are at minimum two characters: the surrounding double quotes. + if (!CanConsume(2)) { + ReportError(JSONReader::JSON_SYNTAX_ERROR, 1); + return false; + } + // StringBuilder will internally build a StringPiece unless a UTF-16 // conversion occurs, at which point it will perform a copy into a // std::string. StringBuilder string(NextChar()); + // Handle the empty string case early. + if (*pos_ == '"') { + *out = std::move(string); + return true; + } + int length = end_pos_ - start_pos_; int32_t next_char = 0; - while (CanConsume(1)) { + // There must always be at least two characters left in the stream: the next + // string character and the terminating closing quote. + while (CanConsume(2)) { int start_index = index_; pos_ = start_pos_ + index_; // CBU8_NEXT is postcrement. CBU8_NEXT(start_pos_, index_, length, next_char); @@ -501,12 +520,18 @@ bool JSONParser::ConsumeStringRaw(StringBuilder* out) { return false; } - switch (*NextChar()) { + NextChar(); + if (!CanConsume(1)) { + ReportError(JSONReader::JSON_INVALID_ESCAPE, 0); + return false; + } + + switch (*pos_) { // Allowed esape sequences: case 'x': { // UTF-8 sequence. // UTF-8 \x escape sequences are not allowed in the spec, but they // are supported here for backwards-compatiblity with the old parser. - if (!CanConsume(2)) { + if (!CanConsume(3)) { ReportError(JSONReader::JSON_INVALID_ESCAPE, 1); return false; } @@ -776,7 +801,7 @@ std::unique_ptr<Value> JSONParser::ConsumeLiteral() { case 't': { const char kTrueLiteral[] = "true"; const int kTrueLen = static_cast<int>(strlen(kTrueLiteral)); - if (!CanConsume(kTrueLen - 1) || + if (!CanConsume(kTrueLen) || !StringsAreEqual(pos_, kTrueLiteral, kTrueLen)) { ReportError(JSONReader::JSON_SYNTAX_ERROR, 1); return nullptr; @@ -787,7 +812,7 @@ std::unique_ptr<Value> JSONParser::ConsumeLiteral() { case 'f': { const char kFalseLiteral[] = "false"; const int kFalseLen = static_cast<int>(strlen(kFalseLiteral)); - if (!CanConsume(kFalseLen - 1) || + if (!CanConsume(kFalseLen) || !StringsAreEqual(pos_, kFalseLiteral, kFalseLen)) { ReportError(JSONReader::JSON_SYNTAX_ERROR, 1); return nullptr; @@ -798,13 +823,13 @@ std::unique_ptr<Value> JSONParser::ConsumeLiteral() { case 'n': { const char kNullLiteral[] = "null"; const int kNullLen = static_cast<int>(strlen(kNullLiteral)); - if (!CanConsume(kNullLen - 1) || + if (!CanConsume(kNullLen) || !StringsAreEqual(pos_, kNullLiteral, kNullLen)) { ReportError(JSONReader::JSON_SYNTAX_ERROR, 1); return nullptr; } NextNChars(kNullLen - 1); - return Value::CreateNullValue(); + return MakeUnique<Value>(); } default: ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1); diff --git a/chromium/base/json/json_parser.h b/chromium/base/json/json_parser.h index d2850e516b2..4f264583638 100644 --- a/chromium/base/json/json_parser.h +++ b/chromium/base/json/json_parser.h @@ -31,7 +31,7 @@ class JSONParserTest; // to be used directly; it encapsulates logic that need not be exposed publicly. // // This parser guarantees O(n) time through the input string. It also optimizes -// base::StringValue by using StringPiece where possible when returning Value +// base::Value by using StringPiece where possible when returning Value // objects by using "hidden roots," discussed in the implementation. // // Iteration happens on the byte level, with the functions CanConsume and diff --git a/chromium/base/json/json_parser_unittest.cc b/chromium/base/json/json_parser_unittest.cc index e3f635b76f1..dfbe77de82b 100644 --- a/chromium/base/json/json_parser_unittest.cc +++ b/chromium/base/json/json_parser_unittest.cc @@ -28,6 +28,17 @@ class JSONParserTest : public testing::Test { return parser; } + // MSan will do a better job detecting over-read errors if the input is + // not nul-terminated on the heap. This will copy |input| to a new buffer + // owned by |owner|, returning a StringPiece to |owner|. + StringPiece MakeNotNullTerminatedInput(const char* input, + std::unique_ptr<char[]>* owner) { + size_t str_len = strlen(input); + owner->reset(new char[str_len]); + memcpy(owner->get(), input, str_len); + return StringPiece(owner->get(), str_len); + } + void TestLastThree(JSONParser* parser) { EXPECT_EQ(',', *parser->NextChar()); EXPECT_EQ('|', *parser->NextChar()); @@ -367,14 +378,11 @@ TEST_F(JSONParserTest, ParseNumberErrors) { auto test_case = kCases[i]; SCOPED_TRACE(StringPrintf("case %u: \"%s\"", i, test_case.input)); - // MSan will do a better job detecting over-read errors if the input is - // not nul-terminated on the heap. - size_t str_len = strlen(test_case.input); - auto non_nul_termianted = MakeUnique<char[]>(str_len); - memcpy(non_nul_termianted.get(), test_case.input, str_len); + std::unique_ptr<char[]> input_owner; + StringPiece input = + MakeNotNullTerminatedInput(test_case.input, &input_owner); - StringPiece string_piece(non_nul_termianted.get(), str_len); - std::unique_ptr<Value> result = JSONReader::Read(string_piece); + std::unique_ptr<Value> result = JSONReader::Read(input); if (test_case.parse_success) { EXPECT_TRUE(result); } else { @@ -390,5 +398,34 @@ TEST_F(JSONParserTest, ParseNumberErrors) { } } +TEST_F(JSONParserTest, UnterminatedInputs) { + const char* kCases[] = { + // clang-format off + "/", + "//", + "/*", + "\"xxxxxx", + "\"", + "{ ", + "[\t", + "tru", + "fals", + "nul", + "\"\\x2", + "\"\\u123", + // clang-format on + }; + + for (unsigned int i = 0; i < arraysize(kCases); ++i) { + auto* test_case = kCases[i]; + SCOPED_TRACE(StringPrintf("case %u: \"%s\"", i, test_case)); + + std::unique_ptr<char[]> input_owner; + StringPiece input = MakeNotNullTerminatedInput(test_case, &input_owner); + + EXPECT_FALSE(JSONReader::Read(input)); + } +} + } // namespace internal } // namespace base diff --git a/chromium/base/json/json_perftest.cc b/chromium/base/json/json_perftest.cc index 345f226a2cf..15222468d78 100644 --- a/chromium/base/json/json_perftest.cc +++ b/chromium/base/json/json_perftest.cc @@ -26,7 +26,7 @@ std::unique_ptr<DictionaryValue> GenerateDict() { list->Set(0, MakeUnique<Value>(2.718)); list->Set(1, MakeUnique<Value>(false)); list->Set(2, MakeUnique<Value>(123)); - list->Set(3, MakeUnique<StringValue>("Bar")); + list->Set(3, MakeUnique<Value>("Bar")); root->Set("List", std::move(list)); return root; diff --git a/chromium/base/json/json_writer.cc b/chromium/base/json/json_writer.cc index 07b9d5091c8..19f28f21ada 100644 --- a/chromium/base/json/json_writer.cc +++ b/chromium/base/json/json_writer.cc @@ -128,7 +128,7 @@ bool JSONWriter::BuildJSONString(const Value& node, size_t depth) { bool result = node.GetAsList(&list); DCHECK(result); for (const auto& value : *list) { - if (omit_binary_values_ && value->GetType() == Value::Type::BINARY) + if (omit_binary_values_ && value.GetType() == Value::Type::BINARY) continue; if (first_value_has_been_output) { @@ -137,7 +137,7 @@ bool JSONWriter::BuildJSONString(const Value& node, size_t depth) { json_string_->push_back(' '); } - if (!BuildJSONString(*value, depth)) + if (!BuildJSONString(value, depth)) result = false; first_value_has_been_output = true; diff --git a/chromium/base/json/json_writer_unittest.cc b/chromium/base/json/json_writer_unittest.cc index 083fdc7eb40..1b57e060697 100644 --- a/chromium/base/json/json_writer_unittest.cc +++ b/chromium/base/json/json_writer_unittest.cc @@ -15,7 +15,7 @@ TEST(JSONWriterTest, BasicTypes) { std::string output_js; // Test null. - EXPECT_TRUE(JSONWriter::Write(*Value::CreateNullValue(), &output_js)); + EXPECT_TRUE(JSONWriter::Write(Value(), &output_js)); EXPECT_EQ("null", output_js); // Test empty dict. @@ -47,7 +47,7 @@ TEST(JSONWriterTest, BasicTypes) { EXPECT_EQ("-0.8", output_js); // Test String values. - EXPECT_TRUE(JSONWriter::Write(StringValue("foo"), &output_js)); + EXPECT_TRUE(JSONWriter::Write(Value("foo"), &output_js)); EXPECT_EQ("\"foo\"", output_js); } @@ -111,29 +111,29 @@ TEST(JSONWriterTest, BinaryValues) { // Binary values should return errors unless suppressed via the // OPTIONS_OMIT_BINARY_VALUES flag. - std::unique_ptr<Value> root(BinaryValue::CreateWithCopiedBuffer("asdf", 4)); + std::unique_ptr<Value> root(Value::CreateWithCopiedBuffer("asdf", 4)); EXPECT_FALSE(JSONWriter::Write(*root, &output_js)); EXPECT_TRUE(JSONWriter::WriteWithOptions( *root, JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &output_js)); EXPECT_TRUE(output_js.empty()); ListValue binary_list; - binary_list.Append(BinaryValue::CreateWithCopiedBuffer("asdf", 4)); + binary_list.Append(Value::CreateWithCopiedBuffer("asdf", 4)); binary_list.Append(MakeUnique<Value>(5)); - binary_list.Append(BinaryValue::CreateWithCopiedBuffer("asdf", 4)); + binary_list.Append(Value::CreateWithCopiedBuffer("asdf", 4)); binary_list.Append(MakeUnique<Value>(2)); - binary_list.Append(BinaryValue::CreateWithCopiedBuffer("asdf", 4)); + binary_list.Append(Value::CreateWithCopiedBuffer("asdf", 4)); EXPECT_FALSE(JSONWriter::Write(binary_list, &output_js)); EXPECT_TRUE(JSONWriter::WriteWithOptions( binary_list, JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &output_js)); EXPECT_EQ("[5,2]", output_js); DictionaryValue binary_dict; - binary_dict.Set("a", BinaryValue::CreateWithCopiedBuffer("asdf", 4)); + binary_dict.Set("a", Value::CreateWithCopiedBuffer("asdf", 4)); binary_dict.SetInteger("b", 5); - binary_dict.Set("c", BinaryValue::CreateWithCopiedBuffer("asdf", 4)); + binary_dict.Set("c", Value::CreateWithCopiedBuffer("asdf", 4)); binary_dict.SetInteger("d", 2); - binary_dict.Set("e", BinaryValue::CreateWithCopiedBuffer("asdf", 4)); + binary_dict.Set("e", Value::CreateWithCopiedBuffer("asdf", 4)); EXPECT_FALSE(JSONWriter::Write(binary_dict, &output_js)); EXPECT_TRUE(JSONWriter::WriteWithOptions( binary_dict, JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &output_js)); |