# HG changeset patch # User Paul Eggert # Date 854395972 0 # Node ID e7814b054e91d487ca5b4a0329a7026db5795008 # Parent eca5dfcd481d552c4c03dbbe13747e648f40e493 Include 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. diff -r eca5dfcd481d -r e7814b054e91 src/doprnt.c --- a/src/doprnt.c Mon Jan 27 05:23:31 1997 +0000 +++ b/src/doprnt.c Mon Jan 27 20:12:52 1997 +0000 @@ -26,6 +26,14 @@ #include #include "lisp.h" +#if STDC_HEADERS +#include +#endif + +#ifndef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 308 /* IEEE double */ +#endif + extern long *xmalloc (), *xrealloc (); static int doprnt1 (); @@ -80,10 +88,10 @@ register char *bufptr = buffer; /* Pointer into output buffer.. */ /* Use this for sprintf unless we need something really big. */ - char tembuf[100]; + char tembuf[DBL_MAX_10_EXP + 100]; /* Size of sprintf_buffer. */ - int size_allocated = 100; + int size_allocated = sizeof (tembuf); /* Buffer to use for sprintf. Either tembuf or same as BIG_BUFFER. */ char *sprintf_buffer = tembuf; @@ -114,7 +122,7 @@ { if (*fmt == '%') /* Check for a '%' character */ { - int size_bound; + int size_bound = 0; fmt++; /* Copy this one %-spec into fmtcpy. */ @@ -123,22 +131,38 @@ while (1) { *string++ = *fmt; - if (! (*fmt >= '0' && *fmt <= '9') - && *fmt != '-' && *fmt != ' '&& *fmt != '.') + if ('0' <= *fmt && *fmt <= '9') + { + /* Get an idea of how much space we might need. + This might be a field width or a precision; e.g. + %1.1000f and %1000.1f both might need 1000+ bytes. + Parse the width or precision, checking for overflow. */ + int n = *fmt - '0'; + while ('0' <= fmt[1] && fmt[1] <= '9') + { + if (n * 10 / 10 != n + || (n = n * 10 + (fmt[1] - '0')) < 0) + error ("Format width or precision too large"); + *string++ = *++fmt; + } + + if (size_bound < n) + size_bound = n; + } + else if (*fmt == '-' || *fmt == ' ' || *fmt == '.') + ; + else break; fmt++; } *string = 0; - /* Get an idea of how much space we might need. */ - size_bound = atoi (&fmtcpy[1]); - /* Avoid pitfall of negative "size" parameter ("%-200d"). */ + /* Make the size bound large enough to handle floating point formats + with large numbers. */ + size_bound += DBL_MAX_10_EXP + 50; + if (size_bound < 0) - size_bound = -size_bound; - size_bound += 50; - - if (size_bound > (((unsigned) 1) << (BITS_PER_INT - 1))) - error ("Format padding too large"); + error ("Format width or precision too large"); /* Make sure we have that much. */ if (size_bound > size_allocated)