| Index: third_party/protobuf/src/google/protobuf/util/internal/json_stream_parser.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/util/internal/json_stream_parser.cc b/third_party/protobuf/src/google/protobuf/util/internal/json_stream_parser.cc
|
| index df916751386848cb27cac043b9f97651c0a9dc85..39be7b03900ab908816cda7e01a53cadae8e478d 100644
|
| --- a/third_party/protobuf/src/google/protobuf/util/internal/json_stream_parser.cc
|
| +++ b/third_party/protobuf/src/google/protobuf/util/internal/json_stream_parser.cc
|
| @@ -42,8 +42,9 @@
|
|
|
| #include <google/protobuf/stubs/logging.h>
|
| #include <google/protobuf/stubs/common.h>
|
| -#include <google/protobuf/stubs/strutil.h>
|
| #include <google/protobuf/util/internal/object_writer.h>
|
| +#include <google/protobuf/util/internal/json_escaping.h>
|
| +#include <google/protobuf/stubs/strutil.h>
|
|
|
| namespace google {
|
| namespace protobuf {
|
| @@ -59,7 +60,7 @@ using util::error::INVALID_ARGUMENT;
|
|
|
| namespace converter {
|
|
|
| -// Number of digits in a unicode escape sequence (/uXXXX)
|
| +// Number of digits in an escaped UTF-16 code unit ('\\' 'u' X X X X)
|
| static const int kUnicodeEscapedLength = 6;
|
|
|
| // Length of the true, false, and null literals.
|
| @@ -419,9 +420,45 @@ util::Status JsonStreamParser::ParseUnicodeEscape() {
|
| }
|
| code = (code << 4) + hex_digit_to_int(p_.data()[i]);
|
| }
|
| + if (code >= JsonEscaping::kMinHighSurrogate &&
|
| + code <= JsonEscaping::kMaxHighSurrogate) {
|
| + if (p_.length() < 2 * kUnicodeEscapedLength) {
|
| + if (!finishing_) {
|
| + return util::Status::CANCELLED;
|
| + }
|
| + if (!coerce_to_utf8_) {
|
| + return ReportFailure("Missing low surrogate.");
|
| + }
|
| + } else if (p_.data()[kUnicodeEscapedLength] == '\\' &&
|
| + p_.data()[kUnicodeEscapedLength + 1] == 'u') {
|
| + uint32 low_code = 0;
|
| + for (int i = kUnicodeEscapedLength + 2; i < 2 * kUnicodeEscapedLength;
|
| + ++i) {
|
| + if (!isxdigit(p_.data()[i])) {
|
| + return ReportFailure("Invalid escape sequence.");
|
| + }
|
| + low_code = (low_code << 4) + hex_digit_to_int(p_.data()[i]);
|
| + }
|
| + if (low_code >= JsonEscaping::kMinLowSurrogate &&
|
| + low_code <= JsonEscaping::kMaxLowSurrogate) {
|
| + // Convert UTF-16 surrogate pair to 21-bit Unicode codepoint.
|
| + code = (((code & 0x3FF) << 10) | (low_code & 0x3FF)) +
|
| + JsonEscaping::kMinSupplementaryCodePoint;
|
| + // Advance past the first code unit escape.
|
| + p_.remove_prefix(kUnicodeEscapedLength);
|
| + } else if (!coerce_to_utf8_) {
|
| + return ReportFailure("Invalid low surrogate.");
|
| + }
|
| + } else if (!coerce_to_utf8_) {
|
| + return ReportFailure("Missing low surrogate.");
|
| + }
|
| + }
|
| + if (!coerce_to_utf8_ && !IsValidCodePoint(code)) {
|
| + return ReportFailure("Invalid unicode code point.");
|
| + }
|
| char buf[UTFmax];
|
| int len = EncodeAsUTF8Char(code, buf);
|
| - // Advance past the unicode escape.
|
| + // Advance past the [final] code unit escape.
|
| p_.remove_prefix(kUnicodeEscapedLength);
|
| parsed_storage_.append(buf, len);
|
| return util::Status::OK;
|
| @@ -473,7 +510,7 @@ util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
|
| floating = true;
|
| continue;
|
| }
|
| - if (c == '+' || c == '-') continue;
|
| + if (c == '+' || c == '-' || c == 'x') continue;
|
| // Not a valid number character, break out.
|
| break;
|
| }
|
| @@ -499,6 +536,10 @@ util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
|
|
|
| // Positive non-floating point number, parse as a uint64.
|
| if (!negative) {
|
| + // Octal/Hex numbers are not valid JSON values.
|
| + if (number.length() >= 2 && number[0] == '0') {
|
| + return ReportFailure("Octal/hex numbers are not valid JSON values.");
|
| + }
|
| if (!safe_strtou64(number, &result->uint_val)) {
|
| return ReportFailure("Unable to parse number.");
|
| }
|
| @@ -507,6 +548,10 @@ util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
|
| return util::Status::OK;
|
| }
|
|
|
| + // Octal/Hex numbers are not valid JSON values.
|
| + if (number.length() >= 3 && number[1] == '0') {
|
| + return ReportFailure("Octal/hex numbers are not valid JSON values.");
|
| + }
|
| // Negative non-floating point number, parse as an int64.
|
| if (!safe_strto64(number, &result->int_val)) {
|
| return ReportFailure("Unable to parse number.");
|
| @@ -677,8 +722,9 @@ util::Status JsonStreamParser::ReportFailure(StringPiece message) {
|
| static const int kContextLength = 20;
|
| const char* p_start = p_.data();
|
| const char* json_start = json_.data();
|
| - const char* begin = max(p_start - kContextLength, json_start);
|
| - const char* end = min(p_start + kContextLength, json_start + json_.size());
|
| + const char* begin = std::max(p_start - kContextLength, json_start);
|
| + const char* end =
|
| + std::min(p_start + kContextLength, json_start + json_.size());
|
| StringPiece segment(begin, end - begin);
|
| string location(p_start - begin, ' ');
|
| location.push_back('^');
|
| @@ -706,8 +752,8 @@ void JsonStreamParser::SkipWhitespace() {
|
| void JsonStreamParser::Advance() {
|
| // Advance by moving one UTF8 character while making sure we don't go beyond
|
| // the length of StringPiece.
|
| - p_.remove_prefix(
|
| - min<int>(p_.length(), UTF8FirstLetterNumBytes(p_.data(), p_.length())));
|
| + p_.remove_prefix(std::min<int>(
|
| + p_.length(), UTF8FirstLetterNumBytes(p_.data(), p_.length())));
|
| }
|
|
|
| util::Status JsonStreamParser::ParseKey() {
|
|
|