CVE-2007-6109.diff   [plain text]


--- src/editfns.c	2007/08/08 07:49:19	1.439.2.3
+++ src/editfns.c	2007/11/23 13:27:12	1.439.2.9
@@ -3543,8 +3543,10 @@
 	      precision[n+1] = 10 * precision[n+1] + *format - '0';
 	  }
 
-	if (format - this_format_start + 1 > longest_format)
-	  longest_format = format - this_format_start + 1;
+	/* Extra +1 for 'l' that we may need to insert into the
+	   format.  */
+	if (format - this_format_start + 2 > longest_format)
+	  longest_format = format - this_format_start + 2;
 
 	if (format == end)
 	  error ("Format string ends in middle of format specifier");
@@ -3605,7 +3607,7 @@
 		  && *format != 'i' && *format != 'X' && *format != 'c')
 		error ("Invalid format operation %%%c", *format);
 
-	    thissize = 30;
+	    thissize = 30 + (precision[n] > 0 ? precision[n] : 0);
 	    if (*format == 'c')
 	      {
 		if (! SINGLE_BYTE_CHAR_P (XINT (args[n]))
@@ -3803,23 +3805,40 @@
 		     format - this_format_start);
 	      this_format[format - this_format_start] = 0;
 
-	      if (INTEGERP (args[n]))
+	      if (format[-1] == 'e' || format[-1] == 'f' || format[-1] == 'g')
+		sprintf (p, this_format, XFLOAT_DATA (args[n]));
+	      else
 		{
-		  if (format[-1] == 'd')
-		    sprintf (p, this_format, XINT (args[n]));
-		  /* Don't sign-extend for octal or hex printing.  */
+		  if (sizeof (EMACS_INT) > sizeof (int)
+		      && format[-1] != 'c')
+		    {
+		      /* Insert 'l' before format spec.  */
+		      this_format[format - this_format_start]
+			= this_format[format - this_format_start - 1];
+		      this_format[format - this_format_start - 1] = 'l';
+		      this_format[format - this_format_start + 1] = 0;
+		    }
+
+		  if (INTEGERP (args[n]))
+		    {
+		      if (format[-1] == 'c')
+			sprintf (p, this_format, (int) XINT (args[n]));
+		      else if (format[-1] == 'd')
+			sprintf (p, this_format, XINT (args[n]));
+		      /* Don't sign-extend for octal or hex printing.  */
+		      else
+			sprintf (p, this_format, XUINT (args[n]));
+		    }
+		  else if (format[-1] == 'c')
+		    sprintf (p, this_format, (int) XFLOAT_DATA (args[n]));
+		  else if (format[-1] == 'd')
+		    /* Maybe we should use "%1.0f" instead so it also works
+		       for values larger than MAXINT.  */
+		    sprintf (p, this_format, (EMACS_INT) XFLOAT_DATA (args[n]));
 		  else
-		    sprintf (p, this_format, XUINT (args[n]));
+		    /* Don't sign-extend for octal or hex printing.  */
+		    sprintf (p, this_format, (EMACS_UINT) XFLOAT_DATA (args[n]));
 		}
-	      else if (format[-1] == 'e' || format[-1] == 'f' || format[-1] == 'g')
-		sprintf (p, this_format, XFLOAT_DATA (args[n]));
-	      else if (format[-1] == 'd')
-		/* Maybe we should use "%1.0f" instead so it also works
-		   for values larger than MAXINT.  */
-		sprintf (p, this_format, (EMACS_INT) XFLOAT_DATA (args[n]));
-	      else
-		/* Don't sign-extend for octal or hex printing.  */
-		sprintf (p, this_format, (EMACS_UINT) XFLOAT_DATA (args[n]));
 
 	      if (p > buf
 		  && multibyte