diff options
author | das <das@FreeBSD.org> | 2003-04-05 22:03:43 +0000 |
---|---|---|
committer | das <das@FreeBSD.org> | 2003-04-05 22:03:43 +0000 |
commit | c0e486bd07885ad47b68f40cdb8d55c8811ed08a (patch) | |
tree | 826bf02ef4bdb923996387c17705464f14a5d35d /lib | |
parent | c0badd1444fc63c006a6fdf38d80d02fa22aa919 (diff) | |
download | FreeBSD-src-c0e486bd07885ad47b68f40cdb8d55c8811ed08a.zip FreeBSD-src-c0e486bd07885ad47b68f40cdb8d55c8811ed08a.tar.gz |
Correct some buffer sizes.
- __vfprintf()'s 'buf' has never been used for floating point, so
don't define it in terms of (incorrect) constants describing
floating point numbers. The actual size needed depends on
sizeof(uintmax_t) and locale details, so I slightly overestimated.
- We don't need a 308-character buffer to store the string "308".
With long doubles and %a we need more than three characters, though.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/stdio/floatio.h | 15 | ||||
-rw-r--r-- | lib/libc/stdio/vfprintf.c | 26 | ||||
-rw-r--r-- | lib/libc/stdio/vfwprintf.c | 24 |
3 files changed, 42 insertions, 23 deletions
diff --git a/lib/libc/stdio/floatio.h b/lib/libc/stdio/floatio.h index a40df00..22fedcd 100644 --- a/lib/libc/stdio/floatio.h +++ b/lib/libc/stdio/floatio.h @@ -41,7 +41,14 @@ * Floating point scanf/printf (input/output) definitions. */ -/* 11-bit exponent (VAX G floating point) is 308 decimal digits */ -#define MAXEXP 308 -/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */ -#define MAXFRACT 39 +/* + * MAXEXPDIG is the maximum number of decimal digits needed to store a + * floating point exponent in the largest supported format. It should + * be ceil(log10(LDBL_MAX_10_EXP)) or, if hexadecimal floating point + * conversions are supported, ceil(log10(LDBL_MAX_EXP)). But since it + * is presently never greater than 5 in practice, we fudge it. + */ +#define MAXEXPDIG 6 +#if LDBL_MAX_EXP > 999999 +#error "floating point buffers too small" +#endif diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c index 5ade7fe..3fb7801 100644 --- a/lib/libc/stdio/vfprintf.c +++ b/lib/libc/stdio/vfprintf.c @@ -410,7 +410,6 @@ vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) #include <math.h> #include "floatio.h" -#define BUF ((MAXEXP*2)+MAXFRACT+1) /* + decimal point */ #define DEFPREC 6 extern char *__dtoa(double, int, int, int *, int *, char **); @@ -419,12 +418,17 @@ extern void __freedtoa(char *s); static char *cvt(double, int, int, char *, int *, int, int *); static int exponent(char *, int, int); -#else /* no FLOATING_POINT */ - -#define BUF 136 - #endif /* FLOATING_POINT */ +/* + * The size of the buffer we use as scratch space for integer + * conversions, among other things. Technically, we would need the + * most space for base 10 conversions with thousands' grouping + * characters between each pair of digits. 100 bytes is a + * conservative overestimate even for a 128-bit uintmax_t. + */ +#define BUF 100 + #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */ /* @@ -471,7 +475,7 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap) int expt; /* integer value of exponent */ int expsize; /* character count for expstr */ int ndig; /* actual number of digits returned by cvt */ - char expstr[7]; /* buffer for exponent string */ + char expstr[MAXEXPDIG+2]; /* buffer for exponent string */ char *dtoaresult; /* buffer allocated by dtoa */ #endif u_long ulval; /* integer arguments %[diouxX] */ @@ -485,7 +489,7 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap) #define NIOV 8 struct __suio uio; /* output information: summary */ struct __siov iov[NIOV];/* ... and individual io vectors */ - char buf[BUF]; /* space for %c, %[diouxX], %[eEfFgG] */ + char buf[BUF]; /* buffer with space for digits of uintmax_t */ char ox[2]; /* space for 0x hex-prefix */ union arg *argtable; /* args, built due to positional arg */ union arg statargtable [STATIC_ARG_TBL_SIZE]; @@ -1022,6 +1026,8 @@ number: if ((dprec = prec) >= 0) grouping); } size = buf + BUF - cp; + if (size > BUF) /* should never happen */ + abort(); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') @@ -1553,7 +1559,7 @@ static int exponent(char *p0, int exp, int fmtch) { char *p, *t; - char expbuf[MAXEXP]; + char expbuf[MAXEXPDIG]; p = p0; *p++ = fmtch; @@ -1563,13 +1569,13 @@ exponent(char *p0, int exp, int fmtch) } else *p++ = '+'; - t = expbuf + MAXEXP; + t = expbuf + MAXEXPDIG; if (exp > 9) { do { *--t = to_char(exp % 10); } while ((exp /= 10) > 9); *--t = to_char(exp); - for (; t < expbuf + MAXEXP; *p++ = *t++); + for (; t < expbuf + MAXEXPDIG; *p++ = *t++); } else { *p++ = '0'; diff --git a/lib/libc/stdio/vfwprintf.c b/lib/libc/stdio/vfwprintf.c index 7ed7187..7f1a627 100644 --- a/lib/libc/stdio/vfwprintf.c +++ b/lib/libc/stdio/vfwprintf.c @@ -403,7 +403,6 @@ vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap) #include <math.h> #include "floatio.h" -#define BUF ((MAXEXP*2)+MAXFRACT+1) /* + decimal point */ #define DEFPREC 6 extern char *__dtoa(double, int, int, int *, int *, char **); @@ -412,12 +411,17 @@ extern void __freedtoa(char *s); static wchar_t *cvt(double, int, int, char *, int *, wchar_t, int *); static int exponent(wchar_t *, int, wchar_t); -#else /* no FLOATING_POINT */ - -#define BUF 136 - #endif /* FLOATING_POINT */ +/* + * The size of the buffer we use as scratch space for integer + * conversions, among other things. Technically, we would need the + * most space for base 10 conversions with thousands' grouping + * characters between each pair of digits. 100 bytes is a + * conservative overestimate even for a 128-bit uintmax_t. + */ +#define BUF 100 + #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */ /* @@ -474,7 +478,7 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap) int size; /* size of converted field or string */ int prsize; /* max size of printed field */ wchar_t *xdigs; /* digits for [xX] conversion */ - wchar_t buf[BUF]; /* space for %c, %[diouxX], %[eEfFgG] */ + wchar_t buf[BUF]; /* buffer with space for digits of uintmax_t */ wchar_t ox[2]; /* space for 0x hex-prefix */ union arg *argtable; /* args, built due to positional arg */ union arg statargtable [STATIC_ARG_TBL_SIZE]; @@ -988,6 +992,8 @@ number: if ((dprec = prec) >= 0) grouping); } size = buf + BUF - cp; + if (size > BUF) /* should never happen */ + abort(); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') @@ -1524,7 +1530,7 @@ static int exponent(wchar_t *p0, int exp, wchar_t fmtch) { wchar_t *p, *t; - wchar_t expbuf[MAXEXP]; + wchar_t expbuf[MAXEXPDIG]; p = p0; *p++ = fmtch; @@ -1534,13 +1540,13 @@ exponent(wchar_t *p0, int exp, wchar_t fmtch) } else *p++ = '+'; - t = expbuf + MAXEXP; + t = expbuf + MAXEXPDIG; if (exp > 9) { do { *--t = to_char(exp % 10); } while ((exp /= 10) > 9); *--t = to_char(exp); - for (; t < expbuf + MAXEXP; *p++ = *t++); + for (; t < expbuf + MAXEXPDIG; *p++ = *t++); } else { *p++ = '0'; |