diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c7ecc61b..f39431253 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ All notable changes to this project will be documented in this file. - ESP32-S3 display stability regression from #23397 (#23404) - DNS setting with `IPAddress4/5` not persisted (#23426) - Berry avoid json parsing for unmatched commands +- Berry fix integer and real parser to handle overflows ### Removed diff --git a/lib/libesp32/berry/src/be_strlib.c b/lib/libesp32/berry/src/be_strlib.c index 2ce560910..bd4198e03 100644 --- a/lib/libesp32/berry/src/be_strlib.c +++ b/lib/libesp32/berry/src/be_strlib.c @@ -16,6 +16,28 @@ #include #include #include +#include +#include +#include + +#if BE_INTGER_TYPE == 0 /* int */ + #define M_IMAX INT_MAX + #define M_IMIN INT_MIN +#elif BE_INTGER_TYPE == 1 /* long */ + #define M_IMAX LONG_MAX + #define M_IMIN LONG_MIN +#else /* int64_t (long long) */ + #define M_IMAX LLONG_MAX + #define M_IMIN LLONG_MIN +#endif + +#if BE_USE_SINGLE_FLOAT == 0 /* double */ + #define BREAL_MAX DBL_MAX + #define BREAL_MIN DBL_MIN +#else + #define BREAL_MAX FLT_MAX + #define BREAL_MIN FLT_MIN +#endif #define is_space(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n') #define is_digit(c) ((c) >= '0' && (c) <= '9') @@ -279,7 +301,9 @@ BERRY_API bint be_str2int(const char *str, const char **endstr) /* hex literal */ str += 2; /* skip 0x or 0X */ while ((c = be_char2hex(*str++)) >= 0) { + if (sum > M_IMAX / 16) goto overflow_pos; sum = sum * 16 + c; + if (sum < 0) goto overflow_pos; /* overflow check */ } if (endstr) { *endstr = str - 1; @@ -292,14 +316,30 @@ BERRY_API bint be_str2int(const char *str, const char **endstr) c = *str++; } while (is_digit(c)) { - sum = sum * 10 + c - '0'; + if (sign == '-') { + if (sum < M_IMIN / 10) goto overflow_neg; + sum = sum * 10 - (c - '0'); + if (sum > 0) goto overflow_neg; /* overflow check */ + } else { + if (sum > M_IMAX / 10) goto overflow_pos; + sum = sum * 10 + (c - '0'); + if (sum < 0) goto overflow_pos; /* overflow check */ + } c = *str++; } if (endstr) { *endstr = str - 1; } - return sign == '-' ? -sum : sum; + return sum; } + +overflow_pos: + if (endstr) *endstr = str - 1; + return M_IMAX; + +overflow_neg: + if (endstr) *endstr = str - 1; + return M_IMIN; } /******************************************************************* @@ -317,42 +357,67 @@ BERRY_API breal be_str2real(const char *str, const char **endstr) { int c, sign; breal sum = 0, deci = 0, point = (breal)0.1; + skip_space(str); sign = c = *str++; - if (c == '+' || c == '-') { - c = *str++; - } + if (c == '+' || c == '-') c = *str++; /* skip sign if present */ + + /* Integer part with overflow check */ while (is_digit(c)) { - sum = sum * 10 + c - '0'; + if (sum > BREAL_MAX / 10) goto overflow; + sum = sum * 10 + (c - '0'); + if (sum > BREAL_MAX) goto overflow; c = *str++; } + + /* Fractional part */ if (c == '.') { c = *str++; while (is_digit(c)) { - deci = deci + ((breal)c - '0') * point; + breal digit = (c - '0') * point; + if (deci + digit < deci) break; /* precision limit reached */ + deci += digit; point *= (breal)0.1; c = *str++; } } - sum = sum + deci; + + sum += deci; + if (sum > BREAL_MAX) goto overflow; + + /* Scientific notation */ if (c == 'e' || c == 'E') { - int e = 0; - breal ratio = (c = *str++) == '-' ? (breal)0.1 : 10; - if (c == '+' || c == '-') { - c = *str++; - } + int e = 0, esign = 1; + c = *str++; + if (c == '-') { esign = -1; c = *str++; } + else if (c == '+') c = *str++; + while (is_digit(c)) { - e = e * 10 + c - '0'; + if (e > 300) goto overflow; + e = e * 10 + (c - '0'); c = *str++; } + + e *= esign; + breal ratio = (e < 0) ? (breal)0.1 : 10; + if (e < 0) e = -e; + while (e--) { + if (e > 0 && sum > BREAL_MAX / ratio) goto overflow; sum *= ratio; } } - if (endstr) { - *endstr = str - 1; - } + + if (endstr) *endstr = str - 1; return sign == '-' ? -sum : sum; + +overflow: + if (endstr) *endstr = str - 1; +#if BE_USE_SINGLE_FLOAT == 0 + return sign == '-' ? -HUGE_VAL : HUGE_VAL; +#else + return sign == '-' ? -HUGE_VALF : HUGE_VALF; +#endif } /* convert a string to a number (integer or real).