blob: 550023d8f100455cfd94b4e11f4fc64420347800 [file] [log] [blame]
// Copyright (c) 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/json/json_parser.h"
#include "base/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/json/json_values.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
TEST(JSONParserTest, Reading) {
JSONParseError error;
JSONValue* tmp_value;
std::unique_ptr<JSONValue> root;
std::unique_ptr<JSONValue> root2;
String str_val;
int int_val = 0;
// Successfull parsing returns kNoError.
root = ParseJSON("1", &error);
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONParseErrorType::kNoError, error.type);
root = ParseJSON("\"string\"", &error);
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONParseErrorType::kNoError, error.type);
root = ParseJSON("[]", &error);
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONParseErrorType::kNoError, error.type);
root = ParseJSON("{}", &error);
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONParseErrorType::kNoError, error.type);
// some whitespace checking
root = ParseJSON(" null ", &error);
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeNull, root->GetType());
EXPECT_EQ(JSONParseErrorType::kNoError, error.type);
// Invalid JSON string
root = ParseJSON("nu", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
// Error reporting
root = ParseJSON("\n\n nu", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 3, column: 3, Syntax error.", error.message);
EXPECT_EQ(JSONParseErrorType::kSyntaxError, error.type);
EXPECT_EQ(3, error.line);
EXPECT_EQ(3, error.column);
// Simple bool
root = ParseJSON("true ");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeBoolean, root->GetType());
// Embedded comment
root = ParseJSON("40 /*/", &error);
// EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
root = ParseJSON("/* comment */null");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeNull, root->GetType());
root = ParseJSON("40 /* comment */");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
EXPECT_TRUE(root->AsInteger(&int_val));
EXPECT_EQ(40, int_val);
root = ParseJSON("/**/ 40 /* multi-line\n comment */ // more comment");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
EXPECT_TRUE(root->AsInteger(&int_val));
EXPECT_EQ(40, int_val);
root = ParseJSON("true // comment");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeBoolean, root->GetType());
root = ParseJSON("/* comment */\"sample string\"");
ASSERT_TRUE(root.get());
EXPECT_TRUE(root->AsString(&str_val));
EXPECT_EQ("sample string", str_val);
root = ParseJSON("[1, /* comment, 2 ] */ \n 3]");
ASSERT_TRUE(root.get());
JSONArray* list = JSONArray::Cast(root.get());
ASSERT_TRUE(list);
EXPECT_EQ(2u, list->size());
tmp_value = list->at(0);
ASSERT_TRUE(tmp_value);
EXPECT_TRUE(tmp_value->AsInteger(&int_val));
EXPECT_EQ(1, int_val);
tmp_value = list->at(1);
ASSERT_TRUE(tmp_value);
EXPECT_TRUE(tmp_value->AsInteger(&int_val));
EXPECT_EQ(3, int_val);
root = ParseJSON("[1, /*a*/2, 3]");
ASSERT_TRUE(root.get());
list = JSONArray::Cast(root.get());
ASSERT_TRUE(list);
EXPECT_EQ(3u, list->size());
root = ParseJSON("/* comment **/42");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
EXPECT_TRUE(root->AsInteger(&int_val));
EXPECT_EQ(42, int_val);
root = ParseJSON(
"/* comment **/\n"
"// */ 43\n"
"44");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
EXPECT_TRUE(root->AsInteger(&int_val));
EXPECT_EQ(44, int_val);
// Test number formats
root = ParseJSON("43");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
EXPECT_TRUE(root->AsInteger(&int_val));
EXPECT_EQ(43, int_val);
// According to RFC4627, oct, hex, and leading zeros are invalid JSON.
root = ParseJSON("043", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 2, Syntax error.", error.message);
root = ParseJSON("0x43", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 2, Unexpected data after root element.",
error.message);
root = ParseJSON("00", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 2, Syntax error.", error.message);
// Test 0 (which needs to be special cased because of the leading zero
// clause).
root = ParseJSON("0");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
int_val = 1;
EXPECT_TRUE(root->AsInteger(&int_val));
EXPECT_EQ(0, int_val);
// Numbers that overflow ints should succeed, being internally promoted to
// storage as doubles
root = ParseJSON("2147483648");
ASSERT_TRUE(root.get());
double double_val;
EXPECT_EQ(JSONValue::kTypeDouble, root->GetType());
double_val = 0.0;
EXPECT_TRUE(root->AsDouble(&double_val));
EXPECT_DOUBLE_EQ(2147483648.0, double_val);
root = ParseJSON("-2147483649");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeDouble, root->GetType());
double_val = 0.0;
EXPECT_TRUE(root->AsDouble(&double_val));
EXPECT_DOUBLE_EQ(-2147483649.0, double_val);
// Parse a double
root = ParseJSON("43.1");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeDouble, root->GetType());
double_val = 0.0;
EXPECT_TRUE(root->AsDouble(&double_val));
EXPECT_DOUBLE_EQ(43.1, double_val);
root = ParseJSON("4.3e-1");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeDouble, root->GetType());
double_val = 0.0;
EXPECT_TRUE(root->AsDouble(&double_val));
EXPECT_DOUBLE_EQ(.43, double_val);
root = ParseJSON("2.1e0");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeDouble, root->GetType());
double_val = 0.0;
EXPECT_TRUE(root->AsDouble(&double_val));
EXPECT_DOUBLE_EQ(2.1, double_val);
root = ParseJSON("2.1e+0001");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
double_val = 0.0;
EXPECT_TRUE(root->AsDouble(&double_val));
EXPECT_DOUBLE_EQ(21.0, double_val);
root = ParseJSON("0.01");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeDouble, root->GetType());
double_val = 0.0;
EXPECT_TRUE(root->AsDouble(&double_val));
EXPECT_DOUBLE_EQ(0.01, double_val);
root = ParseJSON("1.00");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
double_val = 0.0;
EXPECT_TRUE(root->AsDouble(&double_val));
EXPECT_DOUBLE_EQ(1.0, double_val);
// Fractional parts must have a digit before and after the decimal point.
root = ParseJSON("1.", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
root = ParseJSON(".1", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
root = ParseJSON("1.e10", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
// Exponent must have a digit following the 'e'.
root = ParseJSON("1e", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
root = ParseJSON("1E", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
root = ParseJSON("1e1.", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
error.message);
root = ParseJSON("1e1.0", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
error.message);
// INF/-INF/NaN are not valid
root = ParseJSON("NaN", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
root = ParseJSON("nan", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
root = ParseJSON("inf", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
// Invalid number formats
root = ParseJSON("4.3.1", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
error.message);
root = ParseJSON("4e3.1", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
error.message);
// Test string parser
root = ParseJSON("\"hello world\"");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeString, root->GetType());
EXPECT_TRUE(root->AsString(&str_val));
EXPECT_EQ("hello world", str_val);
// Empty string
root = ParseJSON("\"\"");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeString, root->GetType());
EXPECT_TRUE(root->AsString(&str_val));
EXPECT_EQ("", str_val);
// Test basic string escapes
root = ParseJSON("\" \\\"\\\\\\/\\b\\f\\n\\r\\t\\v\"");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeString, root->GetType());
EXPECT_TRUE(root->AsString(&str_val));
EXPECT_EQ(" \"\\/\b\f\n\r\t\v", str_val);
// Test hex and unicode escapes including the null character.
root = ParseJSON("\"\\x41\\x00\\u1234\"", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 4, Invalid escape sequence.", error.message);
// Test invalid strings
root = ParseJSON("\"no closing quote", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 18, Syntax error.", error.message);
root = ParseJSON("\"\\z invalid escape char\"", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 4, Invalid escape sequence.", error.message);
root = ParseJSON("\"not enough escape chars\\u123\"", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 27, Invalid escape sequence.", error.message);
root = ParseJSON("\"extra backslash at end of input\\\"", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 35, Syntax error.", error.message);
root = ParseJSON("\"a\"extra data", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
error.message);
// Bare control characters (including newlines) are not permitted in string
// literals.
root = ParseJSON("\"\n\"", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
root = ParseJSON("[\"\n\"]", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
root = ParseJSON("{\"\n\": true}", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
root = ParseJSON("{\"key\": \"\n\"}", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 11, Syntax error.", error.message);
root = ParseJSON("\"\x1b\"", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
root = ParseJSON("[\"\x07\"]", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
root = ParseJSON("{\"\x09\": true}", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
root = ParseJSON("{\"key\": \"\x01\"}", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 11, Syntax error.", error.message);
// Basic array
root = ParseJSON("[true, false, null]");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeArray, root->GetType());
list = JSONArray::Cast(root.get());
ASSERT_TRUE(list);
EXPECT_EQ(3U, list->size());
// Empty array
root = ParseJSON("[]");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeArray, root->GetType());
list = JSONArray::Cast(root.get());
ASSERT_TRUE(list);
EXPECT_EQ(0U, list->size());
// Nested arrays
root = ParseJSON("[[true], [], [false, [], [null]], null]");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeArray, root->GetType());
list = JSONArray::Cast(root.get());
ASSERT_TRUE(list);
EXPECT_EQ(4U, list->size());
// Invalid, missing close brace.
root = ParseJSON("[[true], [], [false, [], [null]], null", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 39, Syntax error.", error.message);
// Invalid, too many commas
root = ParseJSON("[true,, null]", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);
// Invalid, no commas
root = ParseJSON("[true null]", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);
// Invalid, trailing comma
root = ParseJSON("[true,]", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);
root = ParseJSON("[true]");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeArray, root->GetType());
list = JSONArray::Cast(root.get());
ASSERT_TRUE(list);
EXPECT_EQ(1U, list->size());
tmp_value = list->at(0);
ASSERT_TRUE(tmp_value);
EXPECT_EQ(JSONValue::kTypeBoolean, tmp_value->GetType());
bool bool_value = false;
EXPECT_TRUE(tmp_value->AsBoolean(&bool_value));
EXPECT_TRUE(bool_value);
// Don't allow empty elements.
root = ParseJSON("[,]", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 2, Unexpected token.", error.message);
root = ParseJSON("[true,,]", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);
root = ParseJSON("[,true,]", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 2, Unexpected token.", error.message);
root = ParseJSON("[true,,false]", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);
// Test objects
root = ParseJSON("{}");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeObject, root->GetType());
root = ParseJSON("{\"number\":9.87654321, \"null\":null , \"S\" : \"str\" }");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeObject, root->GetType());
JSONObject* object_val = JSONObject::Cast(root.get());
ASSERT_TRUE(object_val);
double_val = 0.0;
EXPECT_TRUE(object_val->GetDouble("number", &double_val));
EXPECT_DOUBLE_EQ(9.87654321, double_val);
JSONValue* null_val = object_val->Get("null");
ASSERT_TRUE(null_val);
EXPECT_EQ(JSONValue::kTypeNull, null_val->GetType());
EXPECT_TRUE(object_val->GetString("S", &str_val));
EXPECT_EQ("str", str_val);
// Test newline equivalence.
root2 = ParseJSON(
"{\n"
" \"number\":9.87654321,\n"
" \"null\":null,\n"
" \"S\":\"str\"\n"
"}\n");
ASSERT_TRUE(root2.get());
EXPECT_EQ(root->ToJSONString(), root2->ToJSONString());
root2 = ParseJSON(
"{\r\n"
" \"number\":9.87654321,\r\n"
" \"null\":null,\r\n"
" \"S\":\"str\"\r\n"
"}\r\n");
ASSERT_TRUE(root2.get());
EXPECT_EQ(root->ToJSONString(), root2->ToJSONString());
// Test that allowed whitespace is limited to TAB, CR, LF and SP. There are
// several other Unicode characters defined as whitespace, so a selection of
// them are tested to ensure that they are not allowed.
// U+0009 CHARACTER TABULATION is allowed
root = ParseJSON("\t{\t\"key\"\t:\t[\t\"value1\"\t,\t\"value2\"\t]\t}\t");
ASSERT_TRUE(root.get());
// U+000A LINE FEED is allowed
root = ParseJSON("\n{\n\"key\"\n:\n[\n\"value1\"\n,\n\"value2\"\n]\n}\n");
ASSERT_TRUE(root.get());
// U+000D CARRIAGE RETURN is allowed
root = ParseJSON("\r{\r\"key\"\r:\r[\r\"value1\"\r,\r\"value2\"\r]\r}\r");
ASSERT_TRUE(root.get());
// U+0020 SPACE is allowed
root = ParseJSON(" { \"key\" : [ \"value1\" , \"value2\" ] } ");
ASSERT_TRUE(root.get());
// U+000B LINE TABULATION is not allowed
root = ParseJSON("[\x0b\"value\"]");
ASSERT_FALSE(root.get());
// U+00A0 NO-BREAK SPACE is not allowed
UChar invalid_space_1[] = {0x5b, 0x00a0, 0x5d}; // [<U+00A0>]
root = ParseJSON(String(invalid_space_1, base::size(invalid_space_1)));
ASSERT_FALSE(root.get());
// U+3000 IDEOGRAPHIC SPACE is not allowed
UChar invalid_space_2[] = {0x5b, 0x3000, 0x5d}; // [<U+3000>]
root = ParseJSON(String(invalid_space_2, base::size(invalid_space_2)));
ASSERT_FALSE(root.get());
// Test nesting
root = ParseJSON("{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeObject, root->GetType());
object_val = JSONObject::Cast(root.get());
ASSERT_TRUE(object_val);
JSONObject* inner_object = object_val->GetJSONObject("inner");
ASSERT_TRUE(inner_object);
JSONArray* inner_array = inner_object->GetArray("array");
ASSERT_TRUE(inner_array);
EXPECT_EQ(1U, inner_array->size());
bool_value = true;
EXPECT_TRUE(object_val->GetBoolean("false", &bool_value));
EXPECT_FALSE(bool_value);
inner_object = object_val->GetJSONObject("d");
EXPECT_TRUE(inner_object);
// Test keys with periods
root = ParseJSON("{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeObject, root->GetType());
object_val = JSONObject::Cast(root.get());
ASSERT_TRUE(object_val);
int integer_value = 0;
EXPECT_TRUE(object_val->GetInteger("a.b", &integer_value));
EXPECT_EQ(3, integer_value);
EXPECT_TRUE(object_val->GetInteger("c", &integer_value));
EXPECT_EQ(2, integer_value);
inner_object = object_val->GetJSONObject("d.e.f");
ASSERT_TRUE(inner_object);
EXPECT_EQ(1U, inner_object->size());
EXPECT_TRUE(inner_object->GetInteger("g.h.i.j", &integer_value));
EXPECT_EQ(1, integer_value);
root = ParseJSON("{\"a\":{\"b\":2},\"a.b\":1}");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeObject, root->GetType());
object_val = JSONObject::Cast(root.get());
ASSERT_TRUE(object_val);
inner_object = object_val->GetJSONObject("a");
ASSERT_TRUE(inner_object);
EXPECT_TRUE(inner_object->GetInteger("b", &integer_value));
EXPECT_EQ(2, integer_value);
EXPECT_TRUE(object_val->GetInteger("a.b", &integer_value));
EXPECT_EQ(1, integer_value);
// Invalid, no closing brace
root = ParseJSON("{\"a\": true");
EXPECT_FALSE(root.get());
// Invalid, keys must be quoted
root = ParseJSON("{foo:true}", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 2, Syntax error.", error.message);
// Invalid, trailing comma
root = ParseJSON("{\"a\":true,}", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 11, Unexpected token.", error.message);
// Invalid, too many commas
root = ParseJSON("{\"a\":true,,\"b\":false}", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 11, Unexpected token.", error.message);
// Invalid, no separator
root = ParseJSON("{\"a\" \"b\"}", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 6, Unexpected token.", error.message);
// Invalid, lone comma.
root = ParseJSON("{,}", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 2, Unexpected token.", error.message);
root = ParseJSON("{\"a\":true,,}", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 11, Unexpected token.", error.message);
root = ParseJSON("{,\"a\":true}", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 2, Unexpected token.", error.message);
root = ParseJSON("{\"a\":true,,\"b\":false}", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 11, Unexpected token.", error.message);
// Test stack overflow
StringBuilder evil;
evil.ReserveCapacity(2000000);
for (int i = 0; i < 1000000; ++i)
evil.Append('[');
for (int i = 0; i < 1000000; ++i)
evil.Append(']');
root = ParseJSON(evil.ToString(), &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 1001, Too much nesting.", error.message);
// A few thousand adjacent lists is fine.
StringBuilder not_evil;
not_evil.ReserveCapacity(15010);
not_evil.Append('[');
for (int i = 0; i < 5000; ++i)
not_evil.Append("[],");
not_evil.Append("[]]");
root = ParseJSON(not_evil.ToString());
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeArray, root->GetType());
list = JSONArray::Cast(root.get());
ASSERT_TRUE(list);
EXPECT_EQ(5001U, list->size());
// Test utf8 encoded input
root = ParseJSON("\"\\xe7\\xbd\\x91\\xe9\\xa1\\xb5\"", &error);
ASSERT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 4, Invalid escape sequence.", error.message);
// Test utf16 encoded strings.
root = ParseJSON("\"\\u20ac3,14\"");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeString, root->GetType());
EXPECT_TRUE(root->AsString(&str_val));
UChar tmp2[] = {0x20ac, 0x33, 0x2c, 0x31, 0x34};
EXPECT_EQ(String(tmp2, base::size(tmp2)), str_val);
root = ParseJSON("\"\\ud83d\\udca9\\ud83d\\udc6c\"");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeString, root->GetType());
EXPECT_TRUE(root->AsString(&str_val));
UChar tmp3[] = {0xd83d, 0xdca9, 0xd83d, 0xdc6c};
EXPECT_EQ(String(tmp3, base::size(tmp3)), str_val);
// Invalid unicode in a string literal after applying escape sequences.
root = ParseJSON("\n\n \"\\ud800\"", &error);
EXPECT_FALSE(root.get());
EXPECT_EQ(
"Line: 3, column: 5, Unsupported encoding. JSON and all string literals "
"must contain valid Unicode characters.",
error.message);
// Invalid unicode in a JSON itself.
UChar tmp4[] = {0x22, 0xd800, 0x22}; // "?"
root = ParseJSON(String(tmp4, base::size(tmp4)), &error);
EXPECT_FALSE(root.get());
EXPECT_EQ(
"Line: 1, column: 1, Unsupported encoding. JSON and all string literals "
"must contain valid Unicode characters.",
error.message);
// Invalid unicode in a JSON itself.
UChar tmp5[] = {0x7b, 0x22, 0xd800, 0x22, 0x3a, 0x31, 0x7d}; // {"?":1}
root = ParseJSON(String(tmp5, base::size(tmp5)), &error);
EXPECT_FALSE(root.get());
EXPECT_EQ(
"Line: 1, column: 2, Unsupported encoding. JSON and all string literals "
"must contain valid Unicode characters.",
error.message);
// Test literal root objects.
root = ParseJSON("null");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeNull, root->GetType());
root = ParseJSON("true");
ASSERT_TRUE(root.get());
EXPECT_TRUE(root->AsBoolean(&bool_value));
EXPECT_TRUE(bool_value);
root = ParseJSON("10");
ASSERT_TRUE(root.get());
EXPECT_TRUE(root->AsInteger(&integer_value));
EXPECT_EQ(10, integer_value);
root = ParseJSON("\"root\"");
ASSERT_TRUE(root.get());
EXPECT_TRUE(root->AsString(&str_val));
EXPECT_EQ("root", str_val);
}
TEST(JSONParserTest, InvalidSanity) {
const char* const kInvalidJson[] = {
"/* test *", "{\"foo\"", "{\"foo\":", " [", "\"\\u123g\"", "{\n\"eh:\n}",
"////", "*/**/", "/**/", "/*/", "//**/", "\"\\"};
for (size_t i = 0; i < base::size(kInvalidJson); ++i) {
std::unique_ptr<JSONValue> result = ParseJSON(kInvalidJson[i]);
EXPECT_FALSE(result.get());
}
}
// Test that the nesting depth can be limited to values less than 1000, but
// cannot be extended past that maximum.
TEST(JSONParserTest, LimitedDepth) {
std::unique_ptr<JSONValue> root;
JSONParseError error;
// Test cases. Each pair is a JSON string, and the minimum depth required
// to successfully parse that string.
Vector<std::pair<const char*, int>> test_cases = {
{"[[[[[]]]]]", 5},
{"[[[[[\"a\"]]]]]", 6},
{"[[],[],[],[],[]]", 2},
{"{\"a\":{\"a\":{\"a\":{\"a\":{\"a\": \"a\"}}}}}", 6},
{"\"root\"", 1}};
for (const auto& test_case : test_cases) {
// Each test case should parse successfully at the default depth
root = ParseJSON(test_case.first);
EXPECT_TRUE(root.get());
// ... and should parse successfully at the minimum depth
root = ParseJSON(test_case.first, test_case.second);
EXPECT_TRUE(root.get());
// ... but should fail to parse at a shallower depth.
root = ParseJSON(test_case.first, test_case.second - 1);
EXPECT_FALSE(root.get());
}
// Test that everything fails to parse with depth 0
root = ParseJSON("", 0, &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
root = ParseJSON("", -1, &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
root = ParseJSON("true", 0, &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 1, Too much nesting.", error.message);
// Test that the limit can be set to the constant maximum.
StringBuilder evil;
evil.ReserveCapacity(2002);
for (int i = 0; i < 1000; ++i)
evil.Append('[');
for (int i = 0; i < 1000; ++i)
evil.Append(']');
root = ParseJSON(evil.ToString());
EXPECT_TRUE(root.get());
root = ParseJSON(evil.ToString(), 1000);
EXPECT_TRUE(root.get());
// Test that the limit cannot be set higher than the constant maximum.
evil.Clear();
for (int i = 0; i < 1001; ++i)
evil.Append('[');
for (int i = 0; i < 1001; ++i)
evil.Append(']');
root = ParseJSON(evil.ToString(), &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 1001, Too much nesting.", error.message);
root = ParseJSON(evil.ToString(), 1001, &error);
EXPECT_FALSE(root.get());
EXPECT_EQ("Line: 1, column: 1001, Too much nesting.", error.message);
}
} // namespace blink