]> git.eshelyaron.com Git - emacs.git/commitdiff
Include <float.h> if STDC_HEADERS.
authorPaul Eggert <eggert@twinsun.com>
Mon, 27 Jan 1997 20:12:52 +0000 (20:12 +0000)
committerPaul Eggert <eggert@twinsun.com>
Mon, 27 Jan 1997 20:12:52 +0000 (20:12 +0000)
(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.

src/doprnt.c

index d9b6566b1bc3aabb112c810a320888abc5ac414f..aa0b2c20055bbe14dd96bb99208643644994eec5 100644 (file)
@@ -26,6 +26,14 @@ Boston, MA 02111-1307, USA.  */
 #include <ctype.h>
 #include "lisp.h"
 
+#if STDC_HEADERS
+#include <float.h>
+#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 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
   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 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
     {
       if (*fmt == '%') /* Check for a '%' character */
        {
-         int size_bound;
+         int size_bound = 0;
 
          fmt++;
          /* Copy this one %-spec into fmtcpy.  */
@@ -123,22 +131,38 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
          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"). */
-         if (size_bound < 0)
-           size_bound = -size_bound;
-         size_bound += 50;
+         /* Make the size bound large enough to handle floating point formats
+            with large numbers.  */
+         size_bound += DBL_MAX_10_EXP + 50;
 
-         if (size_bound > (((unsigned) 1) << (BITS_PER_INT - 1)))
-           error ("Format padding too large");
+         if (size_bound < 0)
+           error ("Format width or precision too large");
 
          /* Make sure we have that much.  */
          if (size_bound > size_allocated)