diff --git a/CHANGELOG.md b/CHANGELOG.md index 8366b8f2..a6cd4cc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ HEAD * Improve error messages when using `char` or `char*` (issue #2043) * Make string support even more generic (PR #2084 by @d-a-v) +* Fix a buffer overrun in `as()` 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) ------- diff --git a/extras/tests/Numbers/parseDouble.cpp b/extras/tests/Numbers/parseDouble.cpp index 69eb7093..3bdf738b 100644 --- a/extras/tests/Numbers/parseDouble.cpp +++ b/extras/tests/Numbers/parseDouble.cpp @@ -93,4 +93,34 @@ TEST_CASE("parseNumber()") { 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"); + } } diff --git a/src/ArduinoJson/Numbers/FloatTraits.hpp b/src/ArduinoJson/Numbers/FloatTraits.hpp index 6c22cfd0..536653f6 100644 --- a/src/ArduinoJson/Numbers/FloatTraits.hpp +++ b/src/ArduinoJson/Numbers/FloatTraits.hpp @@ -29,6 +29,8 @@ struct FloatTraits { typedef int16_t exponent_type; static const exponent_type exponent_max = 308; + static const size_t binaryPowersOfTen = 9; + static pgm_ptr positiveBinaryPowersOfTen() { ARDUINOJSON_DEFINE_PROGMEM_ARRAY( // uint64_t, factors, @@ -113,6 +115,8 @@ struct FloatTraits { typedef int8_t exponent_type; static const exponent_type exponent_max = 38; + static const size_t binaryPowersOfTen = 6; + static pgm_ptr positiveBinaryPowersOfTen() { 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() : traits::negativeBinaryPowersOfTen(); + auto count = traits::binaryPowersOfTen; + if (e <= 0) e = TExponent(-e); for (uint8_t index = 0; e != 0; index++) { + if (index >= count) + return traits::nan(); if (e & 1) m *= powersOfTen[index]; e >>= 1;