changeset 4298:374bfdd48d05

From GNU libc. (my_strftime): Handle very large width specifications for numeric values correctly. Improve checks for overflow.
author Jim Meyering <jim@meyering.net>
date Fri, 11 Apr 2003 14:59:01 +0000
parents 30aa99ec2725
children 4bed74364766
files lib/strftime.c
diffstat 1 files changed, 42 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/lib/strftime.c
+++ b/lib/strftime.c
@@ -265,7 +265,7 @@
       int _n = (n);							      \
       int _delta = width - _n;						      \
       int _incr = _n + (_delta > 0 ? _delta : 0);			      \
-      if (i + _incr >= maxsize)						      \
+      if ((size_t) _incr >= maxsize - i)				      \
 	return 0;							      \
       if (p)								      \
 	{								      \
@@ -748,8 +748,15 @@
 	  width = 0;
 	  do
 	    {
-	      width *= 10;
-	      width += *f - L_('0');
+	      if (width > INT_MAX / 10
+		  || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 10))
+		/* Avoid overflow.  */
+		width = INT_MAX;
+	      else
+		{
+		  width *= 10;
+		  width += *f - L_('0');
+		}
 	      ++f;
 	    }
 	  while (ISDIGIT (*f));
@@ -773,10 +780,10 @@
       switch (format_char)
 	{
 #define DO_NUMBER(d, v) \
-	  digits = width == -1 ? d : width;				      \
+	  digits = d > width ? d : width;				      \
 	  number_value = v; goto do_number
 #define DO_NUMBER_SPACEPAD(d, v) \
-	  digits = width == -1 ? d : width;				      \
+	  digits = d > width ? d : width;				      \
 	  number_value = v; goto do_number_spacepad
 
 	case L_('%'):
@@ -1033,18 +1040,37 @@
 	      int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
 				      - bufp);
 
-	      if (pad == L_('_'))
+	      if (padding > 0)
 		{
-		  while (0 < padding--)
-		    *--bufp = L_(' ');
-		}
-	      else
-		{
-		  bufp += negative_number;
-		  while (0 < padding--)
-		    *--bufp = L_('0');
-		  if (negative_number)
-		    *--bufp = L_('-');
+		  if (pad == L_('_'))
+		    {
+		      if ((size_t) padding >= maxsize - i)
+			return 0;
+
+		      if (p)
+			memset_space (p, padding);
+		      i += padding;
+		      width = width > padding ? width - padding : 0;
+		    }
+		  else
+		    {
+		      if ((size_t) digits >= maxsize - i)
+			return 0;
+
+		      if (negative_number)
+			{
+			  ++bufp;
+
+			  if (p)
+			    *p++ = L_('-');
+			  ++i;
+			}
+
+		      if (p)
+			memset_zero (p, padding);
+		      i += padding;
+		      width = 0;
+		    }
 		}
 	    }