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 |