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 // clang-format on |
| 415 }; |
| 416 |
| 417 for (unsigned int i = 0; i < arraysize(kCases); ++i) { |
| 418 auto* test_case = kCases[i]; |
| 419 SCOPED_TRACE(StringPrintf("case %u: \"%s\"", i, test_case)); |
| 420 |
| 421 std::unique_ptr<char[]> input_owner; |
| 422 StringPiece input = MakeNotNullTerminatedInput(test_case, &input_owner); |
| 423 |
| 424 EXPECT_FALSE(JSONReader::Read(input)); |
| 425 } |
| 426 } |
| 427 |
393 } // namespace internal | 428 } // namespace internal |
394 } // namespace base | 429 } // namespace base |
OLD | NEW |