diff options
| author | Paul Eggert | 1997-01-27 20:12:52 +0000 |
|---|---|---|
| committer | Paul Eggert | 1997-01-27 20:12:52 +0000 |
| commit | be65c2f46a9170da6b9a508df1f31234db21fce0 (patch) | |
| tree | 38ab70b6cf190f9477e6fb1012e0b8f26ef6fd80 /src | |
| parent | dd713b759cbb6a28e3b4b9bdc0d3a92222ed8370 (diff) | |
| download | emacs-be65c2f46a9170da6b9a508df1f31234db21fce0.tar.gz emacs-be65c2f46a9170da6b9a508df1f31234db21fce0.zip | |
Include <float.h> if STDC_HEADERS.
(DBL_MAX_10_EXP): Define if not defined; default is IEEE double.
(doprnt1): Allocate enough buffer space to handle very large floating
point numbers, or very large field widths or precisions.
Detect overflow in field widths or precisions.
Diffstat (limited to 'src')
| -rw-r--r-- | src/doprnt.c | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/src/doprnt.c b/src/doprnt.c index d9b6566b1bc..aa0b2c20055 100644 --- a/src/doprnt.c +++ b/src/doprnt.c | |||
| @@ -26,6 +26,14 @@ Boston, MA 02111-1307, USA. */ | |||
| 26 | #include <ctype.h> | 26 | #include <ctype.h> |
| 27 | #include "lisp.h" | 27 | #include "lisp.h" |
| 28 | 28 | ||
| 29 | #if STDC_HEADERS | ||
| 30 | #include <float.h> | ||
| 31 | #endif | ||
| 32 | |||
| 33 | #ifndef DBL_MAX_10_EXP | ||
| 34 | #define DBL_MAX_10_EXP 308 /* IEEE double */ | ||
| 35 | #endif | ||
| 36 | |||
| 29 | extern long *xmalloc (), *xrealloc (); | 37 | extern long *xmalloc (), *xrealloc (); |
| 30 | 38 | ||
| 31 | static int doprnt1 (); | 39 | static int doprnt1 (); |
| @@ -80,10 +88,10 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args) | |||
| 80 | register char *bufptr = buffer; /* Pointer into output buffer.. */ | 88 | register char *bufptr = buffer; /* Pointer into output buffer.. */ |
| 81 | 89 | ||
| 82 | /* Use this for sprintf unless we need something really big. */ | 90 | /* Use this for sprintf unless we need something really big. */ |
| 83 | char tembuf[100]; | 91 | char tembuf[DBL_MAX_10_EXP + 100]; |
| 84 | 92 | ||
| 85 | /* Size of sprintf_buffer. */ | 93 | /* Size of sprintf_buffer. */ |
| 86 | int size_allocated = 100; | 94 | int size_allocated = sizeof (tembuf); |
| 87 | 95 | ||
| 88 | /* Buffer to use for sprintf. Either tembuf or same as BIG_BUFFER. */ | 96 | /* Buffer to use for sprintf. Either tembuf or same as BIG_BUFFER. */ |
| 89 | char *sprintf_buffer = tembuf; | 97 | char *sprintf_buffer = tembuf; |
| @@ -114,7 +122,7 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args) | |||
| 114 | { | 122 | { |
| 115 | if (*fmt == '%') /* Check for a '%' character */ | 123 | if (*fmt == '%') /* Check for a '%' character */ |
| 116 | { | 124 | { |
| 117 | int size_bound; | 125 | int size_bound = 0; |
| 118 | 126 | ||
| 119 | fmt++; | 127 | fmt++; |
| 120 | /* Copy this one %-spec into fmtcpy. */ | 128 | /* Copy this one %-spec into fmtcpy. */ |
| @@ -123,22 +131,38 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args) | |||
| 123 | while (1) | 131 | while (1) |
| 124 | { | 132 | { |
| 125 | *string++ = *fmt; | 133 | *string++ = *fmt; |
| 126 | if (! (*fmt >= '0' && *fmt <= '9') | 134 | if ('0' <= *fmt && *fmt <= '9') |
| 127 | && *fmt != '-' && *fmt != ' '&& *fmt != '.') | 135 | { |
| 136 | /* Get an idea of how much space we might need. | ||
| 137 | This might be a field width or a precision; e.g. | ||
| 138 | %1.1000f and %1000.1f both might need 1000+ bytes. | ||
| 139 | Parse the width or precision, checking for overflow. */ | ||
| 140 | int n = *fmt - '0'; | ||
| 141 | while ('0' <= fmt[1] && fmt[1] <= '9') | ||
| 142 | { | ||
| 143 | if (n * 10 / 10 != n | ||
| 144 | || (n = n * 10 + (fmt[1] - '0')) < 0) | ||
| 145 | error ("Format width or precision too large"); | ||
| 146 | *string++ = *++fmt; | ||
| 147 | } | ||
| 148 | |||
| 149 | if (size_bound < n) | ||
| 150 | size_bound = n; | ||
| 151 | } | ||
| 152 | else if (*fmt == '-' || *fmt == ' ' || *fmt == '.') | ||
| 153 | ; | ||
| 154 | else | ||
| 128 | break; | 155 | break; |
| 129 | fmt++; | 156 | fmt++; |
| 130 | } | 157 | } |
| 131 | *string = 0; | 158 | *string = 0; |
| 132 | /* Get an idea of how much space we might need. */ | ||
| 133 | size_bound = atoi (&fmtcpy[1]); | ||
| 134 | 159 | ||
| 135 | /* Avoid pitfall of negative "size" parameter ("%-200d"). */ | 160 | /* Make the size bound large enough to handle floating point formats |
| 136 | if (size_bound < 0) | 161 | with large numbers. */ |
| 137 | size_bound = -size_bound; | 162 | size_bound += DBL_MAX_10_EXP + 50; |
| 138 | size_bound += 50; | ||
| 139 | 163 | ||
| 140 | if (size_bound > (((unsigned) 1) << (BITS_PER_INT - 1))) | 164 | if (size_bound < 0) |
| 141 | error ("Format padding too large"); | 165 | error ("Format width or precision too large"); |
| 142 | 166 | ||
| 143 | /* Make sure we have that much. */ | 167 | /* Make sure we have that much. */ |
| 144 | if (size_bound > size_allocated) | 168 | if (size_bound > size_allocated) |