diff options
Diffstat (limited to 'src/doprnt.c')
| -rw-r--r-- | src/doprnt.c | 23 |
1 files changed, 9 insertions, 14 deletions
diff --git a/src/doprnt.c b/src/doprnt.c index 195598c07ea..79f9f36e461 100644 --- a/src/doprnt.c +++ b/src/doprnt.c | |||
| @@ -102,13 +102,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 102 | #include <stdio.h> | 102 | #include <stdio.h> |
| 103 | #include <ctype.h> | 103 | #include <ctype.h> |
| 104 | #include <setjmp.h> | 104 | #include <setjmp.h> |
| 105 | |||
| 106 | #ifdef STDC_HEADERS | ||
| 107 | #include <float.h> | 105 | #include <float.h> |
| 108 | #endif | ||
| 109 | |||
| 110 | #include <unistd.h> | 106 | #include <unistd.h> |
| 111 | |||
| 112 | #include <limits.h> | 107 | #include <limits.h> |
| 113 | 108 | ||
| 114 | #include "lisp.h" | 109 | #include "lisp.h" |
| @@ -134,8 +129,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 134 | String arguments are passed as C strings. | 129 | String arguments are passed as C strings. |
| 135 | Integers are passed as C integers. */ | 130 | Integers are passed as C integers. */ |
| 136 | 131 | ||
| 137 | size_t | 132 | ptrdiff_t |
| 138 | doprnt (char *buffer, register size_t bufsize, const char *format, | 133 | doprnt (char *buffer, ptrdiff_t bufsize, const char *format, |
| 139 | const char *format_end, va_list ap) | 134 | const char *format_end, va_list ap) |
| 140 | { | 135 | { |
| 141 | const char *fmt = format; /* Pointer into format string */ | 136 | const char *fmt = format; /* Pointer into format string */ |
| @@ -145,7 +140,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, | |||
| 145 | char tembuf[DBL_MAX_10_EXP + 100]; | 140 | char tembuf[DBL_MAX_10_EXP + 100]; |
| 146 | 141 | ||
| 147 | /* Size of sprintf_buffer. */ | 142 | /* Size of sprintf_buffer. */ |
| 148 | size_t size_allocated = sizeof (tembuf); | 143 | ptrdiff_t size_allocated = sizeof (tembuf); |
| 149 | 144 | ||
| 150 | /* Buffer to use for sprintf. Either tembuf or same as BIG_BUFFER. */ | 145 | /* Buffer to use for sprintf. Either tembuf or same as BIG_BUFFER. */ |
| 151 | char *sprintf_buffer = tembuf; | 146 | char *sprintf_buffer = tembuf; |
| @@ -164,7 +159,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, | |||
| 164 | if (format_end == 0) | 159 | if (format_end == 0) |
| 165 | format_end = format + strlen (format); | 160 | format_end = format + strlen (format); |
| 166 | 161 | ||
| 167 | if ((format_end - format + 1) < sizeof (fixed_buffer)) | 162 | if (format_end - format < sizeof (fixed_buffer) - 1) |
| 168 | fmtcpy = fixed_buffer; | 163 | fmtcpy = fixed_buffer; |
| 169 | else | 164 | else |
| 170 | SAFE_ALLOCA (fmtcpy, char *, format_end - format + 1); | 165 | SAFE_ALLOCA (fmtcpy, char *, format_end - format + 1); |
| @@ -176,7 +171,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, | |||
| 176 | { | 171 | { |
| 177 | if (*fmt == '%') /* Check for a '%' character */ | 172 | if (*fmt == '%') /* Check for a '%' character */ |
| 178 | { | 173 | { |
| 179 | size_t size_bound = 0; | 174 | ptrdiff_t size_bound = 0; |
| 180 | EMACS_INT width; /* Columns occupied by STRING on display. */ | 175 | EMACS_INT width; /* Columns occupied by STRING on display. */ |
| 181 | int long_flag = 0; | 176 | int long_flag = 0; |
| 182 | int pIlen = sizeof pI - 1; | 177 | int pIlen = sizeof pI - 1; |
| @@ -194,16 +189,16 @@ doprnt (char *buffer, register size_t bufsize, const char *format, | |||
| 194 | This might be a field width or a precision; e.g. | 189 | This might be a field width or a precision; e.g. |
| 195 | %1.1000f and %1000.1f both might need 1000+ bytes. | 190 | %1.1000f and %1000.1f both might need 1000+ bytes. |
| 196 | Parse the width or precision, checking for overflow. */ | 191 | Parse the width or precision, checking for overflow. */ |
| 197 | size_t n = *fmt - '0'; | 192 | ptrdiff_t n = *fmt - '0'; |
| 198 | while (fmt + 1 < format_end | 193 | while (fmt + 1 < format_end |
| 199 | && '0' <= fmt[1] && fmt[1] <= '9') | 194 | && '0' <= fmt[1] && fmt[1] <= '9') |
| 200 | { | 195 | { |
| 201 | /* Avoid size_t overflow. Avoid int overflow too, as | 196 | /* Avoid ptrdiff_t, size_t, and int overflow, as |
| 202 | many sprintfs mishandle widths greater than INT_MAX. | 197 | many sprintfs mishandle widths greater than INT_MAX. |
| 203 | This test is simple but slightly conservative: e.g., | 198 | This test is simple but slightly conservative: e.g., |
| 204 | (INT_MAX - INT_MAX % 10) is reported as an overflow | 199 | (INT_MAX - INT_MAX % 10) is reported as an overflow |
| 205 | even when it's not. */ | 200 | even when it's not. */ |
| 206 | if (n >= min (INT_MAX, SIZE_MAX) / 10) | 201 | if (n >= min (INT_MAX, min (PTRDIFF_MAX, SIZE_MAX)) / 10) |
| 207 | error ("Format width or precision too large"); | 202 | error ("Format width or precision too large"); |
| 208 | n = n * 10 + fmt[1] - '0'; | 203 | n = n * 10 + fmt[1] - '0'; |
| 209 | *string++ = *++fmt; | 204 | *string++ = *++fmt; |
| @@ -235,7 +230,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, | |||
| 235 | 230 | ||
| 236 | /* Make the size bound large enough to handle floating point formats | 231 | /* Make the size bound large enough to handle floating point formats |
| 237 | with large numbers. */ | 232 | with large numbers. */ |
| 238 | if (size_bound > SIZE_MAX - DBL_MAX_10_EXP - 50) | 233 | if (size_bound > min (PTRDIFF_MAX, SIZE_MAX) - DBL_MAX_10_EXP - 50) |
| 239 | error ("Format width or precision too large"); | 234 | error ("Format width or precision too large"); |
| 240 | size_bound += DBL_MAX_10_EXP + 50; | 235 | size_bound += DBL_MAX_10_EXP + 50; |
| 241 | 236 | ||