json_parser.cc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  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
  3. // found in the LICENSE file.
  4. #include "base/json/json_parser.h"
  5. #include <cmath>
  6. #include <iterator>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/check_op.h"
  10. #include "base/json/json_reader.h"
  11. #include "base/metrics/histogram_functions.h"
  12. #include "base/notreached.h"
  13. #include "base/numerics/safe_conversions.h"
  14. #include "base/ranges/algorithm.h"
  15. #include "base/strings/string_number_conversions.h"
  16. #include "base/strings/string_piece.h"
  17. #include "base/strings/string_util.h"
  18. #include "base/strings/stringprintf.h"
  19. #include "base/strings/utf_string_conversion_utils.h"
  20. #include "base/strings/utf_string_conversions.h"
  21. #include "base/third_party/icu/icu_utf.h"
  22. #include "third_party/abseil-cpp/absl/types/optional.h"
  23. namespace base {
  24. namespace internal {
  25. namespace {
  26. // Values 1000 and above are used by JSONFileValueSerializer::JsonFileError.
  27. static_assert(JSONParser::JSON_PARSE_ERROR_COUNT < 1000,
  28. "JSONParser error out of bounds");
  29. std::string ErrorCodeToString(JSONParser::JsonParseError error_code) {
  30. switch (error_code) {
  31. case JSONParser::JSON_NO_ERROR:
  32. return std::string();
  33. case JSONParser::JSON_SYNTAX_ERROR:
  34. return JSONParser::kSyntaxError;
  35. case JSONParser::JSON_INVALID_ESCAPE:
  36. return JSONParser::kInvalidEscape;
  37. case JSONParser::JSON_UNEXPECTED_TOKEN:
  38. return JSONParser::kUnexpectedToken;
  39. case JSONParser::JSON_TRAILING_COMMA:
  40. return JSONParser::kTrailingComma;
  41. case JSONParser::JSON_TOO_MUCH_NESTING:
  42. return JSONParser::kTooMuchNesting;
  43. case JSONParser::JSON_UNEXPECTED_DATA_AFTER_ROOT:
  44. return JSONParser::kUnexpectedDataAfterRoot;
  45. case JSONParser::JSON_UNSUPPORTED_ENCODING:
  46. return JSONParser::kUnsupportedEncoding;
  47. case JSONParser::JSON_UNQUOTED_DICTIONARY_KEY:
  48. return JSONParser::kUnquotedDictionaryKey;
  49. case JSONParser::JSON_UNREPRESENTABLE_NUMBER:
  50. return JSONParser::kUnrepresentableNumber;
  51. case JSONParser::JSON_PARSE_ERROR_COUNT:
  52. break;
  53. }
  54. NOTREACHED();
  55. return std::string();
  56. }
  57. const int32_t kExtendedASCIIStart = 0x80;
  58. constexpr base_icu::UChar32 kUnicodeReplacementPoint = 0xFFFD;
  59. // UnprefixedHexStringToInt acts like |HexStringToInt|, but enforces that the
  60. // input consists purely of hex digits. I.e. no "0x" nor "OX" prefix is
  61. // permitted.
  62. bool UnprefixedHexStringToInt(StringPiece input, int* output) {
  63. for (size_t i = 0; i < input.size(); i++) {
  64. if (!IsHexDigit(input[i])) {
  65. return false;
  66. }
  67. }
  68. return HexStringToInt(input, output);
  69. }
  70. // These values are persisted to logs. Entries should not be renumbered and
  71. // numeric values should never be reused.
  72. enum class ChromiumJsonExtension {
  73. kCComment,
  74. kCppComment,
  75. kXEscape,
  76. kVerticalTabEscape,
  77. kControlCharacter,
  78. kMaxValue = kControlCharacter,
  79. };
  80. const char kExtensionHistogramName[] =
  81. "Security.JSONParser.ChromiumExtensionUsage";
  82. } // namespace
  83. // This is U+FFFD.
  84. const char kUnicodeReplacementString[] = "\xEF\xBF\xBD";
  85. const char JSONParser::kSyntaxError[] = "Syntax error.";
  86. const char JSONParser::kInvalidEscape[] = "Invalid escape sequence.";
  87. const char JSONParser::kUnexpectedToken[] = "Unexpected token.";
  88. const char JSONParser::kTrailingComma[] = "Trailing comma not allowed.";
  89. const char JSONParser::kTooMuchNesting[] = "Too much nesting.";
  90. const char JSONParser::kUnexpectedDataAfterRoot[] =
  91. "Unexpected data after root element.";
  92. const char JSONParser::kUnsupportedEncoding[] =
  93. "Unsupported encoding. JSON must be UTF-8.";
  94. const char JSONParser::kUnquotedDictionaryKey[] =
  95. "Dictionary keys must be quoted.";
  96. const char JSONParser::kUnrepresentableNumber[] =
  97. "Number cannot be represented.";
  98. JSONParser::JSONParser(int options, size_t max_depth)
  99. : options_(options),
  100. max_depth_(max_depth),
  101. index_(0),
  102. stack_depth_(0),
  103. line_number_(0),
  104. index_last_line_(0),
  105. error_code_(JSON_NO_ERROR),
  106. error_line_(0),
  107. error_column_(0) {
  108. CHECK_LE(max_depth, kAbsoluteMaxDepth);
  109. }
  110. JSONParser::~JSONParser() = default;
  111. absl::optional<Value> JSONParser::Parse(StringPiece input) {
  112. input_ = input;
  113. index_ = 0;
  114. // Line and column counting is 1-based, but |index_| is 0-based. For example,
  115. // if input is "Aaa\nB" then 'A' and 'B' are both in column 1 (at lines 1 and
  116. // 2) and have indexes of 0 and 4. We track the line number explicitly (the
  117. // |line_number_| field) and the column number implicitly (the difference
  118. // between |index_| and |index_last_line_|). In calculating that difference,
  119. // |index_last_line_| is the index of the '\r' or '\n', not the index of the
  120. // first byte after the '\n'. For the 'B' in "Aaa\nB", its |index_| and
  121. // |index_last_line_| would be 4 and 3: 'B' is in column (4 - 3) = 1. We
  122. // initialize |index_last_line_| to -1, not 0, since -1 is the (out of range)
  123. // index of the imaginary '\n' immediately before the start of the string:
  124. // 'A' is in column (0 - -1) = 1.
  125. line_number_ = 1;
  126. index_last_line_ = static_cast<size_t>(-1);
  127. error_code_ = JSON_NO_ERROR;
  128. error_line_ = 0;
  129. error_column_ = 0;
  130. // When the input JSON string starts with a UTF-8 Byte-Order-Mark,
  131. // advance the start position to avoid the ParseNextToken function mis-
  132. // treating a Unicode BOM as an invalid character and returning NULL.
  133. ConsumeIfMatch("\xEF\xBB\xBF");
  134. // Parse the first and any nested tokens.
  135. absl::optional<Value> root(ParseNextToken());
  136. if (!root)
  137. return absl::nullopt;
  138. // Make sure the input stream is at an end.
  139. if (GetNextToken() != T_END_OF_INPUT) {
  140. ReportError(JSON_UNEXPECTED_DATA_AFTER_ROOT, 0);
  141. return absl::nullopt;
  142. }
  143. return root;
  144. }
  145. JSONParser::JsonParseError JSONParser::error_code() const {
  146. return error_code_;
  147. }
  148. std::string JSONParser::GetErrorMessage() const {
  149. return FormatErrorMessage(error_line_, error_column_,
  150. ErrorCodeToString(error_code_));
  151. }
  152. int JSONParser::error_line() const {
  153. return error_line_;
  154. }
  155. int JSONParser::error_column() const {
  156. return error_column_;
  157. }
  158. // StringBuilder ///////////////////////////////////////////////////////////////
  159. JSONParser::StringBuilder::StringBuilder() : StringBuilder(nullptr) {}
  160. JSONParser::StringBuilder::StringBuilder(const char* pos)
  161. : pos_(pos), length_(0) {}
  162. JSONParser::StringBuilder::~StringBuilder() = default;
  163. JSONParser::StringBuilder& JSONParser::StringBuilder::operator=(
  164. StringBuilder&& other) = default;
  165. void JSONParser::StringBuilder::Append(base_icu::UChar32 point) {
  166. DCHECK(IsValidCodepoint(point));
  167. if (point < kExtendedASCIIStart && !string_) {
  168. DCHECK_EQ(static_cast<char>(point), pos_[length_]);
  169. ++length_;
  170. } else {
  171. Convert();
  172. if (UNLIKELY(point == kUnicodeReplacementPoint)) {
  173. string_->append(kUnicodeReplacementString);
  174. } else {
  175. WriteUnicodeCharacter(point, &*string_);
  176. }
  177. }
  178. }
  179. void JSONParser::StringBuilder::Convert() {
  180. if (string_)
  181. return;
  182. string_.emplace(pos_, length_);
  183. }
  184. std::string JSONParser::StringBuilder::DestructiveAsString() {
  185. if (string_)
  186. return std::move(*string_);
  187. return std::string(pos_, length_);
  188. }
  189. // JSONParser private //////////////////////////////////////////////////////////
  190. absl::optional<StringPiece> JSONParser::PeekChars(size_t count) {
  191. if (index_ + count > input_.length())
  192. return absl::nullopt;
  193. // Using StringPiece::substr() is significantly slower (according to
  194. // base_perftests) than constructing a substring manually.
  195. return StringPiece(input_.data() + index_, count);
  196. }
  197. absl::optional<char> JSONParser::PeekChar() {
  198. absl::optional<StringPiece> chars = PeekChars(1);
  199. if (chars)
  200. return (*chars)[0];
  201. return absl::nullopt;
  202. }
  203. absl::optional<StringPiece> JSONParser::ConsumeChars(size_t count) {
  204. absl::optional<StringPiece> chars = PeekChars(count);
  205. if (chars)
  206. index_ += count;
  207. return chars;
  208. }
  209. absl::optional<char> JSONParser::ConsumeChar() {
  210. absl::optional<StringPiece> chars = ConsumeChars(1);
  211. if (chars)
  212. return (*chars)[0];
  213. return absl::nullopt;
  214. }
  215. const char* JSONParser::pos() {
  216. CHECK_LE(index_, input_.length());
  217. return input_.data() + index_;
  218. }
  219. JSONParser::Token JSONParser::GetNextToken() {
  220. EatWhitespaceAndComments();
  221. absl::optional<char> c = PeekChar();
  222. if (!c)
  223. return T_END_OF_INPUT;
  224. switch (*c) {
  225. case '{':
  226. return T_OBJECT_BEGIN;
  227. case '}':
  228. return T_OBJECT_END;
  229. case '[':
  230. return T_ARRAY_BEGIN;
  231. case ']':
  232. return T_ARRAY_END;
  233. case '"':
  234. return T_STRING;
  235. case '0':
  236. case '1':
  237. case '2':
  238. case '3':
  239. case '4':
  240. case '5':
  241. case '6':
  242. case '7':
  243. case '8':
  244. case '9':
  245. case '-':
  246. return T_NUMBER;
  247. case 't':
  248. return T_BOOL_TRUE;
  249. case 'f':
  250. return T_BOOL_FALSE;
  251. case 'n':
  252. return T_NULL;
  253. case ',':
  254. return T_LIST_SEPARATOR;
  255. case ':':
  256. return T_OBJECT_PAIR_SEPARATOR;
  257. default:
  258. return T_INVALID_TOKEN;
  259. }
  260. }
  261. void JSONParser::EatWhitespaceAndComments() {
  262. while (absl::optional<char> c = PeekChar()) {
  263. switch (*c) {
  264. case '\r':
  265. case '\n':
  266. index_last_line_ = index_;
  267. // Don't increment line_number_ twice for "\r\n".
  268. if (!(c == '\n' && index_ > 0 && input_[index_ - 1] == '\r')) {
  269. ++line_number_;
  270. }
  271. [[fallthrough]];
  272. case ' ':
  273. case '\t':
  274. ConsumeChar();
  275. break;
  276. case '/':
  277. if (!EatComment())
  278. return;
  279. break;
  280. default:
  281. return;
  282. }
  283. }
  284. }
  285. bool JSONParser::EatComment() {
  286. absl::optional<StringPiece> comment_start = PeekChars(2);
  287. if (!comment_start)
  288. return false;
  289. const bool comments_allowed = options_ & JSON_ALLOW_COMMENTS;
  290. if (comment_start == "//") {
  291. UmaHistogramEnumeration(kExtensionHistogramName,
  292. ChromiumJsonExtension::kCppComment);
  293. if (!comments_allowed) {
  294. ReportError(JSON_UNEXPECTED_TOKEN, 0);
  295. return false;
  296. }
  297. ConsumeChars(2);
  298. // Single line comment, read to newline.
  299. while (absl::optional<char> c = PeekChar()) {
  300. if (c == '\n' || c == '\r')
  301. return true;
  302. ConsumeChar();
  303. }
  304. } else if (comment_start == "/*") {
  305. UmaHistogramEnumeration(kExtensionHistogramName,
  306. ChromiumJsonExtension::kCComment);
  307. if (!comments_allowed) {
  308. ReportError(JSON_UNEXPECTED_TOKEN, 0);
  309. return false;
  310. }
  311. ConsumeChars(2);
  312. char previous_char = '\0';
  313. // Block comment, read until end marker.
  314. while (absl::optional<char> c = PeekChar()) {
  315. if (previous_char == '*' && c == '/') {
  316. // EatWhitespaceAndComments will inspect pos(), which will still be on
  317. // the last / of the comment, so advance once more (which may also be
  318. // end of input).
  319. ConsumeChar();
  320. return true;
  321. }
  322. previous_char = *ConsumeChar();
  323. }
  324. // If the comment is unterminated, GetNextToken will report T_END_OF_INPUT.
  325. }
  326. return false;
  327. }
  328. absl::optional<Value> JSONParser::ParseNextToken() {
  329. return ParseToken(GetNextToken());
  330. }
  331. absl::optional<Value> JSONParser::ParseToken(Token token) {
  332. switch (token) {
  333. case T_OBJECT_BEGIN:
  334. return ConsumeDictionary();
  335. case T_ARRAY_BEGIN:
  336. return ConsumeList();
  337. case T_STRING:
  338. return ConsumeString();
  339. case T_NUMBER:
  340. return ConsumeNumber();
  341. case T_BOOL_TRUE:
  342. case T_BOOL_FALSE:
  343. case T_NULL:
  344. return ConsumeLiteral();
  345. default:
  346. ReportError(JSON_UNEXPECTED_TOKEN, 0);
  347. return absl::nullopt;
  348. }
  349. }
  350. absl::optional<Value> JSONParser::ConsumeDictionary() {
  351. if (ConsumeChar() != '{') {
  352. ReportError(JSON_UNEXPECTED_TOKEN, 0);
  353. return absl::nullopt;
  354. }
  355. StackMarker depth_check(max_depth_, &stack_depth_);
  356. if (depth_check.IsTooDeep()) {
  357. ReportError(JSON_TOO_MUCH_NESTING, -1);
  358. return absl::nullopt;
  359. }
  360. std::vector<std::pair<std::string, Value>> values;
  361. Token token = GetNextToken();
  362. while (token != T_OBJECT_END) {
  363. if (token != T_STRING) {
  364. ReportError(JSON_UNQUOTED_DICTIONARY_KEY, 0);
  365. return absl::nullopt;
  366. }
  367. // First consume the key.
  368. StringBuilder key;
  369. if (!ConsumeStringRaw(&key)) {
  370. return absl::nullopt;
  371. }
  372. // Read the separator.
  373. token = GetNextToken();
  374. if (token != T_OBJECT_PAIR_SEPARATOR) {
  375. ReportError(JSON_SYNTAX_ERROR, 0);
  376. return absl::nullopt;
  377. }
  378. // The next token is the value. Ownership transfers to |dict|.
  379. ConsumeChar();
  380. absl::optional<Value> value = ParseNextToken();
  381. if (!value) {
  382. // ReportError from deeper level.
  383. return absl::nullopt;
  384. }
  385. values.emplace_back(key.DestructiveAsString(), std::move(*value));
  386. token = GetNextToken();
  387. if (token == T_LIST_SEPARATOR) {
  388. ConsumeChar();
  389. token = GetNextToken();
  390. if (token == T_OBJECT_END && !(options_ & JSON_ALLOW_TRAILING_COMMAS)) {
  391. ReportError(JSON_TRAILING_COMMA, 0);
  392. return absl::nullopt;
  393. }
  394. } else if (token != T_OBJECT_END) {
  395. ReportError(JSON_SYNTAX_ERROR, 0);
  396. return absl::nullopt;
  397. }
  398. }
  399. ConsumeChar(); // Closing '}'.
  400. // Reverse |dict_storage| to keep the last of elements with the same key in
  401. // the input.
  402. ranges::reverse(values);
  403. return Value(Value::Dict(std::make_move_iterator(values.begin()),
  404. std::make_move_iterator(values.end())));
  405. }
  406. absl::optional<Value> JSONParser::ConsumeList() {
  407. if (ConsumeChar() != '[') {
  408. ReportError(JSON_UNEXPECTED_TOKEN, 0);
  409. return absl::nullopt;
  410. }
  411. StackMarker depth_check(max_depth_, &stack_depth_);
  412. if (depth_check.IsTooDeep()) {
  413. ReportError(JSON_TOO_MUCH_NESTING, -1);
  414. return absl::nullopt;
  415. }
  416. Value::List list;
  417. Token token = GetNextToken();
  418. while (token != T_ARRAY_END) {
  419. absl::optional<Value> item = ParseToken(token);
  420. if (!item) {
  421. // ReportError from deeper level.
  422. return absl::nullopt;
  423. }
  424. list.Append(std::move(*item));
  425. token = GetNextToken();
  426. if (token == T_LIST_SEPARATOR) {
  427. ConsumeChar();
  428. token = GetNextToken();
  429. if (token == T_ARRAY_END && !(options_ & JSON_ALLOW_TRAILING_COMMAS)) {
  430. ReportError(JSON_TRAILING_COMMA, 0);
  431. return absl::nullopt;
  432. }
  433. } else if (token != T_ARRAY_END) {
  434. ReportError(JSON_SYNTAX_ERROR, 0);
  435. return absl::nullopt;
  436. }
  437. }
  438. ConsumeChar(); // Closing ']'.
  439. return Value(std::move(list));
  440. }
  441. absl::optional<Value> JSONParser::ConsumeString() {
  442. StringBuilder string;
  443. if (!ConsumeStringRaw(&string))
  444. return absl::nullopt;
  445. return Value(string.DestructiveAsString());
  446. }
  447. bool JSONParser::ConsumeStringRaw(StringBuilder* out) {
  448. if (ConsumeChar() != '"') {
  449. ReportError(JSON_UNEXPECTED_TOKEN, 0);
  450. return false;
  451. }
  452. // StringBuilder will internally build a StringPiece unless a UTF-16
  453. // conversion occurs, at which point it will perform a copy into a
  454. // std::string.
  455. StringBuilder string(pos());
  456. while (PeekChar()) {
  457. base_icu::UChar32 next_char = 0;
  458. if (!ReadUnicodeCharacter(input_.data(), input_.length(), &index_,
  459. &next_char) ||
  460. !IsValidCodepoint(next_char)) {
  461. if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) {
  462. ReportError(JSON_UNSUPPORTED_ENCODING, 0);
  463. return false;
  464. }
  465. ConsumeChar();
  466. string.Append(kUnicodeReplacementPoint);
  467. continue;
  468. }
  469. if (next_char == '"') {
  470. ConsumeChar();
  471. *out = std::move(string);
  472. return true;
  473. }
  474. if (next_char != '\\') {
  475. // Per Section 7, "All Unicode characters may be placed within the
  476. // quotation marks, except for the characters that MUST be escaped:
  477. // quotation mark, reverse solidus, and the control characters (U+0000
  478. // through U+001F)".
  479. if (next_char <= 0x1F) {
  480. UmaHistogramEnumeration(kExtensionHistogramName,
  481. ChromiumJsonExtension::kControlCharacter);
  482. if (!(options_ & JSON_ALLOW_CONTROL_CHARS)) {
  483. ReportError(JSON_UNSUPPORTED_ENCODING, -1);
  484. return false;
  485. }
  486. }
  487. // If this character is not an escape sequence, track any line breaks and
  488. // copy next_char to the StringBuilder. The JSON spec forbids unescaped
  489. // ASCII control characters within a string, including '\r' and '\n', but
  490. // this implementation is more lenient.
  491. if ((next_char == '\r') || (next_char == '\n')) {
  492. index_last_line_ = index_;
  493. // Don't increment line_number_ twice for "\r\n". We are guaranteed
  494. // that (index_ > 0) because we are consuming a string, so we must have
  495. // seen an opening '"' quote character.
  496. if ((next_char == '\r') || (input_[index_ - 1] != '\r')) {
  497. ++line_number_;
  498. }
  499. }
  500. ConsumeChar();
  501. string.Append(next_char);
  502. } else {
  503. // And if it is an escape sequence, the input string will be adjusted
  504. // (either by combining the two characters of an encoded escape sequence,
  505. // or with a UTF conversion), so using StringPiece isn't possible -- force
  506. // a conversion.
  507. string.Convert();
  508. // Read past the escape '\' and ensure there's a character following.
  509. absl::optional<StringPiece> escape_sequence = ConsumeChars(2);
  510. if (!escape_sequence) {
  511. ReportError(JSON_INVALID_ESCAPE, -1);
  512. return false;
  513. }
  514. switch ((*escape_sequence)[1]) {
  515. // Allowed esape sequences:
  516. case 'x': { // UTF-8 sequence.
  517. // UTF-8 \x escape sequences are not allowed in the spec, but they
  518. // are supported here for backwards-compatiblity with the old parser.
  519. UmaHistogramEnumeration(kExtensionHistogramName,
  520. ChromiumJsonExtension::kXEscape);
  521. if (!(options_ & JSON_ALLOW_X_ESCAPES)) {
  522. ReportError(JSON_INVALID_ESCAPE, -1);
  523. return false;
  524. }
  525. escape_sequence = ConsumeChars(2);
  526. if (!escape_sequence) {
  527. ReportError(JSON_INVALID_ESCAPE, -3);
  528. return false;
  529. }
  530. int hex_digit = 0;
  531. if (!UnprefixedHexStringToInt(*escape_sequence, &hex_digit) ||
  532. !IsValidCharacter(hex_digit)) {
  533. ReportError(JSON_INVALID_ESCAPE, -3);
  534. return false;
  535. }
  536. string.Append(hex_digit);
  537. break;
  538. }
  539. case 'u': { // UTF-16 sequence.
  540. // UTF units are of the form \uXXXX.
  541. base_icu::UChar32 code_point;
  542. if (!DecodeUTF16(&code_point)) {
  543. ReportError(JSON_INVALID_ESCAPE, -1);
  544. return false;
  545. }
  546. string.Append(code_point);
  547. break;
  548. }
  549. case '"':
  550. string.Append('"');
  551. break;
  552. case '\\':
  553. string.Append('\\');
  554. break;
  555. case '/':
  556. string.Append('/');
  557. break;
  558. case 'b':
  559. string.Append('\b');
  560. break;
  561. case 'f':
  562. string.Append('\f');
  563. break;
  564. case 'n':
  565. string.Append('\n');
  566. break;
  567. case 'r':
  568. string.Append('\r');
  569. break;
  570. case 't':
  571. string.Append('\t');
  572. break;
  573. case 'v': // Not listed as valid escape sequence in the RFC.
  574. UmaHistogramEnumeration(kExtensionHistogramName,
  575. ChromiumJsonExtension::kVerticalTabEscape);
  576. if (!(options_ & JSON_ALLOW_VERT_TAB)) {
  577. ReportError(JSON_INVALID_ESCAPE, -1);
  578. return false;
  579. }
  580. string.Append('\v');
  581. break;
  582. // All other escape squences are illegal.
  583. default:
  584. ReportError(JSON_INVALID_ESCAPE, -1);
  585. return false;
  586. }
  587. }
  588. }
  589. ReportError(JSON_SYNTAX_ERROR, -1);
  590. return false;
  591. }
  592. // Entry is at the first X in \uXXXX.
  593. bool JSONParser::DecodeUTF16(base_icu::UChar32* out_code_point) {
  594. absl::optional<StringPiece> escape_sequence = ConsumeChars(4);
  595. if (!escape_sequence)
  596. return false;
  597. // Consume the UTF-16 code unit, which may be a high surrogate.
  598. int code_unit16_high = 0;
  599. if (!UnprefixedHexStringToInt(*escape_sequence, &code_unit16_high))
  600. return false;
  601. // If this is a high surrogate, consume the next code unit to get the
  602. // low surrogate.
  603. if (CBU16_IS_SURROGATE(code_unit16_high)) {
  604. // Make sure this is the high surrogate.
  605. if (!CBU16_IS_SURROGATE_LEAD(code_unit16_high)) {
  606. if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0)
  607. return false;
  608. *out_code_point = kUnicodeReplacementPoint;
  609. return true;
  610. }
  611. // Make sure that the token has more characters to consume the
  612. // lower surrogate.
  613. if (!ConsumeIfMatch("\\u")) {
  614. if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0)
  615. return false;
  616. *out_code_point = kUnicodeReplacementPoint;
  617. return true;
  618. }
  619. escape_sequence = ConsumeChars(4);
  620. if (!escape_sequence)
  621. return false;
  622. int code_unit16_low = 0;
  623. if (!UnprefixedHexStringToInt(*escape_sequence, &code_unit16_low))
  624. return false;
  625. if (!CBU16_IS_TRAIL(code_unit16_low)) {
  626. if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0)
  627. return false;
  628. *out_code_point = kUnicodeReplacementPoint;
  629. return true;
  630. }
  631. base_icu::UChar32 code_point =
  632. CBU16_GET_SUPPLEMENTARY(code_unit16_high, code_unit16_low);
  633. *out_code_point = code_point;
  634. } else {
  635. // Not a surrogate.
  636. DCHECK(CBU16_IS_SINGLE(code_unit16_high));
  637. *out_code_point = code_unit16_high;
  638. }
  639. return true;
  640. }
  641. absl::optional<Value> JSONParser::ConsumeNumber() {
  642. const char* num_start = pos();
  643. const size_t start_index = index_;
  644. size_t end_index = start_index;
  645. if (PeekChar() == '-')
  646. ConsumeChar();
  647. if (!ReadInt(false)) {
  648. ReportError(JSON_SYNTAX_ERROR, 0);
  649. return absl::nullopt;
  650. }
  651. end_index = index_;
  652. // The optional fraction part.
  653. if (PeekChar() == '.') {
  654. ConsumeChar();
  655. if (!ReadInt(true)) {
  656. ReportError(JSON_SYNTAX_ERROR, 0);
  657. return absl::nullopt;
  658. }
  659. end_index = index_;
  660. }
  661. // Optional exponent part.
  662. absl::optional<char> c = PeekChar();
  663. if (c == 'e' || c == 'E') {
  664. ConsumeChar();
  665. if (PeekChar() == '-' || PeekChar() == '+') {
  666. ConsumeChar();
  667. }
  668. if (!ReadInt(true)) {
  669. ReportError(JSON_SYNTAX_ERROR, 0);
  670. return absl::nullopt;
  671. }
  672. end_index = index_;
  673. }
  674. // ReadInt is greedy because numbers have no easily detectable sentinel,
  675. // so save off where the parser should be on exit (see Consume invariant at
  676. // the top of the header), then make sure the next token is one which is
  677. // valid.
  678. size_t exit_index = index_;
  679. switch (GetNextToken()) {
  680. case T_OBJECT_END:
  681. case T_ARRAY_END:
  682. case T_LIST_SEPARATOR:
  683. case T_END_OF_INPUT:
  684. break;
  685. default:
  686. ReportError(JSON_SYNTAX_ERROR, 0);
  687. return absl::nullopt;
  688. }
  689. index_ = exit_index;
  690. StringPiece num_string(num_start, end_index - start_index);
  691. int num_int;
  692. if (StringToInt(num_string, &num_int))
  693. return Value(num_int);
  694. double num_double;
  695. if (StringToDouble(num_string, &num_double) && std::isfinite(num_double)) {
  696. return Value(num_double);
  697. }
  698. ReportError(JSON_UNREPRESENTABLE_NUMBER, 0);
  699. return absl::nullopt;
  700. }
  701. bool JSONParser::ReadInt(bool allow_leading_zeros) {
  702. size_t len = 0;
  703. char first = 0;
  704. while (absl::optional<char> c = PeekChar()) {
  705. if (!IsAsciiDigit(c))
  706. break;
  707. if (len == 0)
  708. first = *c;
  709. ++len;
  710. ConsumeChar();
  711. }
  712. if (len == 0)
  713. return false;
  714. if (!allow_leading_zeros && len > 1 && first == '0')
  715. return false;
  716. return true;
  717. }
  718. absl::optional<Value> JSONParser::ConsumeLiteral() {
  719. if (ConsumeIfMatch("true"))
  720. return Value(true);
  721. if (ConsumeIfMatch("false"))
  722. return Value(false);
  723. if (ConsumeIfMatch("null"))
  724. return Value(Value::Type::NONE);
  725. ReportError(JSON_SYNTAX_ERROR, 0);
  726. return absl::nullopt;
  727. }
  728. bool JSONParser::ConsumeIfMatch(StringPiece match) {
  729. if (match == PeekChars(match.size())) {
  730. ConsumeChars(match.size());
  731. return true;
  732. }
  733. return false;
  734. }
  735. void JSONParser::ReportError(JsonParseError code, int column_adjust) {
  736. error_code_ = code;
  737. error_line_ = line_number_;
  738. error_column_ = static_cast<int>(index_ - index_last_line_) + column_adjust;
  739. // For a final blank line ('\n' and then EOF), a negative column_adjust may
  740. // put us below 1, which doesn't really make sense for 1-based columns.
  741. if (error_column_ < 1) {
  742. error_column_ = 1;
  743. }
  744. }
  745. // static
  746. std::string JSONParser::FormatErrorMessage(int line, int column,
  747. const std::string& description) {
  748. if (line || column) {
  749. return StringPrintf("Line: %i, column: %i, %s",
  750. line, column, description.c_str());
  751. }
  752. return description;
  753. }
  754. } // namespace internal
  755. } // namespace base