diff options
author | Damien George <damien.p.george@gmail.com> | 2016-03-15 12:21:56 +0000 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2016-03-15 12:21:56 +0000 |
commit | cea6cf8a5e87127eccc8214cbffa2d4c8aae8527 (patch) | |
tree | 80db64fb94740c2fa290589ef3df72bb38b6b5bd | |
parent | 0d1f8868b616254ee5df9a039da176c900fc6ee6 (diff) | |
download | micropython-cea6cf8a5e87127eccc8214cbffa2d4c8aae8527.tar.gz micropython-cea6cf8a5e87127eccc8214cbffa2d4c8aae8527.zip |
py/formatfloat: Fix buffer overflow when formatting tiny numbers.
-rw-r--r-- | py/formatfloat.c | 14 | ||||
-rw-r--r-- | tests/float/string_format_modulo.py | 16 |
2 files changed, 26 insertions, 4 deletions
diff --git a/py/formatfloat.c b/py/formatfloat.c index b2107316f0..f7762b07dd 100644 --- a/py/formatfloat.c +++ b/py/formatfloat.c @@ -27,6 +27,7 @@ #include "py/mpconfig.h" #if MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_NONE +#include <assert.h> #include <stdlib.h> #include <stdint.h> #include "py/formatfloat.h" @@ -210,13 +211,15 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch dec = -1; *s++ = first_dig; - if (prec + e + 1 > buf_remaining) { - prec = buf_remaining - e - 1; - } - if (org_fmt == 'g') { prec += (e - 1); } + + // truncate precision to prevent buffer overflow + if (prec + 2 > buf_remaining) { + prec = buf_remaining - 2; + } + num_digits = prec; if (num_digits) { *s++ = '.'; @@ -390,6 +393,9 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch } *s = '\0'; + // verify that we did not overrun the input buffer + assert((size_t)(s + 1 - buf) <= buf_size); + return s - buf; } diff --git a/tests/float/string_format_modulo.py b/tests/float/string_format_modulo.py index 03b178703f..681e9eb806 100644 --- a/tests/float/string_format_modulo.py +++ b/tests/float/string_format_modulo.py @@ -26,3 +26,19 @@ print("%02.3d" % 123) # prec > width print("%+f %+f" % (1.23, -1.23)) # float sign print("% f % f" % (1.23, -1.23)) # float space sign print("%0f" % -1.23) # negative number with 0 padding + +# numbers with large negative exponents +print('%f' % 1e-10) +print('%f' % 1e-20) +print('%f' % 1e-50) +print('%f' % 1e-100) +print('%f' % 1e-300) + +# large decimal precision should be truncated and not overflow buffer +# the output depends on the FP calculation so only first 2 digits are printed +# (the 'g' with small e are printed using 'f' style, so need to be checked) +print(('%.40f' % 1e-300)[:2]) +print(('%.40g' % 1e-1)[:2]) +print(('%.40g' % 1e-2)[:2]) +print(('%.40g' % 1e-3)[:2]) +print(('%.40g' % 1e-4)[:2]) |