Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(446)

Side by Side Diff: base/json/json_parser_unittest.cc

Issue 2859513002: Fix potential buffer over-read errors for un-terminated JSON strings and comments. (Closed)
Patch Set: test message fix Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/json/json_parser.cc ('k') | extensions/utility/unpacker_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « base/json/json_parser.cc ('k') | extensions/utility/unpacker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698