소스 검색

Fix buffer overrun in `make_float()`

Fixes #2220
Benoit Blanchon 2 일 전
부모
커밋
ff2db174ff
3개의 변경된 파일41개의 추가작업 그리고 0개의 파일을 삭제
  1. 3 0
      CHANGELOG.md
  2. 30 0
      extras/tests/Numbers/parseDouble.cpp
  3. 8 0
      src/ArduinoJson/Numbers/FloatTraits.hpp

+ 3 - 0
CHANGELOG.md

@@ -6,6 +6,9 @@ HEAD
 
 
 * Improve error messages when using `char` or `char*` (issue #2043)
 * Improve error messages when using `char` or `char*` (issue #2043)
 * Make string support even more generic (PR #2084 by @d-a-v)
 * Make string support even more generic (PR #2084 by @d-a-v)
+* 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)
 
 
 v6.21.5 (2024-01-10)
 v6.21.5 (2024-01-10)
 -------
 -------

+ 30 - 0
extras/tests/Numbers/parseDouble.cpp

@@ -93,4 +93,34 @@ TEST_CASE("parseNumber<double>()") {
     checkDoubleNaN("NaN");
     checkDoubleNaN("NaN");
     checkDoubleNaN("nan");
     checkDoubleNaN("nan");
   }
   }
+
+  SECTION("Overflow exponent with decimal part") {  // Issue #2220
+    checkDoubleNaN(
+        "0.000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000001");
+  }
+
+  SECTION("Overflow exponent with integral part") {
+    checkDoubleNaN(
+        "10000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000"
+        "00000000000000000000000000000000000000000000000000");
+  }
 }
 }

+ 8 - 0
src/ArduinoJson/Numbers/FloatTraits.hpp

@@ -29,6 +29,8 @@ struct FloatTraits<T, 8 /*64bits*/> {
   typedef int16_t exponent_type;
   typedef int16_t exponent_type;
   static const exponent_type exponent_max = 308;
   static const exponent_type exponent_max = 308;
 
 
+  static const size_t binaryPowersOfTen = 9;
+
   static pgm_ptr<T> positiveBinaryPowersOfTen() {
   static pgm_ptr<T> positiveBinaryPowersOfTen() {
     ARDUINOJSON_DEFINE_PROGMEM_ARRAY(  //
     ARDUINOJSON_DEFINE_PROGMEM_ARRAY(  //
         uint64_t, factors,
         uint64_t, factors,
@@ -113,6 +115,8 @@ struct FloatTraits<T, 4 /*32bits*/> {
   typedef int8_t exponent_type;
   typedef int8_t exponent_type;
   static const exponent_type exponent_max = 38;
   static const exponent_type exponent_max = 38;
 
 
+  static const size_t binaryPowersOfTen = 6;
+
   static pgm_ptr<T> positiveBinaryPowersOfTen() {
   static pgm_ptr<T> positiveBinaryPowersOfTen() {
     ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors,
     ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors,
                                      {
                                      {
@@ -198,10 +202,14 @@ inline TFloat make_float(TFloat m, TExponent e) {
 
 
   auto powersOfTen = e > 0 ? traits::positiveBinaryPowersOfTen()
   auto powersOfTen = e > 0 ? traits::positiveBinaryPowersOfTen()
                            : traits::negativeBinaryPowersOfTen();
                            : traits::negativeBinaryPowersOfTen();
+  auto count = traits::binaryPowersOfTen;
+
   if (e <= 0)
   if (e <= 0)
     e = TExponent(-e);
     e = TExponent(-e);
 
 
   for (uint8_t index = 0; e != 0; index++) {
   for (uint8_t index = 0; e != 0; index++) {
+    if (index >= count)
+      return traits::nan();
     if (e & 1)
     if (e & 1)
       m *= powersOfTen[index];
       m *= powersOfTen[index];
     e >>= 1;
     e >>= 1;