From 780d47e795afb499a2fa07fde562de7c9d7c80c1 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Mon, 2 Mar 2026 10:35:44 +0100 Subject: [PATCH] Fix buffer overrun in `make_float()` Fixes #2220 --- CHANGELOG.md | 3 ++ src/ArduinoJson/TypeTraits/FloatTraits.hpp | 12 ++++- test/Polyfills/parseFloat.cpp | 56 ++++++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00f2167e..2bc08314 100644 --- a/CHANGELOG.md +++ b/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()` 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 ------- diff --git a/src/ArduinoJson/TypeTraits/FloatTraits.hpp b/src/ArduinoJson/TypeTraits/FloatTraits.hpp index 1b1bc1d6..445cc4e8 100644 --- a/src/ArduinoJson/TypeTraits/FloatTraits.hpp +++ b/src/ArduinoJson/TypeTraits/FloatTraits.hpp @@ -30,12 +30,14 @@ struct FloatTraits { 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 { 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 { } 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 { 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 { 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]; diff --git a/test/Polyfills/parseFloat.cpp b/test/Polyfills/parseFloat.cpp index 947605cd..c339f5cb 100644 --- a/test/Polyfills/parseFloat.cpp +++ b/test/Polyfills/parseFloat.cpp @@ -103,6 +103,32 @@ TEST_CASE("parseFloat()") { check("false", 0.0f); check("true", 1.0f); } + + SECTION("Overflow exponent with decimal part") { // Issue #2220 + checkNaN( + "0.000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000001"); + } + + SECTION("Overflow exponent with integral part") { + checkNaN( + "10000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000"); + } } TEST_CASE("parseFloat()") { @@ -174,4 +200,34 @@ TEST_CASE("parseFloat()") { check("false", 0.0); check("true", 1.0); } + + SECTION("Overflow exponent with decimal part") { // Issue #2220 + checkNaN( + "0.000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000001"); + } + + SECTION("Overflow exponent with integral part") { + checkNaN( + "10000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000"); + } }