aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/util/internal
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/util/internal')
-rw-r--r--src/google/protobuf/util/internal/json_stream_parser.cc58
-rw-r--r--src/google/protobuf/util/internal/json_stream_parser.h3
-rw-r--r--src/google/protobuf/util/internal/json_stream_parser_test.cc17
3 files changed, 50 insertions, 28 deletions
diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc
index 047c14e1..2ada3583 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser.cc
@@ -498,6 +498,19 @@ util::Status JsonStreamParser::ParseNumber() {
return result;
}
+util::Status JsonStreamParser::ParseDoubleHelper(
+ const string& number, NumberResult* result) {
+ if (!safe_strtod(number, &result->double_val)) {
+ return ReportFailure("Unable to parse number.");
+ }
+ if (!loose_float_number_conversion_ &&
+ !MathLimits<double>::IsFinite(result->double_val)) {
+ return ReportFailure("Number exceeds the range of double.");
+ }
+ result->type = NumberResult::DOUBLE;
+ return util::Status();
+}
+
util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
const char* data = p_.data();
int length = p_.length();
@@ -533,16 +546,11 @@ util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
// Floating point number, parse as a double.
if (floating) {
- if (!safe_strtod(number, &result->double_val)) {
- return ReportFailure("Unable to parse number.");
+ util::Status status = ParseDoubleHelper(number, result);
+ if (status.ok()) {
+ p_.remove_prefix(index);
}
- if (!loose_float_number_conversion_ &&
- !MathLimits<double>::IsFinite(result->double_val)) {
- return ReportFailure("Number exceeds the range of double.");
- }
- result->type = NumberResult::DOUBLE;
- p_.remove_prefix(index);
- return util::Status();
+ return status;
}
// Positive non-floating point number, parse as a uint64.
@@ -551,12 +559,18 @@ util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
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.");
+ if (safe_strtou64(number, &result->uint_val)) {
+ result->type = NumberResult::UINT;
+ p_.remove_prefix(index);
+ return util::Status();
+ } else {
+ // If the value is too large, parse it as double.
+ util::Status status = ParseDoubleHelper(number, result);
+ if (status.ok()) {
+ p_.remove_prefix(index);
+ }
+ return status;
}
- result->type = NumberResult::UINT;
- p_.remove_prefix(index);
- return util::Status();
}
// Octal/Hex numbers are not valid JSON values.
@@ -564,12 +578,18 @@ util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
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.");
+ if (safe_strto64(number, &result->int_val)) {
+ result->type = NumberResult::INT;
+ p_.remove_prefix(index);
+ return util::Status();
+ } else {
+ // If the value is too large, parse it as double.
+ util::Status status = ParseDoubleHelper(number, result);
+ if (status.ok()) {
+ p_.remove_prefix(index);
+ }
+ return status;
}
- result->type = NumberResult::INT;
- p_.remove_prefix(index);
- return util::Status();
}
util::Status JsonStreamParser::HandleBeginObject() {
diff --git a/src/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h
index 6b9d46ee..31933b67 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.h
+++ b/src/google/protobuf/util/internal/json_stream_parser.h
@@ -154,6 +154,9 @@ class LIBPROTOBUF_EXPORT JsonStreamParser {
// component.
util::Status ParseNumberHelper(NumberResult* result);
+ // Parse a number as double into a NumberResult.
+ util::Status ParseDoubleHelper(const string& number, NumberResult* result);
+
// Handles a { during parsing of a value.
util::Status HandleBeginObject();
diff --git a/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc
index ca71ff24..a11e9be0 100644
--- a/src/google/protobuf/util/internal/json_stream_parser_test.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc
@@ -694,20 +694,19 @@ TEST_F(JsonStreamParserTest, ExtraCharactersAfterObject) {
}
}
-// numbers too large
-TEST_F(JsonStreamParserTest, PositiveNumberTooBig) {
- StringPiece str = "[18446744073709551616]"; // 2^64
+TEST_F(JsonStreamParserTest, PositiveNumberTooBigIsDouble) {
+ StringPiece str = "18446744073709551616"; // 2^64
for (int i = 0; i <= str.length(); ++i) {
- ow_.StartList("");
- DoErrorTest(str, i, "Unable to parse number.");
+ ow_.RenderDouble("", 18446744073709552000.0);
+ DoTest(str, i);
}
}
-TEST_F(JsonStreamParserTest, NegativeNumberTooBig) {
- StringPiece str = "[-18446744073709551616]";
+TEST_F(JsonStreamParserTest, NegativeNumberTooBigIsDouble) {
+ StringPiece str = "-18446744073709551616";
for (int i = 0; i <= str.length(); ++i) {
- ow_.StartList("");
- DoErrorTest(str, i, "Unable to parse number.");
+ ow_.RenderDouble("", -18446744073709551616.0);
+ DoTest(str, i);
}
}