Fix buffer overrun in make_float()

Fixes #2220
This commit is contained in:
Benoit Blanchon
2026-03-02 10:35:44 +01:00
parent 874127593a
commit 780d47e795
3 changed files with 69 additions and 2 deletions
+3
View File
@@ -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
View File
@@ -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
View File
@@ -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");
}
}