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 MakeNotNullTerminatedInput(const char* input, | |
| 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 = |
| 372 size_t str_len = strlen(test_case.input); | 383 MakeNotNullTerminatedInput(test_case.input, &input_owner); |
| 373 auto non_nul_termianted = MakeUnique<char[]>(str_len); | |
| 374 memcpy(non_nul_termianted.get(), test_case.input, str_len); | |
| 375 | 384 |
| 376 StringPiece string_piece(non_nul_termianted.get(), str_len); | 385 std::unique_ptr<Value> result = JSONReader::Read(input); |
| 377 std::unique_ptr<Value> result = JSONReader::Read(string_piece); | |
| 378 if (test_case.parse_success) { | 386 if (test_case.parse_success) { |
| 379 EXPECT_TRUE(result); | 387 EXPECT_TRUE(result); |
| 380 } else { | 388 } else { |
| 381 EXPECT_FALSE(result); | 389 EXPECT_FALSE(result); |
| 382 } | 390 } |
| 383 | 391 |
| 384 if (!result) | 392 if (!result) |
| 385 continue; | 393 continue; |
| 386 | 394 |
| 387 double double_value = 0; | 395 double double_value = 0; |
| 388 EXPECT_TRUE(result->GetAsDouble(&double_value)); | 396 EXPECT_TRUE(result->GetAsDouble(&double_value)); |
| 389 EXPECT_EQ(test_case.value, double_value); | 397 EXPECT_EQ(test_case.value, double_value); |
| 390 } | 398 } |
| 391 } | 399 } |
| 392 | 400 |
| 401 TEST_F(JSONParserTest, UnterminatedInputs) { | |
| 402 const char* kCases[] = { | |
| 403 // clang-format off | |
| 404 "/", | |
| 405 "//", | |
| 406 "/*", | |
| 407 "\"xxxxxx", | |
| 408 "\"", | |
| 409 "{ ", | |
| 410 "[\t", | |
| 411 "tru", | |
| 412 "fals", | |
| 413 "nul", | |
| 414 "\"\\x2", | |
| 415 "\"\\u123", | |
| 416 // clang-format on | |
| 417 }; | |
| 418 | |
| 419 for (unsigned int i = 0; i < arraysize(kCases); ++i) { | |
|
brettw
2017/05/09 19:53:14
Random optional thought: Does C++11 let you do:
Robert Sesek
2017/05/09 21:27:36
The |for (:)| construct does work, but I use |i| i
| |
| 420 auto* test_case = kCases[i]; | |
| 421 SCOPED_TRACE(StringPrintf("case %u: \"%s\"", i, test_case)); | |
| 422 | |
| 423 std::unique_ptr<char[]> input_owner; | |
| 424 StringPiece input = MakeNotNullTerminatedInput(test_case, &input_owner); | |
| 425 | |
| 426 EXPECT_FALSE(JSONReader::Read(input)); | |
| 427 } | |
| 428 } | |
| 429 | |
| 393 } // namespace internal | 430 } // namespace internal |
| 394 } // namespace base | 431 } // namespace base |
| OLD | NEW |