ソースを参照

Fix buffer overrun in `make_float()`

Fixes #2220
Benoit Blanchon 2 日 前
コミット
780d47e795
3 ファイル変更69 行追加2 行削除
  1. 3 0
      CHANGELOG.md
  2. 10 2
      src/ArduinoJson/TypeTraits/FloatTraits.hpp
  3. 56 0
      test/Polyfills/parseFloat.cpp

+ 3 - 0
CHANGELOG.md

@@ -6,6 +6,9 @@ HEAD
 
 * `JsonObject::createNestedObject()` returns `JsonObject::invalid()` if key is null (issue #1891)
 * `JsonObject::createNestedArray()` returns `JsonArray::invalid()` if key is null
+* Fix a buffer overrun in `as<T>()` when `T` is a numeric type and
+  the variant contains a string representing a floating point number
+  with a large number of digits (issue #2220)
 
 v5.13.5
 -------

+ 10 - 2
src/ArduinoJson/TypeTraits/FloatTraits.hpp

@@ -30,12 +30,14 @@ struct FloatTraits<T, 8 /*64bits*/> {
   static T make_float(T m, TExponent e) {
     if (e > 0) {
       for (uint8_t index = 0; e != 0; index++) {
+        if (index >= binaryPowersOfTen) return nan();
         if (e & 1) m *= positiveBinaryPowerOfTen(index);
         e >>= 1;
       }
     } else {
       e = TExponent(-e);
       for (uint8_t index = 0; e != 0; index++) {
+        if (index >= binaryPowersOfTen) return nan();
         if (e & 1) m *= negativeBinaryPowerOfTen(index);
         e >>= 1;
       }
@@ -43,8 +45,10 @@ struct FloatTraits<T, 8 /*64bits*/> {
     return m;
   }
 
+  static const size_t binaryPowersOfTen = 9;
+
   static T positiveBinaryPowerOfTen(int index) {
-    static T factors[] = {
+    static T factors[binaryPowersOfTen] = {
         1e1,
         1e2,
         1e4,
@@ -59,7 +63,7 @@ struct FloatTraits<T, 8 /*64bits*/> {
   }
 
   static T negativeBinaryPowerOfTen(int index) {
-    static T factors[] = {
+    static T factors[binaryPowersOfTen] = {
         forge(0x3FB99999, 0x9999999A),  // 1e-1
         forge(0x3F847AE1, 0x47AE147B),  // 1e-2
         forge(0x3F1A36E2, 0xEB1C432D),  // 1e-4
@@ -118,12 +122,14 @@ struct FloatTraits<T, 4 /*32bits*/> {
   static T make_float(T m, TExponent e) {
     if (e > 0) {
       for (uint8_t index = 0; e != 0; index++) {
+        if (index >= binaryPowersOfTen) return nan();
         if (e & 1) m *= positiveBinaryPowerOfTen(index);
         e >>= 1;
       }
     } else {
       e = -e;
       for (uint8_t index = 0; e != 0; index++) {
+        if (index >= binaryPowersOfTen) return nan();
         if (e & 1) m *= negativeBinaryPowerOfTen(index);
         e >>= 1;
       }
@@ -131,6 +137,8 @@ struct FloatTraits<T, 4 /*32bits*/> {
     return m;
   }
 
+  static const size_t binaryPowersOfTen = 6;
+
   static T positiveBinaryPowerOfTen(int index) {
     static T factors[] = {1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f};
     return factors[index];

+ 56 - 0
test/Polyfills/parseFloat.cpp

@@ -103,6 +103,32 @@ TEST_CASE("parseFloat<float>()") {
     check<float>("false", 0.0f);
     check<float>("true", 1.0f);
   }
+
+  SECTION("Overflow exponent with decimal part") {  // Issue #2220
+    checkNaN<float>(
+        "0.000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000001");
+  }
+
+  SECTION("Overflow exponent with integral part") {
+    checkNaN<float>(
+        "10000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000");
+  }
 }
 
 TEST_CASE("parseFloat<double>()") {
@@ -174,4 +200,34 @@ TEST_CASE("parseFloat<double>()") {
     check<double>("false", 0.0);
     check<double>("true", 1.0);
   }
+
+  SECTION("Overflow exponent with decimal part") {  // Issue #2220
+    checkNaN<double>(
+        "0.000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000001");
+  }
+
+  SECTION("Overflow exponent with integral part") {
+    checkNaN<double>(
+        "10000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000");
+  }
 }