mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-19 16:56:34 +00:00
Berry fix integer and real parser to handle overflows (#23495)
This commit is contained in:
parent
fcf4706914
commit
1cd4e27123
@ -28,6 +28,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
- ESP32-S3 display stability regression from #23397 (#23404)
|
- ESP32-S3 display stability regression from #23397 (#23404)
|
||||||
- DNS setting with `IPAddress4/5` not persisted (#23426)
|
- DNS setting with `IPAddress4/5` not persisted (#23426)
|
||||||
- Berry avoid json parsing for unmatched commands
|
- Berry avoid json parsing for unmatched commands
|
||||||
|
- Berry fix integer and real parser to handle overflows
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
@ -16,6 +16,28 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#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_space(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
|
||||||
#define is_digit(c) ((c) >= '0' && (c) <= '9')
|
#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 */
|
/* hex literal */
|
||||||
str += 2; /* skip 0x or 0X */
|
str += 2; /* skip 0x or 0X */
|
||||||
while ((c = be_char2hex(*str++)) >= 0) {
|
while ((c = be_char2hex(*str++)) >= 0) {
|
||||||
|
if (sum > M_IMAX / 16) goto overflow_pos;
|
||||||
sum = sum * 16 + c;
|
sum = sum * 16 + c;
|
||||||
|
if (sum < 0) goto overflow_pos; /* overflow check */
|
||||||
}
|
}
|
||||||
if (endstr) {
|
if (endstr) {
|
||||||
*endstr = str - 1;
|
*endstr = str - 1;
|
||||||
@ -292,14 +316,30 @@ BERRY_API bint be_str2int(const char *str, const char **endstr)
|
|||||||
c = *str++;
|
c = *str++;
|
||||||
}
|
}
|
||||||
while (is_digit(c)) {
|
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++;
|
c = *str++;
|
||||||
}
|
}
|
||||||
if (endstr) {
|
if (endstr) {
|
||||||
*endstr = str - 1;
|
*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;
|
int c, sign;
|
||||||
breal sum = 0, deci = 0, point = (breal)0.1;
|
breal sum = 0, deci = 0, point = (breal)0.1;
|
||||||
|
|
||||||
skip_space(str);
|
skip_space(str);
|
||||||
sign = c = *str++;
|
sign = c = *str++;
|
||||||
if (c == '+' || c == '-') {
|
if (c == '+' || c == '-') c = *str++; /* skip sign if present */
|
||||||
c = *str++;
|
|
||||||
}
|
/* Integer part with overflow check */
|
||||||
while (is_digit(c)) {
|
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++;
|
c = *str++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fractional part */
|
||||||
if (c == '.') {
|
if (c == '.') {
|
||||||
c = *str++;
|
c = *str++;
|
||||||
while (is_digit(c)) {
|
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;
|
point *= (breal)0.1;
|
||||||
c = *str++;
|
c = *str++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sum = sum + deci;
|
|
||||||
|
sum += deci;
|
||||||
|
if (sum > BREAL_MAX) goto overflow;
|
||||||
|
|
||||||
|
/* Scientific notation */
|
||||||
if (c == 'e' || c == 'E') {
|
if (c == 'e' || c == 'E') {
|
||||||
int e = 0;
|
int e = 0, esign = 1;
|
||||||
breal ratio = (c = *str++) == '-' ? (breal)0.1 : 10;
|
|
||||||
if (c == '+' || c == '-') {
|
|
||||||
c = *str++;
|
c = *str++;
|
||||||
}
|
if (c == '-') { esign = -1; c = *str++; }
|
||||||
|
else if (c == '+') c = *str++;
|
||||||
|
|
||||||
while (is_digit(c)) {
|
while (is_digit(c)) {
|
||||||
e = e * 10 + c - '0';
|
if (e > 300) goto overflow;
|
||||||
|
e = e * 10 + (c - '0');
|
||||||
c = *str++;
|
c = *str++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e *= esign;
|
||||||
|
breal ratio = (e < 0) ? (breal)0.1 : 10;
|
||||||
|
if (e < 0) e = -e;
|
||||||
|
|
||||||
while (e--) {
|
while (e--) {
|
||||||
|
if (e > 0 && sum > BREAL_MAX / ratio) goto overflow;
|
||||||
sum *= ratio;
|
sum *= ratio;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (endstr) {
|
|
||||||
*endstr = str - 1;
|
if (endstr) *endstr = str - 1;
|
||||||
}
|
|
||||||
return sign == '-' ? -sum : sum;
|
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).
|
/* convert a string to a number (integer or real).
|
||||||
|
Loading…
x
Reference in New Issue
Block a user