folly json bug fix: overflow for -1LL<<63
authorAlexander Sidorov <salex@fb.com>
Fri, 17 Jan 2014 06:26:04 +0000 (22:26 -0800)
committerJordan DeLong <jdelong@fb.com>
Sun, 19 Jan 2014 01:39:43 +0000 (17:39 -0800)
Summary: -1LL<<63 was passed to folly::to() without '-' so it overflowed. Fixed that

Test Plan:
tried this:

int main() {
stringstream s;
s << "{\"int\":" << -1LL<<63 << "}";
string str = s.str();
cout << "string to parse: " << endl << str << endl;

int64_t sample = folly::parseJson(str.c_str())["int"].asInt();
LOG(INFO) << "test result = " << sample;

return 0;
}

it returns right value.

Also tried it with "-Infinity" and double type for sample. In works fine as well.

Reviewed By: andrei.alexandrescu@fb.com

FB internal diff: D1130155

folly/json.cpp

index 3b954ef41e27df84a912d9c88a02236b92ef9a71..f248ef8e324a416af14a973b7636c1c6cfd80948 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013 Facebook, Inc.
+ * Copyright 2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -308,6 +308,15 @@ struct Input {
     return skipWhile([] (char c) { return c >= '0' && c <= '9'; });
   }
 
+  StringPiece skipMinusAndDigits() {
+    bool firstChar = true;
+    return skipWhile([&firstChar] (char c) {
+        bool result = (c >= '0' && c <= '9') || (firstChar && c == '-');
+        firstChar = false;
+        return result;
+      });
+  }
+
   void skipWhitespace() {
     // Spaces other than ' ' characters are less common but should be
     // checked.  This configuration where we loop on the ' '
@@ -469,22 +478,19 @@ dynamic parseArray(Input& in) {
 dynamic parseNumber(Input& in) {
   bool const negative = (*in == '-');
   if (negative) {
-    ++in;
-    if (in.consume("Infinity")) {
+    if (in.consume("-Infinity")) {
       return -std::numeric_limits<double>::infinity();
     }
   }
 
-  auto integral = in.skipDigits();
-  if (integral.empty()) {
+  auto integral = in.skipMinusAndDigits();
+  if (negative && integral.size() < 2) {
     in.error("expected digits after `-'");
   }
+
   auto const wasE = *in == 'e' || *in == 'E';
   if (*in != '.' && !wasE) {
     auto val = to<int64_t>(integral);
-    if (negative) {
-      val = -val;
-    }
     in.skipWhitespace();
     return val;
   }
@@ -501,9 +507,6 @@ dynamic parseNumber(Input& in) {
   auto fullNum = makeRange(integral.begin(), end);
 
   auto val = to<double>(fullNum);
-  if (negative) {
-    val *= -1;
-  }
   return val;
 }