Folly parseJson doesn't handle minInt properly
authorBo You <byou@fb.com>
Mon, 27 Jun 2016 16:17:21 +0000 (09:17 -0700)
committerFacebook Github Bot 8 <facebook-github-bot-8-bot@fb.com>
Mon, 27 Jun 2016 16:23:22 +0000 (09:23 -0700)
Summary:
Right now in ##parseNumber## in ##folly/json.cpp##, when a negative number is provided, both the minus sign and the digits are stored in the variable ##integral##: https://fburl.com/362938516.

This causes problem when the exact min int is provided (-9223372036854775808). Because now ##integral.size()## equals 20 (including the minus sign), which is greater than ##maxIntLen## (which is 19). We need to handle negatives separately to get the correct result.

Reviewed By: yfeldblum

Differential Revision: D3479054

fbshipit-source-id: 15c782962a5f5ee845a2a18f2145c7695ec2d546

folly/json.cpp
folly/test/JsonTest.cpp

index 86600fd5d7ca21d011136b1e87fa498aaede8d95..f4607efd88754069754c25589886c94a8f4061bb 100644 (file)
@@ -512,9 +512,9 @@ dynamic parseNumber(Input& in) {
   auto const wasE = *in == 'e' || *in == 'E';
 
   constexpr const char* maxInt = "9223372036854775807";
-  constexpr const char* minInt = "9223372036854775808";
+  constexpr const char* minInt = "-9223372036854775808";
   constexpr auto maxIntLen = constexpr_strlen(maxInt);
-
+  constexpr auto minIntLen = constexpr_strlen(minInt);
 
   if (*in != '.' && !wasE && in.getOpts().parse_numbers_as_strings) {
     return integral;
@@ -522,8 +522,8 @@ dynamic parseNumber(Input& in) {
 
   if (*in != '.' && !wasE) {
     if (LIKELY(!in.getOpts().double_fallback || integral.size() < maxIntLen) ||
-         (integral.size() == maxIntLen &&
-           (integral <= maxInt || (integral == minInt && negative)))) {
+        (!negative && integral.size() == maxIntLen && integral <= maxInt) ||
+        (negative && integral.size() == minIntLen && integral <= minInt)) {
       auto val = to<int64_t>(integral);
       in.skipWhitespace();
       return val;
index a9bca3bab9edfd1bef848ca1f9a361b7d628da8d..e6820f7f01b526ae2f31cf8c6ad438ead13c6e6e 100644 (file)
@@ -395,6 +395,9 @@ TEST(Json, ParseDoubleFallback) {
   EXPECT_EQ(847605071342477612345678900000.0,
       parseJson("{\"a\":847605071342477612345678912345}",
         opts).items().begin()->second.asDouble());
+  EXPECT_EQ(
+      toJson(parseJson(R"({"a":-9223372036854775808})", opts)),
+      R"({"a":-9223372036854775808})");
 }
 
 TEST(Json, ParseNumbersAsStrings) {