changeset 16943:e7814b054e91

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.
author Paul Eggert <eggert@twinsun.com>
date Mon, 27 Jan 1997 20:12:52 +0000
parents eca5dfcd481d
children 54108c7f46e6
files src/doprnt.c
diffstat 1 files changed, 37 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- 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 <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 @@
   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)