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

Side by Side Diff: third_party/WebKit/Source/platform/json/JSONParser.cpp

Issue 2517183002: Add a configurable maximum parse depth for the blink JSON parser. (Closed)
Patch Set: Created 4 years, 1 month 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
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "platform/json/JSONParser.h" 5 #include "platform/json/JSONParser.h"
6 6
7 #include "platform/Decimal.h" 7 #include "platform/Decimal.h"
8 #include "platform/json/JSONValues.h" 8 #include "platform/json/JSONValues.h"
9 #include "wtf/text/StringBuilder.h" 9 #include "wtf/text/StringBuilder.h"
10 #include "wtf/text/StringToNumber.h" 10 #include "wtf/text/StringToNumber.h"
11 11
12 namespace blink { 12 namespace blink {
13 13
14 namespace { 14 namespace {
15 15
16 const int stackLimit = 1000; 16 const int kMaxStackLimit = 1000;
17 17
18 enum Token { 18 enum Token {
19 ObjectBegin, 19 ObjectBegin,
20 ObjectEnd, 20 ObjectEnd,
21 ArrayBegin, 21 ArrayBegin,
22 ArrayEnd, 22 ArrayEnd,
23 StringLiteral, 23 StringLiteral,
24 Number, 24 Number,
25 BoolTrue, 25 BoolTrue,
26 BoolFalse, 26 BoolFalse,
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 // Validate constructed utf16 string. 383 // Validate constructed utf16 string.
384 if (output->utf8(StrictUTF8Conversion).isNull()) 384 if (output->utf8(StrictUTF8Conversion).isNull())
385 return false; 385 return false;
386 return true; 386 return true;
387 } 387 }
388 388
389 template <typename CharType> 389 template <typename CharType>
390 std::unique_ptr<JSONValue> buildValue(const CharType* start, 390 std::unique_ptr<JSONValue> buildValue(const CharType* start,
391 const CharType* end, 391 const CharType* end,
392 const CharType** valueTokenEnd, 392 const CharType** valueTokenEnd,
393 int depth) { 393 int maxDepth) {
394 if (depth > stackLimit) 394 if (maxDepth == 0)
395 return nullptr; 395 return nullptr;
396 396
397 std::unique_ptr<JSONValue> result; 397 std::unique_ptr<JSONValue> result;
398 const CharType* tokenStart; 398 const CharType* tokenStart;
399 const CharType* tokenEnd; 399 const CharType* tokenEnd;
400 Token token = parseToken(start, end, &tokenStart, &tokenEnd); 400 Token token = parseToken(start, end, &tokenStart, &tokenEnd);
401 switch (token) { 401 switch (token) {
402 case InvalidToken: 402 case InvalidToken:
403 return nullptr; 403 return nullptr;
404 case NullToken: 404 case NullToken:
(...skipping 26 matching lines...) Expand all
431 return nullptr; 431 return nullptr;
432 result = JSONString::create(value); 432 result = JSONString::create(value);
433 break; 433 break;
434 } 434 }
435 case ArrayBegin: { 435 case ArrayBegin: {
436 std::unique_ptr<JSONArray> array = JSONArray::create(); 436 std::unique_ptr<JSONArray> array = JSONArray::create();
437 start = tokenEnd; 437 start = tokenEnd;
438 token = parseToken(start, end, &tokenStart, &tokenEnd); 438 token = parseToken(start, end, &tokenStart, &tokenEnd);
439 while (token != ArrayEnd) { 439 while (token != ArrayEnd) {
440 std::unique_ptr<JSONValue> arrayNode = 440 std::unique_ptr<JSONValue> arrayNode =
441 buildValue(start, end, &tokenEnd, depth + 1); 441 buildValue(start, end, &tokenEnd, maxDepth - 1);
442 if (!arrayNode) 442 if (!arrayNode)
443 return nullptr; 443 return nullptr;
444 array->pushValue(std::move(arrayNode)); 444 array->pushValue(std::move(arrayNode));
445 445
446 // After a list value, we expect a comma or the end of the list. 446 // After a list value, we expect a comma or the end of the list.
447 start = tokenEnd; 447 start = tokenEnd;
448 token = parseToken(start, end, &tokenStart, &tokenEnd); 448 token = parseToken(start, end, &tokenStart, &tokenEnd);
449 if (token == ListSeparator) { 449 if (token == ListSeparator) {
450 start = tokenEnd; 450 start = tokenEnd;
451 token = parseToken(start, end, &tokenStart, &tokenEnd); 451 token = parseToken(start, end, &tokenStart, &tokenEnd);
(...skipping 20 matching lines...) Expand all
472 if (!decodeString(tokenStart + 1, tokenEnd - 1, &key)) 472 if (!decodeString(tokenStart + 1, tokenEnd - 1, &key))
473 return nullptr; 473 return nullptr;
474 start = tokenEnd; 474 start = tokenEnd;
475 475
476 token = parseToken(start, end, &tokenStart, &tokenEnd); 476 token = parseToken(start, end, &tokenStart, &tokenEnd);
477 if (token != ObjectPairSeparator) 477 if (token != ObjectPairSeparator)
478 return nullptr; 478 return nullptr;
479 start = tokenEnd; 479 start = tokenEnd;
480 480
481 std::unique_ptr<JSONValue> value = 481 std::unique_ptr<JSONValue> value =
482 buildValue(start, end, &tokenEnd, depth + 1); 482 buildValue(start, end, &tokenEnd, maxDepth - 1);
483 if (!value) 483 if (!value)
484 return nullptr; 484 return nullptr;
485 object->setValue(key, std::move(value)); 485 object->setValue(key, std::move(value));
486 start = tokenEnd; 486 start = tokenEnd;
487 487
488 // After a key/value pair, we expect a comma or the end of the 488 // After a key/value pair, we expect a comma or the end of the
489 // object. 489 // object.
490 token = parseToken(start, end, &tokenStart, &tokenEnd); 490 token = parseToken(start, end, &tokenStart, &tokenEnd);
491 if (token == ListSeparator) { 491 if (token == ListSeparator) {
492 start = tokenEnd; 492 start = tokenEnd;
(...skipping 15 matching lines...) Expand all
508 // We got a token that's not a value. 508 // We got a token that's not a value.
509 return nullptr; 509 return nullptr;
510 } 510 }
511 511
512 skipWhitespaceAndComments(tokenEnd, end, valueTokenEnd); 512 skipWhitespaceAndComments(tokenEnd, end, valueTokenEnd);
513 return result; 513 return result;
514 } 514 }
515 515
516 template <typename CharType> 516 template <typename CharType>
517 std::unique_ptr<JSONValue> parseJSONInternal(const CharType* start, 517 std::unique_ptr<JSONValue> parseJSONInternal(const CharType* start,
518 unsigned length) { 518 unsigned length,
519 int maxDepth) {
519 const CharType* end = start + length; 520 const CharType* end = start + length;
520 const CharType* tokenEnd; 521 const CharType* tokenEnd;
521 std::unique_ptr<JSONValue> value = buildValue(start, end, &tokenEnd, 0); 522 std::unique_ptr<JSONValue> value =
523 buildValue(start, end, &tokenEnd, maxDepth);
522 if (!value || tokenEnd != end) 524 if (!value || tokenEnd != end)
523 return nullptr; 525 return nullptr;
524 return value; 526 return value;
525 } 527 }
526 528
527 } // anonymous namespace 529 } // anonymous namespace
528 530
529 std::unique_ptr<JSONValue> parseJSON(const String& json) { 531 std::unique_ptr<JSONValue> parseJSON(const String& json) {
532 return parseJSON(json, kMaxStackLimit);
533 }
534
535 std::unique_ptr<JSONValue> parseJSON(const String& json, int maxDepth) {
530 if (json.isEmpty()) 536 if (json.isEmpty())
531 return nullptr; 537 return nullptr;
538 if (maxDepth < 0)
539 maxDepth = 0;
540 if (maxDepth > kMaxStackLimit)
541 maxDepth = kMaxStackLimit;
532 if (json.is8Bit()) 542 if (json.is8Bit())
533 return parseJSONInternal(json.characters8(), json.length()); 543 return parseJSONInternal(json.characters8(), json.length(), maxDepth);
534 return parseJSONInternal(json.characters16(), json.length()); 544 return parseJSONInternal(json.characters16(), json.length(), maxDepth);
535 } 545 }
536 546
537 } // namespace blink 547 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/json/JSONParser.h ('k') | third_party/WebKit/Source/platform/json/JSONParserTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698