diff options
author | Rich Felker <dalias@aerifal.cx> | 2016-10-19 20:17:16 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2016-10-19 20:17:16 -0400 |
commit | 70d2687d85c314963cf280759b23fd4573ff0d82 (patch) | |
tree | dbbd4b169245294bee78e30f33e1cc22c519be3d /src/stdio | |
parent | aee6abb2400b9a955c2b41166db1c22f63ad42ef (diff) | |
download | musl-70d2687d85c314963cf280759b23fd4573ff0d82.tar.gz musl-70d2687d85c314963cf280759b23fd4573ff0d82.tar.bz2 musl-70d2687d85c314963cf280759b23fd4573ff0d82.tar.xz musl-70d2687d85c314963cf280759b23fd4573ff0d82.zip |
fix integer overflow in float printf needed-precision computation
if the requested precision is close to INT_MAX, adding
LDBL_MANT_DIG/3+8 overflows. in practice the resulting undefined
behavior manifests as a large negative result, which is then used to
compute the new end pointer (z) with a wildly out-of-bounds value
(more overflow, more undefined behavior). the end result is at least
incorrect output and character count (return value); worse things do
not seem to happen, but detailed analysis has not been done.
this patch fixes the overflow by performing the intermediate
computation as unsigned; after division by 9, the final result
necessarily fits in int.
Diffstat (limited to 'src/stdio')
-rw-r--r-- | src/stdio/vfprintf.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index e439a07a..cd17ad70 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -312,7 +312,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) } while (e2<0) { uint32_t carry=0, *b; - int sh=MIN(9,-e2), need=1+(p+LDBL_MANT_DIG/3+8)/9; + int sh=MIN(9,-e2), need=1+(p+LDBL_MANT_DIG/3U+8)/9; for (d=a; d<z; d++) { uint32_t rm = *d & (1<<sh)-1; *d = (*d>>sh) + carry; |