Skip to content

Commit 78f3f41

Browse files
authored
Merge pull request #131 from arduino/fix-buf-size-float
Bugfix: Small buffer size causes buffer overrun when invoking String::Ctor with large float/double value.
2 parents 4f19438 + 3c76ef2 commit 78f3f41

File tree

3 files changed

+54
-11
lines changed

3 files changed

+54
-11
lines changed

Diff for: api/String.cpp

+18-4
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,24 @@
2020
*/
2121

2222
#include "String.h"
23+
#include "Common.h"
2324
#include "itoa.h"
2425
#include "deprecated-avr-comp/avr/dtostrf.h"
2526

27+
#include <float.h>
28+
29+
namespace arduino {
30+
2631
/*********************************************/
27-
/* Constructors */
32+
/* Static Member Initialisation */
2833
/*********************************************/
2934

30-
namespace arduino {
35+
size_t const String::FLT_MAX_DECIMAL_PLACES;
36+
size_t const String::DBL_MAX_DECIMAL_PLACES;
37+
38+
/*********************************************/
39+
/* Constructors */
40+
/*********************************************/
3141

3242
String::String(const char *cstr)
3343
{
@@ -111,15 +121,19 @@ String::String(unsigned long value, unsigned char base)
111121

112122
String::String(float value, unsigned char decimalPlaces)
113123
{
124+
static size_t const FLOAT_BUF_SIZE = FLT_MAX_10_EXP + FLT_MAX_DECIMAL_PLACES + 1 /* '-' */ + 1 /* '.' */ + 1 /* '\0' */;
114125
init();
115-
char buf[33];
126+
char buf[FLOAT_BUF_SIZE];
127+
decimalPlaces = min(decimalPlaces, FLT_MAX_DECIMAL_PLACES);
116128
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
117129
}
118130

119131
String::String(double value, unsigned char decimalPlaces)
120132
{
133+
static size_t const DOUBLE_BUF_SIZE = DBL_MAX_10_EXP + DBL_MAX_DECIMAL_PLACES + 1 /* '-' */ + 1 /* '.' */ + 1 /* '\0' */;
121134
init();
122-
char buf[33];
135+
char buf[DOUBLE_BUF_SIZE];
136+
decimalPlaces = min(decimalPlaces, DBL_MAX_DECIMAL_PLACES);
123137
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
124138
}
125139

Diff for: api/String.h

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ class String
5858
typedef void (String::*StringIfHelperType)() const;
5959
void StringIfHelper() const {}
6060

61+
static size_t const FLT_MAX_DECIMAL_PLACES = 10;
62+
static size_t const DBL_MAX_DECIMAL_PLACES = FLT_MAX_DECIMAL_PLACES;
63+
6164
public:
6265
// constructors
6366
// creates a copy of the initial value.

Diff for: test/src/String/test_String.cpp

+33-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
* INCLUDE
77
**************************************************************************************/
88

9+
#include <float.h>
10+
911
#include <catch.hpp>
1012

1113
#include <String.h>
@@ -80,16 +82,40 @@ TEST_CASE ("Testing String(unsigned long, unsigned char base = 10) constructor()
8082

8183
TEST_CASE ("Testing String(float, unsigned char decimalPlaces = 2) constructor()", "[String-Ctor-10]")
8284
{
83-
float const val = 1.234f;
84-
arduino::String str(val);
85-
REQUIRE(strcmp(str.c_str(), "1.23") == 0);
85+
WHEN ("String::String (some float value)")
86+
{
87+
arduino::String str(1.234f);
88+
REQUIRE(strcmp(str.c_str(), "1.23") == 0);
89+
}
90+
WHEN ("String::String (FLT_MAX)")
91+
{
92+
arduino::String str(FLT_MAX);
93+
REQUIRE(strcmp(str.c_str(), "340282346638528859811704183484516925440.00") == 0);
94+
}
95+
WHEN ("String::String (-FLT_MAX)")
96+
{
97+
arduino::String str(-FLT_MAX);
98+
REQUIRE(strcmp(str.c_str(), "-340282346638528859811704183484516925440.00") == 0);
99+
}
86100
}
87101

88102
TEST_CASE ("Testing String(double, unsigned char decimalPlaces = 2) constructor()", "[String-Ctor-11]")
89103
{
90-
double const val = 5.678;
91-
arduino::String str(val);
92-
REQUIRE(strcmp(str.c_str(), "5.68") == 0);
104+
WHEN ("String::String (some double value)")
105+
{
106+
arduino::String str(5.678);
107+
REQUIRE(strcmp(str.c_str(), "5.68") == 0);
108+
}
109+
WHEN ("String::String (DBL_MAX)")
110+
{
111+
arduino::String str(DBL_MAX);
112+
REQUIRE(strcmp(str.c_str(), "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00") == 0);
113+
}
114+
WHEN ("String::String (-DBL_MAX)")
115+
{
116+
arduino::String str(-DBL_MAX);
117+
REQUIRE(strcmp(str.c_str(), "-179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00") == 0);
118+
}
93119
}
94120

95121
TEST_CASE ("Testing String(const __FlashStringHelper) constructor() with invalid buffer", "[String-Ctor-12]")
@@ -131,4 +157,4 @@ TEST_CASE ("Testing String(String &&) with move(String &rhs) from larger to smal
131157
arduino::String str1("Arduino");
132158
str = static_cast<arduino::String&&>(str1);
133159
REQUIRE(str1.compareTo("Arduino") == 0);
134-
}
160+
}

0 commit comments

Comments
 (0)