Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/json/json_parser.h" | 5 #include "base/json/json_parser.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 public: | 21 public: |
| 22 JSONParser* NewTestParser(const std::string& input, | 22 JSONParser* NewTestParser(const std::string& input, |
| 23 int options = JSON_PARSE_RFC) { | 23 int options = JSON_PARSE_RFC) { |
| 24 JSONParser* parser = new JSONParser(options); | 24 JSONParser* parser = new JSONParser(options); |
| 25 parser->start_pos_ = input.data(); | 25 parser->start_pos_ = input.data(); |
| 26 parser->pos_ = parser->start_pos_; | 26 parser->pos_ = parser->start_pos_; |
| 27 parser->end_pos_ = parser->start_pos_ + input.length(); | 27 parser->end_pos_ = parser->start_pos_ + input.length(); |
| 28 return parser; | 28 return parser; |
| 29 } | 29 } |
| 30 | 30 |
| 31 // MSan will do a better job detecting over-read errors if the input is | |
| 32 // not nul-terminated on the heap. This will copy |input| to a new buffer | |
| 33 // owned by |owner|, returning a StringPiece to |owner|. | |
| 34 StringPiece MakeNullTerminatedInput(const char* input, | |
|
jdoerrie
2017/05/05 09:34:11
nit: MakeNonNullTerminatedInput
Robert Sesek
2017/05/05 21:20:50
Done.
| |
| 35 std::unique_ptr<char[]>* owner) { | |
| 36 size_t str_len = strlen(input); | |
| 37 owner->reset(new char[str_len]); | |
| 38 memcpy(owner->get(), input, str_len); | |
| 39 return StringPiece(owner->get(), str_len); | |
| 40 } | |
| 41 | |
| 31 void TestLastThree(JSONParser* parser) { | 42 void TestLastThree(JSONParser* parser) { |
| 32 EXPECT_EQ(',', *parser->NextChar()); | 43 EXPECT_EQ(',', *parser->NextChar()); |
| 33 EXPECT_EQ('|', *parser->NextChar()); | 44 EXPECT_EQ('|', *parser->NextChar()); |
| 34 EXPECT_EQ('\0', *parser->NextChar()); | 45 EXPECT_EQ('\0', *parser->NextChar()); |
| 35 EXPECT_EQ(parser->end_pos_, parser->pos_); | 46 EXPECT_EQ(parser->end_pos_, parser->pos_); |
| 36 } | 47 } |
| 37 }; | 48 }; |
| 38 | 49 |
| 39 TEST_F(JSONParserTest, NextChar) { | 50 TEST_F(JSONParserTest, NextChar) { |
| 40 std::string input("Hello world"); | 51 std::string input("Hello world"); |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 360 {"9e-3", true, 0.009}, | 371 {"9e-3", true, 0.009}, |
| 361 {"2e+", false, 0}, | 372 {"2e+", false, 0}, |
| 362 {"2e+2", true, 200}, | 373 {"2e+2", true, 200}, |
| 363 // clang-format on | 374 // clang-format on |
| 364 }; | 375 }; |
| 365 | 376 |
| 366 for (unsigned int i = 0; i < arraysize(kCases); ++i) { | 377 for (unsigned int i = 0; i < arraysize(kCases); ++i) { |
| 367 auto test_case = kCases[i]; | 378 auto test_case = kCases[i]; |
| 368 SCOPED_TRACE(StringPrintf("case %u: \"%s\"", i, test_case.input)); | 379 SCOPED_TRACE(StringPrintf("case %u: \"%s\"", i, test_case.input)); |
| 369 | 380 |
| 370 // MSan will do a better job detecting over-read errors if the input is | 381 std::unique_ptr<char[]> input_owner; |
| 371 // not nul-terminated on the heap. | 382 StringPiece input = MakeNullTerminatedInput(test_case.input, &input_owner); |
| 372 size_t str_len = strlen(test_case.input); | |
| 373 auto non_nul_termianted = MakeUnique<char[]>(str_len); | |
| 374 memcpy(non_nul_termianted.get(), test_case.input, str_len); | |
| 375 | 383 |
| 376 StringPiece string_piece(non_nul_termianted.get(), str_len); | 384 std::unique_ptr<Value> result = JSONReader::Read(input); |
| 377 std::unique_ptr<Value> result = JSONReader::Read(string_piece); | |
| 378 if (test_case.parse_success) { | 385 if (test_case.parse_success) { |
| 379 EXPECT_TRUE(result); | 386 EXPECT_TRUE(result); |
| 380 } else { | 387 } else { |
| 381 EXPECT_FALSE(result); | 388 EXPECT_FALSE(result); |
| 382 } | 389 } |
| 383 | 390 |
| 384 if (!result) | 391 if (!result) |
| 385 continue; | 392 continue; |
| 386 | 393 |
| 387 double double_value = 0; | 394 double double_value = 0; |
| 388 EXPECT_TRUE(result->GetAsDouble(&double_value)); | 395 EXPECT_TRUE(result->GetAsDouble(&double_value)); |
| 389 EXPECT_EQ(test_case.value, double_value); | 396 EXPECT_EQ(test_case.value, double_value); |
| 390 } | 397 } |
| 391 } | 398 } |
| 392 | 399 |
| 400 TEST_F(JSONParserTest, UnterminatedInputs) { | |
| 401 const char* kCases[] = { | |
| 402 // clang-format off | |
| 403 "/", | |
| 404 "//", | |
| 405 "/*", | |
| 406 "\"xxxxxx", | |
| 407 "\"", | |
| 408 "{ ", | |
| 409 "[\t", | |
| 410 // clang-format on | |
| 411 }; | |
| 412 | |
| 413 for (unsigned int i = 0; i < arraysize(kCases); ++i) { | |
| 414 auto* test_case = kCases[i]; | |
| 415 SCOPED_TRACE(StringPrintf("case %u: \"%s\"", i, test_case)); | |
| 416 | |
| 417 std::unique_ptr<char[]> input_owner; | |
| 418 StringPiece input = MakeNullTerminatedInput(test_case, &input_owner); | |
| 419 | |
| 420 EXPECT_FALSE(JSONReader::Read(input)); | |
| 421 } | |
| 422 } | |
| 423 | |
| 393 } // namespace internal | 424 } // namespace internal |
| 394 } // namespace base | 425 } // namespace base |
| OLD | NEW |