diff --git a/py/formatfloat.c b/py/formatfloat.c index 78e38831c4..b2107316f0 100644 --- a/py/formatfloat.c +++ b/py/formatfloat.c @@ -56,6 +56,7 @@ #define FPCONST(x) x##F #define FPROUND_TO_ONE 0.9999995F #define FPDECEXP 32 +#define FPMIN_BUF_SIZE 6 // +9e+99 #define FLT_SIGN_MASK 0x80000000 #define FLT_EXP_MASK 0x7F800000 @@ -79,6 +80,7 @@ static inline int fp_isless1(float x) { union floatbits fb = {x}; return fb.u < #define FPCONST(x) x #define FPROUND_TO_ONE 0.999999999995 #define FPDECEXP 256 +#define FPMIN_BUF_SIZE 7 // +9e+199 #include #define fp_signbit(x) signbit(x) #define fp_isspecial(x) 1 @@ -105,11 +107,11 @@ static const FPTYPE g_neg_pow[] = { int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, char sign) { char *s = buf; - int buf_remaining = buf_size - 1; - if (buf_size < 7) { - // Smallest exp notion is -9e+99 which is 6 chars plus terminating - // null. + if (buf_size <= FPMIN_BUF_SIZE) { + // FPMIN_BUF_SIZE is the minimum size needed to store any FP number. + // If the buffer does not have enough room for this (plus null terminator) + // then don't try to format the float. if (buf_size >= 2) { *s++ = '?'; @@ -127,7 +129,10 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch *s++ = sign; } } - buf_remaining -= (s - buf); // Adjust for sign + + // buf_remaining contains bytes available for digits and exponent. + // It is buf_size minus room for the sign and null byte. + int buf_remaining = buf_size - 1 - (s - buf); if (fp_isspecial(f)) { char uc = fmt & 0x20; @@ -226,8 +231,8 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch e_sign = e_sign_char; dec = 0; - if (prec > (buf_remaining - 6)) { - prec = buf_remaining - 6; + if (prec > (buf_remaining - FPMIN_BUF_SIZE)) { + prec = buf_remaining - FPMIN_BUF_SIZE; if (fmt == 'g') { prec++; } @@ -258,8 +263,8 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch } } } - if (fmt == 'e' && prec > (buf_remaining - 6)) { - prec = buf_remaining - 6; + if (fmt == 'e' && prec > (buf_remaining - FPMIN_BUF_SIZE)) { + prec = buf_remaining - FPMIN_BUF_SIZE; } // If the user specified 'g' format, and e is < prec, then we'll switch // to the fixed format. @@ -377,7 +382,10 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch if (e_sign) { *s++ = e_char; *s++ = e_sign; - *s++ = '0' + (e / 10); + if (FPMIN_BUF_SIZE == 7 && e >= 100) { + *s++ = '0' + (e / 100); + } + *s++ = '0' + ((e / 10) % 10); *s++ = '0' + (e % 10); } *s = '\0';