From d9c0c09aa8308c52e96388dc55ad6fca533348a1 Mon Sep 17 00:00:00 2001 From: TD-er <gijs.noorlander@gmail.com> Date: Thu, 25 Aug 2022 22:30:22 +0200 Subject: [PATCH] [String] Fix float assignment using wrong type Using 3.0.2 assigning a float to a string resulted in undefined behaviour. ```c++ String str; float myfloat[12][4]; myfloat[0][0] = 1.0f; str = myfloat[0][0]; ``` `str` does contain a single char. Worked fine in 2.7.4 --- cores/esp8266/WString.cpp | 120 ++++++++++++++++++++++++++++------ cores/esp8266/WString.h | 133 ++++++++++++-------------------------- 2 files changed, 144 insertions(+), 109 deletions(-) diff --git a/cores/esp8266/WString.cpp b/cores/esp8266/WString.cpp index 331b2a5409..77b021d4dc 100644 --- a/cores/esp8266/WString.cpp +++ b/cores/esp8266/WString.cpp @@ -37,7 +37,7 @@ /* Conversion helpers */ /*********************************************/ -static String toString(unsigned char value, unsigned char base) { +static String toString(const unsigned char& value, unsigned char base) { String out; char buf[1 + std::numeric_limits<unsigned char>::digits]; @@ -46,7 +46,7 @@ static String toString(unsigned char value, unsigned char base) { return out; } -static String toString(int value, unsigned char base) { +static String toString(const int& value, unsigned char base) { String out; char buf[2 + std::numeric_limits<int>::digits]; @@ -55,7 +55,7 @@ static String toString(int value, unsigned char base) { return out; } -static String toString(unsigned int value, unsigned char base) { +static String toString(const unsigned int& value, unsigned char base) { String out; char buf[1 + std::numeric_limits<unsigned int>::digits]; @@ -64,7 +64,7 @@ static String toString(unsigned int value, unsigned char base) { return out; } -static String toString(long value, unsigned char base) { +static String toString(const long& value, unsigned char base) { String out; char buf[2 + std::numeric_limits<long>::digits]; @@ -73,7 +73,7 @@ static String toString(long value, unsigned char base) { return out; } -static String toString(unsigned long value, unsigned char base) { +static String toString(const unsigned long& value, unsigned char base) { String out; char buf[1 + std::numeric_limits<unsigned long>::digits]; @@ -84,7 +84,7 @@ static String toString(unsigned long value, unsigned char base) { // TODO: {u,}lltoa don't guarantee that the buffer is usable directly, one should always use the returned pointer -static String toString(long long value, unsigned char base) { +static String toString(const long long& value, unsigned char base) { String out; char buf[2 + std::numeric_limits<long long>::digits]; @@ -93,7 +93,7 @@ static String toString(long long value, unsigned char base) { return out; } -static String toString(unsigned long long value, unsigned char base) { +static String toString(const unsigned long long& value, unsigned char base) { String out; char buf[1 + std::numeric_limits<unsigned long long>::digits]; @@ -102,7 +102,7 @@ static String toString(unsigned long long value, unsigned char base) { return out; } -static String toString(double value, unsigned char decimalPlaces) { +static String toString(const double& value, unsigned char decimalPlaces) { String out; char buf[33]; @@ -111,7 +111,7 @@ static String toString(double value, unsigned char decimalPlaces) { return out; } -static String toString(float value, unsigned char decimalPlaces) { +static String toString(const float& value, unsigned char decimalPlaces) { return toString(static_cast<double>(value), decimalPlaces); } @@ -140,42 +140,79 @@ String::String(String &&rval) noexcept { move(rval); } -String::String(unsigned char value, unsigned char base) : +String::String(const unsigned char& value, unsigned char base) : String(toString(value, base)) {} -String::String(int value, unsigned char base) : +String::String(unsigned char value) : + String(value, 10) +{} + +String::String(const int& value, unsigned char base) : String(toString(value, base)) {} -String::String(unsigned int value, unsigned char base) : +String::String(int value) : + String(value, 10) +{} + +String::String(const unsigned int& value, unsigned char base) : String(toString(value, base)) {} -String::String(long value, unsigned char base) : +String::String(unsigned int value) : + String(value, 10) +{} + +String::String(const long& value, unsigned char base) : String(toString(value, base)) {} -String::String(unsigned long value, unsigned char base) : +String::String(long value) : + String(value, 10) +{} + +String::String(const unsigned long& value, unsigned char base) : String(toString(value, base)) {} -String::String(long long value, unsigned char base) : +String::String(unsigned long value) : + String(value, 10) +{} + +String::String(const long long& value, unsigned char base) : String(toString(value, base)) {} -String::String(unsigned long long value, unsigned char base) : +String::String(long long value) : + String(value, 10) +{} + +String::String(const unsigned long long& value, unsigned char base) : String(toString(value, base)) {} -String::String(float value, unsigned char decimalPlaces) : +String::String(unsigned long long value) : + String(value, 10) +{} + +String::String(const float& value, unsigned char decimalPlaces) : String(toString(value, decimalPlaces)) {} -String::String(double value, unsigned char decimalPlaces) : +String::String(float value) : + String(value, 2) +{} + +String::String(const double& value, unsigned char decimalPlaces) : String(toString(value, decimalPlaces)) {} +String::String(double value) : + String(value, 2) +{} + + /*********************************************/ /* Memory Management */ /*********************************************/ @@ -314,12 +351,57 @@ String &String::operator =(const __FlashStringHelper *pstr) { return *this; } -String &String::operator =(char c) { +String &String::operator =(const char& c) { char buffer[2] { c, '\0' }; *this = buffer; return *this; } +String &String::operator =(const unsigned char& value) { + *this = String(value); + return *this; +} + +String &String::operator =(const int& value) { + *this = String(value); + return *this; +} + +String &String::operator =(const unsigned int& value) { + *this = String(value); + return *this; +} + +String &String::operator =(const long& value) { + *this = String(value); + return *this; +} + +String &String::operator =(const unsigned long& value) { + *this = String(value); + return *this; +} + +String &String::operator =(const long long& value) { + *this = String(value); + return *this; +} + +String &String::operator =(const unsigned long long& value) { + *this = String(value); + return *this; +} + +String &String::operator =(const float& value) { + *this = String(value); + return *this; +} + +String &String::operator =(const double& value) { + *this = String(value); + return *this; +} + /*********************************************/ /* concat */ /*********************************************/ diff --git a/cores/esp8266/WString.h b/cores/esp8266/WString.h index 47a9177534..79a0b1011d 100644 --- a/cores/esp8266/WString.h +++ b/cores/esp8266/WString.h @@ -66,50 +66,32 @@ class String { sso.isHeap = 0; } - String(unsigned char, unsigned char base); - explicit String(unsigned char value) : - String(value, 10) - {} - - String(int, unsigned char base); - explicit String(int value) : - String(value, 10) - {} - - String(unsigned int, unsigned char base); - explicit String(unsigned int value) : - String(value, 10) - {} - - String(long, unsigned char base); - explicit String(long value) : - String(value, 10) - {} - - String(unsigned long, unsigned char base); - explicit String(unsigned long value) : - String(value, 10) - {} - - String(long long, unsigned char base); - explicit String(long long value) : - String(value, 10) - {} - - String(unsigned long long, unsigned char base); - explicit String(unsigned long long value) : - String(value, 10) - {} - - String(float, unsigned char decimalPlaces); - explicit String(float value) : - String(value, 2) - {} - - String(double, unsigned char decimalPlaces); - explicit String(double value) : - String(value, 2) - {} + String(const unsigned char&, unsigned char base); + explicit String(unsigned char value); + + String(const int&, unsigned char base); + explicit String(int value); + + String(const unsigned int&, unsigned char base); + explicit String(unsigned int value); + + String(const long&, unsigned char base); + explicit String(long value); + + String(const unsigned long&, unsigned char base); + explicit String(unsigned long value); + + String(const long long&, unsigned char base); + explicit String(long long value); + + String(const unsigned long long&, unsigned char base); + explicit String(unsigned long long value); + + String(const float&, unsigned char decimalPlaces); + explicit String(float value); + + String(const double&, unsigned char decimalPlaces); + explicit String(double value); ~String() { invalidate(); @@ -135,52 +117,17 @@ class String { String &operator =(String &&rval) noexcept; String &operator =(const char *cstr); String &operator =(const __FlashStringHelper *str); - String &operator =(char c); - - String &operator =(unsigned char value) { - *this = String(value); - return *this; - } - - String &operator =(int value) { - *this = String(value); - return *this; - } - - String &operator =(unsigned int value) { - *this = String(value); - return *this; - } - - String &operator =(long value) { - *this = String(value); - return *this; - } - - String &operator =(unsigned long value) { - *this = String(value); - return *this; - } - - String &operator =(long long value) { - *this = String(value); - return *this; - } - - String &operator =(unsigned long long value) { - *this = String(value); - return *this; - } - - String &operator =(float value) { - *this = String(value); - return *this; - } - - String &operator =(double value) { - *this = String(value); - return *this; - } + String &operator =(const char& c); + + String &operator =(const unsigned char& value); + String &operator =(const int& value); + String &operator =(const unsigned int& value); + String &operator =(const long& value); + String &operator =(const unsigned long& value); + String &operator =(const long long& value); + String &operator =(const unsigned long long& value); + String &operator =(const float& value); + String &operator =(const double& value); // concatenate (works w/ built-in types, same as assignment) @@ -227,12 +174,18 @@ class String { bool operator ==(const char *cstr) const { return equals(cstr); } + bool operator ==(const __FlashStringHelper *s) const { + return equals(s); + } bool operator !=(const String &rhs) const { return !equals(rhs); } bool operator !=(const char *cstr) const { return !equals(cstr); } + bool operator !=(const __FlashStringHelper *s) const { + return !equals(s); + } bool operator <(const String &rhs) const; bool operator >(const String &rhs) const; bool operator <=(const String &rhs) const;