| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |