From c5de6b46d5bcda33ee11a03906c219361481c393 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 14 Jan 2022 09:30:22 -0300 Subject: [PATCH 1/7] Fixes String(float) issue with Stack Smashing --- cores/esp32/WString.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cores/esp32/WString.cpp b/cores/esp32/WString.cpp index b78cf2eed90..0455cfaad70 100644 --- a/cores/esp32/WString.cpp +++ b/cores/esp32/WString.cpp @@ -114,13 +114,13 @@ String::String(unsigned long value, unsigned char base) { String::String(float value, unsigned char decimalPlaces) { init(); - char buf[33]; + char buf[34]; *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); } String::String(double value, unsigned char decimalPlaces) { init(); - char buf[33]; + char buf[34]; *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); } From 1c459879da0dec07ccc769833ebd6342dfbd1afb Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 14 Jan 2022 15:20:27 -0300 Subject: [PATCH 2/7] Fixes String(float) issue with Stack Smashing --- cores/esp32/stdlib_noniso.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/cores/esp32/stdlib_noniso.c b/cores/esp32/stdlib_noniso.c index 8f24520dac3..cb598d869e5 100644 --- a/cores/esp32/stdlib_noniso.c +++ b/cores/esp32/stdlib_noniso.c @@ -88,6 +88,32 @@ char* ultoa(unsigned long value, char* result, int base) { return result; } +#if 1 +// This version is intended to be user proof +// It avoids Stack Smashing issue, even for s = String(-234223.4f, 32) or String(0.0f, 100) +char *dtostrf(double number, signed char width, unsigned char prec, char *s) { + char fmt[34]; + // calculates how many characters the integer part of the float will take + sprintf(fmt, "%32.0f", number); + // finds the start of number ignoring the blanks + char *start = fmt; + while (*start == ' ') start++; + unsigned char numSize = strlen(start), maxSize = sizeof(fmt) - 1; + int maxPrec; + + if (prec) numSize += 1; // for the '.' + + // avoiding Stack smashing protect failure! + if (width > maxSize) width = maxSize; + maxPrec = maxSize - numSize; + prec = maxPrec > 0 ? maxPrec : 0; + + sprintf(fmt, "%%%d.%df", width, prec); + sprintf(s, fmt, number); + return s; +} +#else +// orginal code from Arduino ESP8266 char * dtostrf(double number, signed char width, unsigned char prec, char *s) { bool negative = false; @@ -160,3 +186,4 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { *out = 0; return s; } +#endif From f3c7b4980ded4d75af5536cb4cb9691444dbe0f4 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Sun, 16 Jan 2022 18:34:21 -0300 Subject: [PATCH 3/7] Fixes String(float) issue with Stack Smashing --- cores/esp32/WString.cpp | 8 +++--- cores/esp32/stdlib_noniso.c | 49 +++++++++++++++++++++++-------------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/cores/esp32/WString.cpp b/cores/esp32/WString.cpp index 0455cfaad70..5434af73399 100644 --- a/cores/esp32/WString.cpp +++ b/cores/esp32/WString.cpp @@ -114,14 +114,14 @@ String::String(unsigned long value, unsigned char base) { String::String(float value, unsigned char decimalPlaces) { init(); - char buf[34]; - *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); + char buf[64]; + *this = dtostrf(value, sizeof(buf) - 1, decimalPlaces, buf); } String::String(double value, unsigned char decimalPlaces) { init(); - char buf[34]; - *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); + char buf[64]; + *this = dtostrf(value, sizeof(buf) - 1, decimalPlaces, buf); } String::~String() { diff --git a/cores/esp32/stdlib_noniso.c b/cores/esp32/stdlib_noniso.c index cb598d869e5..b39e0369ca1 100644 --- a/cores/esp32/stdlib_noniso.c +++ b/cores/esp32/stdlib_noniso.c @@ -92,25 +92,36 @@ char* ultoa(unsigned long value, char* result, int base) { // This version is intended to be user proof // It avoids Stack Smashing issue, even for s = String(-234223.4f, 32) or String(0.0f, 100) char *dtostrf(double number, signed char width, unsigned char prec, char *s) { - char fmt[34]; - // calculates how many characters the integer part of the float will take - sprintf(fmt, "%32.0f", number); - // finds the start of number ignoring the blanks - char *start = fmt; - while (*start == ' ') start++; - unsigned char numSize = strlen(start), maxSize = sizeof(fmt) - 1; - int maxPrec; - - if (prec) numSize += 1; // for the '.' - - // avoiding Stack smashing protect failure! - if (width > maxSize) width = maxSize; - maxPrec = maxSize - numSize; - prec = maxPrec > 0 ? maxPrec : 0; - - sprintf(fmt, "%%%d.%df", width, prec); - sprintf(s, fmt, number); - return s; + char fmt[20]; // just for the formating in sprintf() + uint8_t numSize = 0; + int maxPrec; + + if (isnan(number)) { + strcpy(s, "nan"); + return s; + } + if (isinf(number)) { + strcpy(s, "inf"); + return s; + } + + // calculates how many characters the integer part of the float will take + if (number < 0) { // number is negative + numSize = 1; // for the '-' simbol + } + double n = fabs(number); + do { + numSize++; + n = n / 10; + } while (n > 1); + if (prec) numSize += 1; // for the '.' + // avoiding Stack smashing protect failure! + maxPrec = width - numSize; + if (prec) prec = maxPrec > 0 ? maxPrec : 0; + + sprintf(fmt, "%%%d.%df", numSize, prec); + sprintf(s, fmt, number); + return s; } #else // orginal code from Arduino ESP8266 From c6ab73b04f07f60e1c0d229ba29df3a9038154ea Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Sun, 16 Jan 2022 20:14:12 -0300 Subject: [PATCH 4/7] Fixes String(float) issue with Stack Smashing --- cores/esp32/WString.cpp | 11 ++++++----- cores/esp32/stdlib_noniso.c | 38 ------------------------------------- 2 files changed, 6 insertions(+), 43 deletions(-) diff --git a/cores/esp32/WString.cpp b/cores/esp32/WString.cpp index 5434af73399..1021570211e 100644 --- a/cores/esp32/WString.cpp +++ b/cores/esp32/WString.cpp @@ -114,14 +114,15 @@ String::String(unsigned long value, unsigned char base) { String::String(float value, unsigned char decimalPlaces) { init(); - char buf[64]; - *this = dtostrf(value, sizeof(buf) - 1, decimalPlaces, buf); -} + char *buf = (char*)malloc(decimalPlaces + 42); + *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); + free(buf);} String::String(double value, unsigned char decimalPlaces) { init(); - char buf[64]; - *this = dtostrf(value, sizeof(buf) - 1, decimalPlaces, buf); + char *buf = (char*)malloc(decimalPlaces + 312); + *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); + free(buf); } String::~String() { diff --git a/cores/esp32/stdlib_noniso.c b/cores/esp32/stdlib_noniso.c index b39e0369ca1..8f24520dac3 100644 --- a/cores/esp32/stdlib_noniso.c +++ b/cores/esp32/stdlib_noniso.c @@ -88,43 +88,6 @@ char* ultoa(unsigned long value, char* result, int base) { return result; } -#if 1 -// This version is intended to be user proof -// It avoids Stack Smashing issue, even for s = String(-234223.4f, 32) or String(0.0f, 100) -char *dtostrf(double number, signed char width, unsigned char prec, char *s) { - char fmt[20]; // just for the formating in sprintf() - uint8_t numSize = 0; - int maxPrec; - - if (isnan(number)) { - strcpy(s, "nan"); - return s; - } - if (isinf(number)) { - strcpy(s, "inf"); - return s; - } - - // calculates how many characters the integer part of the float will take - if (number < 0) { // number is negative - numSize = 1; // for the '-' simbol - } - double n = fabs(number); - do { - numSize++; - n = n / 10; - } while (n > 1); - if (prec) numSize += 1; // for the '.' - // avoiding Stack smashing protect failure! - maxPrec = width - numSize; - if (prec) prec = maxPrec > 0 ? maxPrec : 0; - - sprintf(fmt, "%%%d.%df", numSize, prec); - sprintf(s, fmt, number); - return s; -} -#else -// orginal code from Arduino ESP8266 char * dtostrf(double number, signed char width, unsigned char prec, char *s) { bool negative = false; @@ -197,4 +160,3 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { *out = 0; return s; } -#endif From 7cbd148d5d3d5c2fbda5dbfc501b3625942d1e0b Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Sun, 16 Jan 2022 20:45:43 -0300 Subject: [PATCH 5/7] Fixes String(float) issue with Stack Smashing --- cores/esp32/WString.cpp | 4 ++-- cores/esp32/WString.h | 4 ++-- cores/esp32/stdlib_noniso.c | 4 ++-- cores/esp32/stdlib_noniso.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cores/esp32/WString.cpp b/cores/esp32/WString.cpp index 1021570211e..8e6d2be84ee 100644 --- a/cores/esp32/WString.cpp +++ b/cores/esp32/WString.cpp @@ -112,13 +112,13 @@ String::String(unsigned long value, unsigned char base) { *this = buf; } -String::String(float value, unsigned char decimalPlaces) { +String::String(float value, unsigned int decimalPlaces) { init(); char *buf = (char*)malloc(decimalPlaces + 42); *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); free(buf);} -String::String(double value, unsigned char decimalPlaces) { +String::String(double value, unsigned int decimalPlaces) { init(); char *buf = (char*)malloc(decimalPlaces + 312); *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); diff --git a/cores/esp32/WString.h b/cores/esp32/WString.h index 958b01792e8..3190a247dda 100644 --- a/cores/esp32/WString.h +++ b/cores/esp32/WString.h @@ -71,8 +71,8 @@ class String { explicit String(unsigned int, unsigned char base = 10); explicit String(long, unsigned char base = 10); explicit String(unsigned long, unsigned char base = 10); - explicit String(float, unsigned char decimalPlaces = 2); - explicit String(double, unsigned char decimalPlaces = 2); + explicit String(float, unsigned int decimalPlaces = 2); + explicit String(double, unsigned int decimalPlaces = 2); ~String(void); // memory management diff --git a/cores/esp32/stdlib_noniso.c b/cores/esp32/stdlib_noniso.c index 8f24520dac3..99168d14506 100644 --- a/cores/esp32/stdlib_noniso.c +++ b/cores/esp32/stdlib_noniso.c @@ -88,7 +88,7 @@ char* ultoa(unsigned long value, char* result, int base) { return result; } -char * dtostrf(double number, signed char width, unsigned char prec, char *s) { +char * dtostrf(double number, signed char width, unsigned int prec, char *s) { bool negative = false; if (isnan(number)) { @@ -117,7 +117,7 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { // Round correctly so that print(1.999, 2) prints as "2.00" // I optimized out most of the divisions double rounding = 2.0; - for (uint8_t i = 0; i < prec; ++i) + for (uint32_t i = 0; i < prec; ++i) rounding *= 10.0; rounding = 1.0 / rounding; diff --git a/cores/esp32/stdlib_noniso.h b/cores/esp32/stdlib_noniso.h index 3df2cc2a1b6..308efbbce09 100644 --- a/cores/esp32/stdlib_noniso.h +++ b/cores/esp32/stdlib_noniso.h @@ -39,7 +39,7 @@ char* utoa (unsigned int val, char *s, int radix); char* ultoa (unsigned long val, char *s, int radix); -char* dtostrf (double val, signed char width, unsigned char prec, char *s); +char* dtostrf (double val, signed char width, unsigned int prec, char *s); #ifdef __cplusplus } // extern "C" From 90e5b044791d9ac1ee38860deebd062955db3ee6 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Sun, 16 Jan 2022 20:59:34 -0300 Subject: [PATCH 6/7] Fixes String(float) issue with Stack Smashing --- cores/esp32/stdlib_noniso.c | 2 +- cores/esp32/stdlib_noniso.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cores/esp32/stdlib_noniso.c b/cores/esp32/stdlib_noniso.c index 99168d14506..e66edace7e3 100644 --- a/cores/esp32/stdlib_noniso.c +++ b/cores/esp32/stdlib_noniso.c @@ -88,7 +88,7 @@ char* ultoa(unsigned long value, char* result, int base) { return result; } -char * dtostrf(double number, signed char width, unsigned int prec, char *s) { +char * dtostrf(double number, signed int width, unsigned int prec, char *s) { bool negative = false; if (isnan(number)) { diff --git a/cores/esp32/stdlib_noniso.h b/cores/esp32/stdlib_noniso.h index 308efbbce09..e5bb44e563a 100644 --- a/cores/esp32/stdlib_noniso.h +++ b/cores/esp32/stdlib_noniso.h @@ -39,7 +39,7 @@ char* utoa (unsigned int val, char *s, int radix); char* ultoa (unsigned long val, char *s, int radix); -char* dtostrf (double val, signed char width, unsigned int prec, char *s); +char* dtostrf (double val, signed int width, unsigned int prec, char *s); #ifdef __cplusplus } // extern "C" From 8eafb5efeeccf1a8ebca7cd8944c92f059f21aa9 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Sun, 16 Jan 2022 22:05:53 -0300 Subject: [PATCH 7/7] Fixes String(float) issue with Stack Smashing --- cores/esp32/WString.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/cores/esp32/WString.cpp b/cores/esp32/WString.cpp index 8e6d2be84ee..ded2a3c1e78 100644 --- a/cores/esp32/WString.cpp +++ b/cores/esp32/WString.cpp @@ -115,14 +115,25 @@ String::String(unsigned long value, unsigned char base) { String::String(float value, unsigned int decimalPlaces) { init(); char *buf = (char*)malloc(decimalPlaces + 42); - *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); - free(buf);} + if (buf) { + *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); + free(buf); + } else { + *this = "nan"; + log_e("No enought memory for the operation."); + } +} String::String(double value, unsigned int decimalPlaces) { init(); char *buf = (char*)malloc(decimalPlaces + 312); - *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); - free(buf); + if (buf) { + *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); + free(buf); + } else { + *this = "nan"; + log_e("No enought memory for the operation."); + } } String::~String() {