summaryrefslogtreecommitdiffstats
path: root/chromium/base/json
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-07-12 14:07:37 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-07-17 10:29:26 +0000
commitec02ee4181c49b61fce1c8fb99292dbb8139cc90 (patch)
tree25cde714b2b71eb639d1cd53f5a22e9ba76e14ef /chromium/base/json
parentbb09965444b5bb20b096a291445170876225268d (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.cc63
-rw-r--r--chromium/base/json/json_parser.h2
-rw-r--r--chromium/base/json/json_parser_unittest.cc51
-rw-r--r--chromium/base/json/json_perftest.cc2
-rw-r--r--chromium/base/json/json_writer.cc4
-rw-r--r--chromium/base/json/json_writer_unittest.cc18
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));