Subject: bug#9412: closed (patch committed)

From: [email-masked] (GNU bug Tracking System)
Date: Sun, 04 Sep 2011 22:00:05 +0000

Your bug report

#9412: sprintf-related integer and memory overflow issues

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
9412: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=9412
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: patch committed
From: Paul Eggert <[email-masked]>
To: [email-masked], [email-masked]
Date: Sun, 04 Sep 2011 14:56:09 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

I committed the patch for this bug into the trunk
as bzr 105655 and am marking the bug as done.

Subject: sprintf-related integer and memory overflow issues
From: Paul Eggert <[email-masked]>
To: [email-masked]
Date: Tue, 30 Aug 2011 15:42:58 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

Package: Emacs
Version: 24.0.50
Tags: patch

Here's a patch to the Emacs trunk to fix some sprintf-related integer
and memory overflow issues in Emacs proper.  These bugs can cause the
wrong integer to be displayed, or a buffer overrun in sprintf output,
that sort of thing.  Almost all the bugs can occur independently of
whether --with-wide-int is used.  The bugs range from unlikely to
extremely unlikely in normal use (otherwise they would have been fixed
already....).  The patch is (I hope) routine.  I plan to install this
patch after some more internal testing.

Here's an example bug.  Arrange for the DISPLAY environment variable
to use a host name that is longer than about 250 bytes.  One way to do
this is to set DISPLAY='127.0.00000000000000.1:10.0' (but use 250 more zeros).
Run Emacs under X, and then arrange for the X server's connection to
be dropped.  The Emacs function x_io_error_quitter will do this:

    char buf[256];
    sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));

and the long host name will overrun BUF.

=== modified file 'src/ChangeLog'
--- src/ChangeLog	2011-08-30 18:15:53 +0000
+++ src/ChangeLog	2011-08-30 21:16:49 +0000
@@ -1,3 +1,109 @@
+2011-08-30  Paul Eggert  <[email-masked]>
+
+	sprintf-related integer and memory overflow issues.
+
+	* doprnt.c (doprnt): Support printing ptrdiff_t and intmax_t values.
+	(esprintf, esnprintf, exprintf, evxprintf): New functions.
+	* keyboard.c (command_loop_level): Now EMACS_INT, not int.
+	(cmd_error): kbd macro iterations count is now EMACS_INT, not int.
+	(modify_event_symbol): Do not assume that the length of
+	name_alist_or_stem is safe to alloca and fits in int.
+	(Fexecute_extended_command): Likewise for function name and binding.
+	(Frecursion_depth): Wrap around reliably on integer overflow.
+	* keymap.c (push_key_description): First arg is now EMACS_INT, not int,
+	since some callers pass EMACS_INT values.
+	(Fsingle_key_description): Don't crash if symbol name contains more
+	than MAX_ALLOCA bytes.
+	* minibuf.c (minibuf_level): Now EMACS_INT, not int.
+	(get_minibuffer): Arg is now EMACS_INT, not int.
+	* lisp.h (get_minibuffer, push_key_description): Reflect API changes.
+	(esprintf, esnprintf, exprintf, evxprintf): New decls.
+	* window.h (command_loop_level, minibuf_level): Reflect API changes.
+
+	* dbusbind.c (signature_cat): New function.
+	(xd_signature, Fdbus_register_signal):
+	Do not overrun buffer; instead, report string overflow.
+
+	* dispnew.c (add_window_display_history): Don't overrun buffer.
+	Truncate instead; this is OK since it's just a log.
+
+	* editfns.c (Fcurrent_time_zone): Don't overrun buffer
+	even if the time zone offset is outlandishly large.
+	Don't mishandle offset == INT_MIN.
+
+	* emacs.c (main) [NS_IMPL_COCOA]: Don't overrun buffer
+	when creating daemon; the previous buffer-overflow check was incorrect.
+
+	* eval.c (verror): Simplify by rewriting in terms of evxprintf,
+	which has the guts of the old verror function.
+
+	* filelock.c (lock_file_1, lock_file): Don't blindly alloca long name;
+	use SAFE_ALLOCA instead.  Use esprintf to avoid int-overflow issues.
+
+	* font.c: Include <float.h>, for DBL_MAX_10_EXP.
+	(font_unparse_xlfd): Don't blindly alloca long strings.
+	Don't assume XINT result fits in int, or that XFLOAT_DATA * 10
+	fits in int, when using sprintf.  Use single snprintf to count
+	length of string rather than counting it via multiple sprintfs;
+	that's simpler and more reliable.
+	(APPEND_SPRINTF): New macro.
+	(font_unparse_fcname): Use it to avoid sprintf buffer overrun.
+	(generate_otf_features) [0 && HAVE_LIBOTF]: Use esprintf, not
+	sprintf, in case result does not fit in int.
+
+	* fontset.c (num_auto_fontsets): Now printmax_t, not int.
+	(fontset_from_font): Print it.
+
+	* frame.c (tty_frame_count): Now printmax_t, not int.
+	(make_terminal_frame, set_term_frame_name): Print it.
+	(x_report_frame_params): In X, window IDs are unsigned long,
+	not signed long, so print them as unsigned.
+	(validate_x_resource_name): Check for implausibly long names,
+	and don't assume name length fits in 'int'.
+	(x_get_resource_string): Don't blindly alloca invocation name;
+	use SAFE_ALLOCA.  Use esprintf, not sprintf, in case result does
+	not fit in int.
+
+	* gtkutil.c: Include <float.h>, for DBL_MAX_10_EXP.
+	(xg_check_special_colors, xg_set_geometry):
+	Make sprintf buffers a bit bigger, to avoid potential buffer overrun.
+
+	* lread.c (dir_warning): Don't blindly alloca buffer; use SAFE_ALLOCA.
+	Use esprintf, not sprintf, in case result does not fit in int.
+
+	* macros.c (executing_kbd_macro_iterations): Now EMACS_INT, not int.
+	(Fend_kbd_macro): Don't mishandle MOST_NEGATIVE_FIXNUM by treating
+	it as a large positive number.
+	(Fexecute_kbd_macro): Don't assume repeat count fits in int.
+	* macros.h (executing_kbd_macro_iterations): Now EMACS_INT, not int.
+
+	* nsterm.m ((NSSize)windowWillResize): Use esprintf, not sprintf,
+	in case result does not fit in int.
+
+	* print.c (float_to_string): Detect width overflow more reliably.
+	(print_object): Make sprintf buffer a bit bigger, to avoid potential
+	buffer overrun.  Don't assume list length fits in 'int'.  Treat
+	print length of 0 as 0, not as infinity; to be consistent with other
+	uses of print length in this function.  Don't overflow print length
+	index.  Don't assume hash table size fits in 'long', or that
+	vectorlike size fits in 'unsigned long'.
+
+	* process.c (make_process): Use printmax_t, not int, to format
+	process-name gensyms.
+
+	* term.c (produce_glyphless_glyph): Make sprintf buffer a bit bigger
+	to avoid potential buffer overrun.
+
+	* xfaces.c (x_update_menu_appearance): Don't overrun buffer
+	if X resource line is longer than 512 bytes.
+
+	* xfns.c (x_window): Make sprintf buffer a bit bigger
+	to avoid potential buffer overrun.
+
+	* xterm.c (x_io_error_quitter): Don't overrun sprintf buffer.
+
+	* xterm.h (x_check_errors): Add ATTRIBUTE_FORMAT_PRINTF.
+
 2011-08-30  Eli Zaretskii  <[email-masked]>
 
 	* image.c (x_bitmap_pixmap): Cast to int to avoid compiler warnings.

=== modified file 'src/dbusbind.c'
--- src/dbusbind.c	2011-06-24 21:25:22 +0000
+++ src/dbusbind.c	2011-08-30 22:02:56 +0000
@@ -259,6 +259,18 @@
     }									\
   while (0)
 
+/* Append to SIGNATURE a copy of X, making sure SIGNATURE does
+   not become too long.  */
+static void
+signature_cat (char *signature, char const *x)
+{
+  ptrdiff_t siglen = strlen (signature);
+  ptrdiff_t xlen = strlen (x);
+  if (DBUS_MAXIMUM_SIGNATURE_LENGTH - xlen <= siglen)
+    string_overflow ();
+  strcat (signature, x);
+}
+
 /* Compute SIGNATURE of OBJECT.  It must have a form that it can be
    used in dbus_message_iter_open_container.  DTYPE is the DBusType
    the object is related to.  It is passed as argument, because it
@@ -271,6 +283,7 @@
 {
   unsigned int subtype;
   Lisp_Object elt;
+  char const *subsig;
   char x[DBUS_MAXIMUM_SIGNATURE_LENGTH];
 
   elt = object;
@@ -328,12 +341,13 @@
       if (NILP (elt))
 	{
 	  subtype = DBUS_TYPE_STRING;
-	  strcpy (x, DBUS_TYPE_STRING_AS_STRING);
+	  subsig = DBUS_TYPE_STRING_AS_STRING;
 	}
       else
 	{
 	  subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
 	  xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
+	  subsig = x;
 	}
 
       /* If the element type is DBUS_TYPE_SIGNATURE, and this is the
@@ -342,7 +356,7 @@
       if ((subtype == DBUS_TYPE_SIGNATURE)
 	  && STRINGP (CAR_SAFE (XD_NEXT_VALUE (elt)))
 	  && NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
-	strcpy (x, SSDATA (CAR_SAFE (XD_NEXT_VALUE (elt))));
+	subsig = SSDATA (CAR_SAFE (XD_NEXT_VALUE (elt)));
 
       while (!NILP (elt))
 	{
@@ -351,7 +365,10 @@
 	  elt = CDR_SAFE (XD_NEXT_VALUE (elt));
 	}
 
-      sprintf (signature, "%c%s", dtype, x);
+      if (esnprintf (signature, DBUS_MAXIMUM_SIGNATURE_LENGTH,
+		     "%c%s", dtype, subsig)
+	  == DBUS_MAXIMUM_SIGNATURE_LENGTH - 1)
+	string_overflow ();
       break;
 
     case DBUS_TYPE_VARIANT:
@@ -383,10 +400,10 @@
 	{
 	  subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
 	  xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
-	  strcat (signature, x);
+	  signature_cat (signature, x);
 	  elt = CDR_SAFE (XD_NEXT_VALUE (elt));
 	}
-      strcat (signature, DBUS_STRUCT_END_CHAR_AS_STRING);
+      signature_cat (signature, DBUS_STRUCT_END_CHAR_AS_STRING);
       break;
 
     case DBUS_TYPE_DICT_ENTRY:
@@ -407,7 +424,7 @@
       elt = XD_NEXT_VALUE (elt);
       subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
       xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
-      strcat (signature, x);
+      signature_cat (signature, x);
 
       if (!XD_BASIC_DBUS_TYPE (subtype))
 	wrong_type_argument (intern ("D-Bus"), CAR_SAFE (XD_NEXT_VALUE (elt)));
@@ -416,14 +433,14 @@
       elt = CDR_SAFE (XD_NEXT_VALUE (elt));
       subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
       xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
-      strcat (signature, x);
+      signature_cat (signature, x);
 
       if (!NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
 	wrong_type_argument (intern ("D-Bus"),
 			     CAR_SAFE (CDR_SAFE (XD_NEXT_VALUE (elt))));
 
       /* Closing signature.  */
-      strcat (signature, DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
+      signature_cat (signature, DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
       break;
 
     default:
@@ -2026,7 +2043,7 @@
   DBusConnection *connection;
   ptrdiff_t i;
   char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
-  char x[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
+  int rulelen;
   DBusError derror;
 
   /* Check parameters.  */
@@ -2071,34 +2088,32 @@
       connection = xd_initialize (bus, TRUE);
 
       /* Create a rule to receive related signals.  */
-      sprintf (rule,
-	       "type='signal',interface='%s',member='%s'",
-	       SDATA (interface),
-	       SDATA (signal));
+      rulelen = esnprintf (rule, sizeof rule,
+			   "type='signal',interface='%s',member='%s'",
+			   SDATA (interface),
+			   SDATA (signal));
 
       /* Add unique name and path to the rule if they are non-nil.  */
       if (!NILP (uname))
-	{
-	  sprintf (x, ",sender='%s'", SDATA (uname));
-	  strcat (rule, x);
-	}
+	rulelen += esnprintf (rule + rulelen, sizeof rule - rulelen,
+			      ",sender='%s'", SDATA (uname));
 
       if (!NILP (path))
-	{
-	  sprintf (x, ",path='%s'", SDATA (path));
-	  strcat (rule, x);
-	}
+	rulelen += esnprintf (rule + rulelen, sizeof rule - rulelen,
+			      ",path='%s'", SDATA (path));
 
       /* Add arguments to the rule if they are non-nil.  */
       for (i = 6; i < nargs; ++i)
 	if (!NILP (args[i]))
 	  {
 	    CHECK_STRING (args[i]);
-	    sprintf (x, ",arg%"pD"d='%s'", i - 6,
-		     SDATA (args[i]));
-	    strcat (rule, x);
+	    rulelen += esnprintf (rule + rulelen, sizeof rule - rulelen,
+				  ",arg%"pD"d='%s'", i - 6, SDATA (args[i]));
 	  }
 
+      if (rulelen == sizeof rule - 1)
+	string_overflow ();
+
       /* Add the rule to the bus.  */
       dbus_error_init (&derror);
       dbus_bus_add_match (connection, rule, &derror);

=== modified file 'src/dispnew.c'
--- src/dispnew.c	2011-08-24 21:20:36 +0000
+++ src/dispnew.c	2011-08-29 15:51:23 +0000
@@ -272,15 +272,16 @@
   buf = redisplay_history[history_idx].trace;
   ++history_idx;
 
-  sprintf (buf, "%"pMu": window %p (`%s')%s\n",
-	   history_tick++,
-	   w,
-	   ((BUFFERP (w->buffer)
-	     && STRINGP (BVAR (XBUFFER (w->buffer), name)))
-	    ? SSDATA (BVAR (XBUFFER (w->buffer), name))
-	    : "???"),
-	   paused_p ? " ***paused***" : "");
-  strcat (buf, msg);
+  esnprintf (buf, sizeof redisplay_history[0].trace,
+	     "%"pMu": window %p (`%s')%s\n%s",
+	     history_tick++,
+	     w,
+	     ((BUFFERP (w->buffer)
+	       && STRINGP (BVAR (XBUFFER (w->buffer), name)))
+	      ? SSDATA (BVAR (XBUFFER (w->buffer), name))
+	      : "???"),
+	     paused_p ? " ***paused***" : "",
+	     msg);
 }

=== modified file 'src/doprnt.c'
--- src/doprnt.c	2011-07-07 02:14:52 +0000
+++ src/doprnt.c	2011-08-29 15:43:34 +0000
@@ -70,9 +70,9 @@
      %<flags><width><precision><length>character
 
    where flags is [+ -0], width is [0-9]+, precision is .[0-9]+, and length
-   is empty or l or the value of the pI macro.  Also, %% in a format
-   stands for a single % in the output.  A % that does not introduce a
-   valid %-sequence causes undefined behavior.
+   is empty or l or the value of the pD or pI or pMd (sans "d") macros.
+   Also, %% in a format stands for a single % in the output.  A % that
+   does not introduce a valid %-sequence causes undefined behavior.
 
    The + flag character inserts a + before any positive number, while a space
    inserts a space before any positive number; these flags only affect %d, %o,
@@ -85,8 +85,10 @@
    modifier: it is supported for %d, %o, and %x conversions of integral
    arguments, must immediately precede the conversion specifier, and means that
    the respective argument is to be treated as `long int' or `unsigned long
-   int'.  Similarly, the value of the pI macro means to use EMACS_INT or
-   EMACS_UINT and the empty length modifier means `int' or `unsigned int'.
+   int'.  Similarly, the value of the pD macro means to use ptrdiff_t,
+   the value of the pI macro means to use EMACS_INT or EMACS_UINT, the
+   value of the pMd etc. macros means to use intmax_t or uintmax_t,
+   and the empty length modifier means `int' or `unsigned int'.
 
    The width specifier supplies a lower limit for the length of the printed
    representation.  The padding, if any, normally goes on the left, but it goes
@@ -173,8 +175,17 @@
 	{
 	  ptrdiff_t size_bound = 0;
 	  EMACS_INT width;  /* Columns occupied by STRING on display.  */
-	  int long_flag = 0;
-	  int pIlen = sizeof pI - 1;
+	  enum {
+	    pDlen = sizeof pD - 1,
+	    pIlen = sizeof pI - 1,
+	    pMlen = sizeof pMd - 2
+	  };
+	  enum {
+	    no_modifier, long_modifier, pD_modifier, pI_modifier, pM_modifier
+	  } length_modifier = no_modifier;
+	  static char const modifier_len[] = { 0, 1, pDlen, pIlen, pMlen };
+	  int maxmlen = max (max (1, pDlen), max (pIlen, pMlen));
+	  int mlen;
 
 	  fmt++;
 	  /* Copy this one %-spec into fmtcpy.  */
@@ -213,19 +224,26 @@
 	      fmt++;
 	    }
 
-	  if (0 < pIlen && pIlen <= format_end - fmt
-	      && memcmp (fmt, pI, pIlen) == 0)
-	    {
-	      long_flag = 2;
-	      memcpy (string, fmt + 1, pIlen);
-	      string += pIlen;
-	      fmt += pIlen;
-	    }
-	  else if (fmt < format_end && *fmt == 'l')
-	    {
-	      long_flag = 1;
-	      *string++ = *++fmt;
-	    }
+	  /* Check for the length modifiers in textual length order, so
+	     that longer modifiers override shorter ones.  */
+	  for (mlen = 1; mlen <= maxmlen; mlen++)
+	    {
+	      if (format_end - fmt < mlen)
+		break;
+	      if (mlen == 1 && *fmt == 'l')
+		length_modifier = long_modifier;
+	      if (mlen == pDlen && memcmp (fmt, pD, pDlen) == 0)
+		length_modifier = pD_modifier;
+	      if (mlen == pIlen && memcmp (fmt, pI, pIlen) == 0)
+		length_modifier = pI_modifier;
+	      if (mlen == pMlen && memcmp (fmt, pMd, pMlen) == 0)
+		length_modifier = pM_modifier;
+	    }
+
+	  mlen = modifier_len[length_modifier];
+	  memcpy (string, fmt + 1, mlen);
+	  string += mlen;
+	  fmt += mlen;
 	  *string = 0;
 
 	  /* Make the size bound large enough to handle floating point formats
@@ -252,55 +270,78 @@
 /*	    case 'b': */
 	    case 'l':
 	    case 'd':
-	      {
-		int i;
-		long l;
-
-		if (1 < long_flag)
-		  {
-		    EMACS_INT ll = va_arg (ap, EMACS_INT);
-		    sprintf (sprintf_buffer, fmtcpy, ll);
-		  }
-		else if (long_flag)
-		  {
-		    l = va_arg(ap, long);
-		    sprintf (sprintf_buffer, fmtcpy, l);
-		  }
-		else
-		  {
-		    i = va_arg(ap, int);
-		    sprintf (sprintf_buffer, fmtcpy, i);
-		  }
-		/* Now copy into final output, truncating as necessary.  */
-		string = sprintf_buffer;
-		goto doit;
-	      }
+	      switch (length_modifier)
+		{
+		case no_modifier:
+		  {
+		    int v = va_arg (ap, int);
+		    sprintf (sprintf_buffer, fmtcpy, v);
+		  }
+		  break;
+		case long_modifier:
+		  {
+		    long v = va_arg (ap, long);
+		    sprintf (sprintf_buffer, fmtcpy, v);
+		  }
+		  break;
+		case pD_modifier:
+		signed_pD_modifier:
+		  {
+		    ptrdiff_t v = va_arg (ap, ptrdiff_t);
+		    sprintf (sprintf_buffer, fmtcpy, v);
+		  }
+		  break;
+		case pI_modifier:
+		  {
+		    EMACS_INT v = va_arg (ap, EMACS_INT);
+		    sprintf (sprintf_buffer, fmtcpy, v);
+		  }
+		  break;
+		case pM_modifier:
+		  {
+		    intmax_t v = va_arg (ap, intmax_t);
+		    sprintf (sprintf_buffer, fmtcpy, v);
+		  }
+		  break;
+		}
+	      /* Now copy into final output, truncating as necessary.  */
+	      string = sprintf_buffer;
+	      goto doit;
 
 	    case 'o':
 	    case 'x':
-	      {
-		unsigned u;
-		unsigned long ul;
-
-		if (1 < long_flag)
-		  {
-		    EMACS_UINT ull = va_arg (ap, EMACS_UINT);
-		    sprintf (sprintf_buffer, fmtcpy, ull);
-		  }
-		else if (long_flag)
-		  {
-		    ul = va_arg(ap, unsigned long);
-		    sprintf (sprintf_buffer, fmtcpy, ul);
-		  }
-		else
-		  {
-		    u = va_arg(ap, unsigned);
-		    sprintf (sprintf_buffer, fmtcpy, u);
-		  }
-		/* Now copy into final output, truncating as necessary.  */
-		string = sprintf_buffer;
-		goto doit;
-	      }
+	      switch (length_modifier)
+		{
+		case no_modifier:
+		  {
+		    unsigned v = va_arg (ap, unsigned);
+		    sprintf (sprintf_buffer, fmtcpy, v);
+		  }
+		  break;
+		case long_modifier:
+		  {
+		    unsigned long v = va_arg (ap, unsigned long);
+		    sprintf (sprintf_buffer, fmtcpy, v);
+		  }
+		  break;
+		case pD_modifier:
+		  goto signed_pD_modifier;
+		case pI_modifier:
+		  {
+		    EMACS_UINT v = va_arg (ap, EMACS_UINT);
+		    sprintf (sprintf_buffer, fmtcpy, v);
+		  }
+		  break;
+		case pM_modifier:
+		  {
+		    uintmax_t v = va_arg (ap, uintmax_t);
+		    sprintf (sprintf_buffer, fmtcpy, v);
+		  }
+		  break;
+		}
+	      /* Now copy into final output, truncating as necessary.  */
+	      string = sprintf_buffer;
+	      goto doit;
 
 	    case 'f':
 	    case 'e':
@@ -426,3 +467,82 @@
   SAFE_FREE ();
   return bufptr - buffer;
 }
+
+/* Format to an unbounded buffer BUF.  This is like sprintf, except it
+   is not limited to returning an 'int' so it doesn't have a silly 2
+   GiB limit on typical 64-bit hosts.  However, it is limited to the
+   Emacs-style formats that doprnt supports.
+
+   Return the number of bytes put into BUF, excluding the terminating
+   '\0'.  */
+ptrdiff_t
+esprintf (char *buf, char const *format, ...)
+{
+  ptrdiff_t nbytes;
+  va_list ap;
+  va_start (ap, format);
+  nbytes = doprnt (buf, TYPE_MAXIMUM (ptrdiff_t), format, 0, ap);
+  va_end (ap);
+  return nbytes;
+}
+
+/* Format to a buffer BUF of positive size BUFSIZE.  This is like
+   snprintf, except it is not limited to returning an 'int' so it
+   doesn't have a silly 2 GiB limit on typical 64-bit hosts.  However,
+   it is limited to the Emacs-style formats that doprnt supports, and
+   BUFSIZE must be positive.
+
+   Return the number of bytes put into BUF, excluding the terminating
+   '\0'.  Unlike snprintf, always return a nonnegative value less than
+   BUFSIZE; if the output is truncated, return BUFSIZE - 1, which is
+   the length of the truncated output.  */
+ptrdiff_t
+esnprintf (char *buf, ptrdiff_t bufsize, char const *format, ...)
+{
+  ptrdiff_t nbytes;
+  va_list ap;
+  va_start (ap, format);
+  nbytes = doprnt (buf, bufsize, format, 0, ap);
+  va_end (ap);
+  return nbytes;
+}
+
+/* Format to buffer *BUF of positive size *BUFSIZE, reallocating *BUF
+   and updating *BUFSIZE if the buffer is too small, and otherwise
+   behaving line esprintf.  When reallocating, free *BUF unless it is
+   equal to NONHEAPBUF, and if BUFSIZE_MAX is nonnegative then signal
+   memory exhaustion instead of growing the buffer size past
+   BUFSIZE_MAX.  */
+ptrdiff_t
+exprintf (char **buf, ptrdiff_t *bufsize,
+	  char const *nonheapbuf, ptrdiff_t bufsize_max,
+	  char const *format, ...)
+{
+  ptrdiff_t nbytes;
+  va_list ap;
+  va_start (ap, format);
+  nbytes = evxprintf (buf, bufsize, nonheapbuf, bufsize_max, format, ap);
+  va_end (ap);
+  return nbytes;
+}
+
+/* Act like exprintf, except take a va_list.  */
+ptrdiff_t
+evxprintf (char **buf, ptrdiff_t *bufsize,
+	   char const *nonheapbuf, ptrdiff_t bufsize_max,
+	   char const *format, va_list ap)
+{
+  for (;;)
+    {
+      ptrdiff_t nbytes;
+      va_list ap_copy;
+      va_copy (ap_copy, ap);
+      nbytes = doprnt (*buf, *bufsize, format, 0, ap_copy);
+      va_end (ap_copy);
+      if (nbytes < *bufsize - 1)
+	return nbytes;
+      if (*buf != nonheapbuf)
+	xfree (*buf);
+      *buf = xpalloc (NULL, bufsize, 1, bufsize_max, 1);
+    }
+}

=== modified file 'src/editfns.c'
--- src/editfns.c	2011-08-19 06:11:38 +0000
+++ src/editfns.c	2011-08-29 15:53:21 +0000
@@ -2014,7 +2014,7 @@
     {
       int offset = tm_diff (t, &gmt);
       char *s = 0;
-      char buf[6];
+      char buf[sizeof "+00" + INT_STRLEN_BOUND (int)];
 
 #ifdef HAVE_TM_ZONE
       if (t->tm_zone)
@@ -2029,7 +2029,8 @@
       if (!s)
 	{
 	  /* No local time zone name is available; use "+-NNNN" instead.  */
-	  int am = (offset < 0 ? -offset : offset) / 60;
+	  int m = offset / 60;
+	  int am = offset < 0 ? - m : m;
 	  sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60);
 	  s = buf;
 	}

=== modified file 'src/emacs.c'
--- src/emacs.c	2011-08-05 02:19:34 +0000
+++ src/emacs.c	2011-08-29 15:56:20 +0000
@@ -1068,15 +1068,17 @@
         if (!dname_arg || !strchr (dname_arg, '\n'))
           {  /* In orig, child: now exec w/special daemon name. */
             char fdStr[80];
+	    int fdStrlen =
+	      snprintf (fdStr, sizeof fdStr,
+			"--daemon=\n%d,%d\n%s", daemon_pipe[0],
+			daemon_pipe[1], dname_arg ? dname_arg : "");
 
-            if (dname_arg && strlen (dname_arg) > 70)
+	    if (! (0 <= fdStrlen && fdStrlen < sizeof fdStr))
               {
                 fprintf (stderr, "daemon: child name too long\n");
                 exit (1);
               }
 
-            sprintf (fdStr, "--daemon=\n%d,%d\n%s", daemon_pipe[0],
-                     daemon_pipe[1], dname_arg ? dname_arg : "");
             argv[skip_args] = fdStr;
 
             execv (argv[0], argv);

=== modified file 'src/eval.c'
--- src/eval.c	2011-08-24 21:20:36 +0000
+++ src/eval.c	2011-08-29 16:01:33 +0000
@@ -1951,35 +1951,11 @@
   char buf[4000];
   ptrdiff_t size = sizeof buf;
   ptrdiff_t size_max = STRING_BYTES_BOUND + 1;
-  char const *m_end = m + strlen (m);
   char *buffer = buf;
   ptrdiff_t used;
   Lisp_Object string;
 
-  while (1)
-    {
-      va_list ap_copy;
-      va_copy (ap_copy, ap);
-      used = doprnt (buffer, size, m, m_end, ap_copy);
-      va_end (ap_copy);
-
-      /* Note: the -1 below is because `doprnt' returns the number of bytes
-	 excluding the terminating null byte, and it always terminates with a
-	 null byte, even when producing a truncated message.  */
-      if (used < size - 1)
-	break;
-      if (size <= size_max / 2)
-	size *= 2;
-      else if (size < size_max)
-	size = size_max;
-      else
-	break;	/* and leave the message truncated */
-
-      if (buffer != buf)
-	xfree (buffer);
-      buffer = (char *) xmalloc (size);
-    }
-
+  used = evxprintf (&buffer, &size, buf, size_max, m, ap);
   string = make_string (buffer, used);
   if (buffer != buf)
     xfree (buffer);

=== modified file 'src/filelock.c'
--- src/filelock.c	2011-07-07 21:52:44 +0000
+++ src/filelock.c	2011-08-29 16:48:19 +0000
@@ -341,6 +341,9 @@
   const char *user_name;
   const char *host_name;
   char *lock_info_str;
+  ptrdiff_t lock_info_size;
+  int symlink_errno;
+  USE_SAFE_ALLOCA;
 
   /* Call this first because it can GC.  */
   boot = get_boot_time ();
@@ -353,17 +356,14 @@
     host_name = SSDATA (Fsystem_name ());
   else
     host_name = "";
-  lock_info_str = (char *)alloca (strlen (user_name) + strlen (host_name)
-				  + 2 * INT_STRLEN_BOUND (printmax_t)
-				  + sizeof "@.:");
+  lock_info_size = (strlen (user_name) + strlen (host_name)
+		    + 2 * INT_STRLEN_BOUND (printmax_t)
+		    + sizeof "@.:");
+  SAFE_ALLOCA (lock_info_str, char *, lock_info_size);
   pid = getpid ();
 
-  if (boot)
-    sprintf (lock_info_str, "%s@%s.%"pMd":%"pMd,
-	     user_name, host_name, pid, boot);
-  else
-    sprintf (lock_info_str, "%s@%s.%"pMd,
-	     user_name, host_name, pid);
+  esprintf (lock_info_str, boot ? "%s@%s.%"pMd":%"pMd : "%s@%s.%"pMd,
+	    user_name, host_name, pid, boot);
 
   err = symlink (lock_info_str, lfname);
   if (errno == EEXIST && force)
@@ -372,6 +372,9 @@
       err = symlink (lock_info_str, lfname);
     }
 
+  symlink_errno = errno;
+  SAFE_FREE ();
+  errno = symlink_errno;
   return err == 0;
 }
 
@@ -541,9 +544,11 @@
 {
   register Lisp_Object attack, orig_fn, encoded_fn;
   register char *lfname, *locker;
+  ptrdiff_t locker_size;
   lock_info_type lock_info;
   printmax_t pid;
   struct gcpro gcpro1;
+  USE_SAFE_ALLOCA;
 
   /* Don't do locking while dumping Emacs.
      Uncompressing wtmp files uses call-process, which does not work
@@ -580,15 +585,17 @@
     return;
 
   /* Else consider breaking the lock */
-  locker = (char *) alloca (strlen (lock_info.user) + strlen (lock_info.host)
-			    + INT_STRLEN_BOUND (printmax_t)
-			    + sizeof "@ (pid )");
+  locker_size = (strlen (lock_info.user) + strlen (lock_info.host)
+		 + INT_STRLEN_BOUND (printmax_t)
+		 + sizeof "@ (pid )");
+  SAFE_ALLOCA (locker, char *, locker_size);
   pid = lock_info.pid;
-  sprintf (locker, "%s@%s (pid %"pMd")",
-	   lock_info.user, lock_info.host, pid);
+  esprintf (locker, "%s@%s (pid %"pMd")",
+	    lock_info.user, lock_info.host, pid);
   FREE_LOCK_INFO (lock_info);
 
   attack = call2 (intern ("ask-user-about-lock"), fn, build_string (locker));
+  SAFE_FREE ();
   if (!NILP (attack))
     /* User says take the lock */
     {

=== modified file 'src/font.c'
--- src/font.c	2011-07-10 08:20:10 +0000
+++ src/font.c	2011-08-29 20:57:42 +0000
@@ -21,6 +21,7 @@
 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
+#include <float.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <setjmp.h>
@@ -1180,7 +1181,7 @@
   char *p;
   const char *f[XLFD_REGISTRY_INDEX + 1];
   Lisp_Object val;
-  int i, j, len = 0;
+  int i, j, len;
 
   font_assert (FONTP (font));
 
@@ -1195,9 +1196,9 @@
       if (NILP (val))
 	{
 	  if (j == XLFD_REGISTRY_INDEX)
-	    f[j] = "*-*", len += 4;
+	    f[j] = "*-*";
 	  else
-	    f[j] = "*", len += 2;
+	    f[j] = "*";
 	}
       else
 	{
@@ -1207,21 +1208,15 @@
 	      && ! strchr (SSDATA (val), '-'))
 	    {
 	      /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*".  */
-	      if (SDATA (val)[SBYTES (val) - 1] == '*')
-		{
-		  f[j] = p = alloca (SBYTES (val) + 3);
-		  sprintf (p, "%s-*", SDATA (val));
-		  len += SBYTES (val) + 3;
-		}
-	      else
-		{
-		  f[j] = p = alloca (SBYTES (val) + 4);
-		  sprintf (p, "%s*-*", SDATA (val));
-		  len += SBYTES (val) + 4;
-		}
+	      ptrdiff_t alloc = SBYTES (val) + 4;
+	      if (nbytes <= alloc)
+		return -1;
+	      f[j] = p = alloca (alloc);
+	      sprintf (p, "%s%s-*", SDATA (val),
+		       "*" + (SDATA (val)[SBYTES (val) - 1] == '*'));
 	    }
 	  else
-	    f[j] = SSDATA (val), len += SBYTES (val) + 1;
+	    f[j] = SSDATA (val);
 	}
     }
 
@@ -1230,11 +1225,11 @@
     {
       val = font_style_symbolic (font, i, 0);
       if (NILP (val))
-	f[j] = "*", len += 2;
+	f[j] = "*";
       else
 	{
 	  val = SYMBOL_NAME (val);
-	  f[j] = SSDATA (val), len += SBYTES (val) + 1;
+	  f[j] = SSDATA (val);
 	}
     }
 
@@ -1242,64 +1237,62 @@
   font_assert (NUMBERP (val) || NILP (val));
   if (INTEGERP (val))
     {
-      i = XINT (val);
-      if (i <= 0)
-	i = pixel_size;
-      if (i > 0)
+      EMACS_INT v = XINT (val);
+      if (v <= 0)
+	v = pixel_size;
+      if (v > 0)
 	{
-	  f[XLFD_PIXEL_INDEX] = p = alloca (22);
-	  len += sprintf (p, "%d-*", i) + 1;
+	  f[XLFD_PIXEL_INDEX] = p =
+	    alloca (sizeof "-*" + INT_STRLEN_BOUND (EMACS_INT));
+	  sprintf (p, "%"pI"d-*", v);
 	}
       else
-	f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
+	f[XLFD_PIXEL_INDEX] = "*-*";
     }
   else if (FLOATP (val))
     {
-      i = XFLOAT_DATA (val) * 10;
-      f[XLFD_PIXEL_INDEX] = p = alloca (12);
-      len += sprintf (p, "*-%d", i) + 1;
+      double v = XFLOAT_DATA (val) * 10;
+      f[XLFD_PIXEL_INDEX] = p = alloca (sizeof "*-" + 1 + DBL_MAX_10_EXP + 1);
+      sprintf (p, "*-%.0f", v);
     }
   else
-    f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
+    f[XLFD_PIXEL_INDEX] = "*-*";
 
   if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
     {
-      i = XINT (AREF (font, FONT_DPI_INDEX));
-      f[XLFD_RESX_INDEX] = p = alloca (22);
-      len += sprintf (p, "%d-%d", i, i) + 1;
+      EMACS_INT v = XINT (AREF (font, FONT_DPI_INDEX));
+      f[XLFD_RESX_INDEX] = p =
+	alloca (sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT));
+      sprintf (p, "%"pI"d-%"pI"d", v, v);
     }
   else
-    f[XLFD_RESX_INDEX] = "*-*", len += 4;
+    f[XLFD_RESX_INDEX] = "*-*";
   if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
     {
-      int spacing = XINT (AREF (font, FONT_SPACING_INDEX));
+      EMACS_INT spacing = XINT (AREF (font, FONT_SPACING_INDEX));
 
       f[XLFD_SPACING_INDEX] = (spacing <= FONT_SPACING_PROPORTIONAL ? "p"
 			       : spacing <= FONT_SPACING_DUAL ? "d"
 			       : spacing <= FONT_SPACING_MONO ? "m"
 			       : "c");
-      len += 2;
     }
   else
-    f[XLFD_SPACING_INDEX] = "*", len += 2;
+    f[XLFD_SPACING_INDEX] = "*";
   if (INTEGERP (AREF (font,  FONT_AVGWIDTH_INDEX)))
     {
-      f[XLFD_AVGWIDTH_INDEX] = p = alloca (22);
-      len += sprintf (p, "%"pI"d",
-		      XINT (AREF (font, FONT_AVGWIDTH_INDEX))) + 1;
+      f[XLFD_AVGWIDTH_INDEX] = p = alloca (INT_BUFSIZE_BOUND (EMACS_INT));
+      sprintf (p, "%"pI"d", XINT (AREF (font, FONT_AVGWIDTH_INDEX)));
     }
   else
-    f[XLFD_AVGWIDTH_INDEX] = "*", len += 2;
-  len++;	/* for terminating '\0'.  */
-  if (len >= nbytes)
-    return -1;
-  return sprintf (name, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
+    f[XLFD_AVGWIDTH_INDEX] = "*";
+  len = snprintf (name, nbytes, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
 		  f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
 		  f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
 		  f[XLFD_SWIDTH_INDEX], f[XLFD_ADSTYLE_INDEX],
 		  f[XLFD_PIXEL_INDEX], f[XLFD_RESX_INDEX],
 		  f[XLFD_SPACING_INDEX], f[XLFD_AVGWIDTH_INDEX],
 		  f[XLFD_REGISTRY_INDEX]);
+  return len < nbytes ? len : -1;
 }
 
 /* Parse NAME (null terminated) and store information in FONT
@@ -1553,23 +1546,19 @@
 font_unparse_fcname (Lisp_Object font, int pixel_size, char *name, int nbytes)
 {
   Lisp_Object family, foundry;
-  Lisp_Object tail, val;
+  Lisp_Object val;
   int point_size;
   int i;
-  ptrdiff_t len = 1;
   char *p;
+  char *lim;
   Lisp_Object styles[3];
   const char *style_names[3] = { "weight", "slant", "width" };
-  char work[256];
 
   family = AREF (font, FONT_FAMILY_INDEX);
   if (! NILP (family))
     {
       if (SYMBOLP (family))
-	{
-	  family = SYMBOL_NAME (family);
-	  len += SBYTES (family);
-	}
+	family = SYMBOL_NAME (family);
       else
 	family = Qnil;
     }
@@ -1580,7 +1569,6 @@
       if (XINT (val) != 0)
 	pixel_size = XINT (val);
       point_size = -1;
-      len += 21;		/* for ":pixelsize=NUM" */
     }
   else
     {
@@ -1588,80 +1576,54 @@
 	abort ();
       pixel_size = -1;
       point_size = (int) XFLOAT_DATA (val);
-      len += 11;		/* for "-NUM" */
     }
 
   foundry = AREF (font, FONT_FOUNDRY_INDEX);
   if (! NILP (foundry))
     {
       if (SYMBOLP (foundry))
-	{
-	  foundry = SYMBOL_NAME (foundry);
-	  len += 9 + SBYTES (foundry); /* ":foundry=NAME" */
-	}
+	foundry = SYMBOL_NAME (foundry);
       else
 	foundry = Qnil;
     }
 
   for (i = 0; i < 3; i++)
-    {
-      styles[i] = font_style_symbolic (font, FONT_WEIGHT_INDEX + i, 0);
-      if (! NILP (styles[i]))
-	len += sprintf (work, ":%s=%s", style_names[i],
-			SDATA (SYMBOL_NAME (styles[i])));
-    }
-
-  if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
-    len += sprintf (work, ":dpi=%"pI"d", XINT (AREF (font, FONT_DPI_INDEX)));
-  if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
-    len += strlen (":spacing=100");
-  if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
-    len += strlen (":scalable=false"); /* or ":scalable=true" */
-  for (tail = AREF (font, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
-    {
-      Lisp_Object key = XCAR (XCAR (tail)), value = XCDR (XCAR (tail));
-
-      len += SBYTES (SYMBOL_NAME (key)) + 1; /* for :KEY= */
-      if (STRINGP (value))
-	len += SBYTES (value);
-      else if (INTEGERP (value))
-	len += sprintf (work, "%"pI"d", XINT (value));
-      else if (SYMBOLP (value))
-	len += (NILP (value) ? 5 : 4); /* for "false" or "true" */
-    }
-
-  if (len > nbytes)
-    return -1;
+    styles[i] = font_style_symbolic (font, FONT_WEIGHT_INDEX + i, 0);
+
   p = name;
+  lim = name + nbytes;
+# define APPEND_SNPRINTF(args)			\
+    do {					\
+      int len = snprintf args;			\
+      if (! (0 <= len && len < lim - p))	\
+	return -1;				\
+      p += len;					\
+    } while (0)
   if (! NILP (family))
-    p += sprintf (p, "%s", SDATA (family));
+    APPEND_SNPRINTF ((p, lim - p, "%s", SSDATA (family)));
   if (point_size > 0)
-    {
-      if (p == name)
-	p += sprintf (p, "%d", point_size);
-      else
-	p += sprintf (p, "-%d", point_size);
-    }
+    APPEND_SNPRINTF ((p, lim - p, "-%d" + (p == name), point_size));
   else if (pixel_size > 0)
-    p += sprintf (p, ":pixelsize=%d", pixel_size);
+    APPEND_SNPRINTF ((p, lim - p, ":pixelsize=%d", pixel_size));
   if (! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
-    p += sprintf (p, ":foundry=%s",
-		  SDATA (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX))));
+    APPEND_SNPRINTF ((p, lim - p, ":foundry=%s",
+		      SSDATA (SYMBOL_NAME (AREF (font,
+						 FONT_FOUNDRY_INDEX)))));
   for (i = 0; i < 3; i++)
     if (! NILP (styles[i]))
-      p += sprintf (p, ":%s=%s", style_names[i],
-		    SDATA (SYMBOL_NAME (styles[i])));
+      APPEND_SNPRINTF ((p, lim - p, ":%s=%s", style_names[i],
+			SSDATA (SYMBOL_NAME (styles[i]))));
   if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
-    p += sprintf (p, ":dpi=%"pI"d", XINT (AREF (font, FONT_DPI_INDEX)));
+    APPEND_SNPRINTF ((p, lim - p, ":dpi=%"pI"d",
+		      XINT (AREF (font, FONT_DPI_INDEX))));
   if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
-    p += sprintf (p, ":spacing=%"pI"d", XINT (AREF (font, FONT_SPACING_INDEX)));
+    APPEND_SNPRINTF ((p, lim - p, ":spacing=%"pI"d",
+		      XINT (AREF (font, FONT_SPACING_INDEX))));
   if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
-    {
-      if (XINT (AREF (font, FONT_AVGWIDTH_INDEX)) == 0)
-	p += sprintf (p, ":scalable=true");
-      else
-	p += sprintf (p, ":scalable=false");
-    }
+    APPEND_SNPRINTF ((p, lim - p,
+		      (XINT (AREF (font, FONT_AVGWIDTH_INDEX)) == 0
+		       ? ":scalable=true"
+		       : ":scalable=false")));
   return (p - name);
 }
 
@@ -1952,12 +1914,12 @@
       else if (! asterisk)
 	{
 	  val = SYMBOL_NAME (val);
-	  p += sprintf (p, "%s", SDATA (val));
+	  p += esprintf (p, "%s", SDATA (val));
 	}
       else
 	{
 	  val = SYMBOL_NAME (val);
-	  p += sprintf (p, "~%s", SDATA (val));
+	  p += esprintf (p, "~%s", SDATA (val));
 	}
     }
   if (CONSP (spec))

=== modified file 'src/fontset.c'
--- src/fontset.c	2011-08-09 22:13:11 +0000
+++ src/fontset.c	2011-08-29 18:48:24 +0000
@@ -1700,7 +1700,7 @@
 static Lisp_Object auto_fontset_alist;
 
 /* Number of automatically created fontsets.  */
-static int num_auto_fontsets;
+static printmax_t num_auto_fontsets;
 
 /* Retun a fontset synthesized from FONT-OBJECT.  This is called from
    x_new_font when FONT-OBJECT is used for the default ASCII font of a
@@ -1727,9 +1727,9 @@
     alias = intern ("fontset-startup");
   else
     {
-      char temp[32];
+      char temp[sizeof "fontset-auto" + INT_STRLEN_BOUND (printmax_t)];
 
-      sprintf (temp, "fontset-auto%d", num_auto_fontsets - 1);
+      sprintf (temp, "fontset-auto%"pMd, num_auto_fontsets - 1);
       alias = intern (temp);
     }
   fontset_spec = copy_font_spec (font_spec);

=== modified file 'src/frame.c'
--- src/frame.c	2011-08-14 06:40:45 +0000
+++ src/frame.c	2011-08-29 18:52:26 +0000
@@ -497,7 +497,7 @@
 
 /* Construct a frame that refers to a terminal.  */
 
-static int tty_frame_count;
+static printmax_t tty_frame_count;
 
 struct frame *
 make_initial_frame (void)
@@ -551,7 +551,7 @@
 {
   register struct frame *f;
   Lisp_Object frame;
-  char name[20];
+  char name[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
 
   if (!terminal->name)
     error ("Terminal is not live, can't create new frames on it");
@@ -562,7 +562,7 @@
   Vframe_list = Fcons (frame, Vframe_list);
 
   tty_frame_count++;
-  sprintf (name, "F%d", tty_frame_count);
+  sprintf (name, "F%"pMd, tty_frame_count);
   f->name = build_string (name);
 
   f->visible = 1;		/* FRAME_SET_VISIBLE wd set frame_garbaged. */
@@ -2074,7 +2074,7 @@
   /* If NAME is nil, set the name to F<num>.  */
   if (NILP (name))
     {
-      char namebuf[20];
+      char namebuf[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
 
       /* Check for no change needed in this very common case
 	 before we do any consing.  */
@@ -2083,7 +2083,7 @@
 	return;
 
       tty_frame_count++;
-      sprintf (namebuf, "F%d", tty_frame_count);
+      sprintf (namebuf, "F%"pMd, tty_frame_count);
       name = build_string (namebuf);
     }
   else
@@ -3065,6 +3065,7 @@
 {
   char buf[16];
   Lisp_Object tem;
+  unsigned long w;
 
   /* Represent negative positions (off the top or left screen edge)
      in a way that Fmodify_frame_parameters will understand correctly.  */
@@ -3097,7 +3098,8 @@
 		      for non-toolkit scroll bar.
 		      ruler-mode.el depends on this.  */
 		   : Qnil));
-  sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
+  w = FRAME_X_WINDOW (f);
+  sprintf (buf, "%lu", w);
   store_in_alist (alistptr, Qwindow_id,
 		  build_string (buf));
 #ifdef HAVE_X_WINDOWS
@@ -3105,7 +3107,10 @@
   /* Tooltip frame may not have this widget.  */
   if (FRAME_X_OUTPUT (f)->widget)
 #endif
-    sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
+    {
+      w = FRAME_OUTER_WINDOW (f);
+      sprintf (buf, "%lu", w);
+    }
   store_in_alist (alistptr, Qouter_window_id,
 		  build_string (buf));
 #endif
@@ -3576,13 +3581,13 @@
 void
 validate_x_resource_name (void)
 {
-  int len = 0;
+  ptrdiff_t len = 0;
   /* Number of valid characters in the resource name.  */
-  int good_count = 0;
+  ptrdiff_t good_count = 0;
   /* Number of invalid characters in the resource name.  */
-  int bad_count = 0;
+  ptrdiff_t bad_count = 0;
   Lisp_Object new;
-  int i;
+  ptrdiff_t i;
 
   if (!STRINGP (Vx_resource_class))
     Vx_resource_class = build_string (EMACS_CLASS);
@@ -3615,8 +3620,9 @@
   if (bad_count == 0)
     return;
 
-  /* If name is entirely invalid, or nearly so, use `emacs'.  */
-  if (good_count < 2)
+  /* If name is entirely invalid, or nearly so, or is so implausibly
+     large that alloca might not work, use `emacs'.  */
+  if (good_count < 2 || MAX_ALLOCA - sizeof ".customization" < len)
     {
       Vx_resource_name = build_string ("emacs");
       return;
@@ -3745,20 +3751,24 @@
 {
   char *name_key;
   char *class_key;
+  char *result;
   struct frame *sf = SELECTED_FRAME ();
+  ptrdiff_t invocation_namelen = SBYTES (Vinvocation_name);
+  USE_SAFE_ALLOCA;
 
   /* Allocate space for the components, the dots which separate them,
      and the final '\0'.  */
-  name_key = (char *) alloca (SBYTES (Vinvocation_name)
-			      + strlen (attribute) + 2);
+  SAFE_ALLOCA (name_key, char *, invocation_namelen + strlen (attribute) + 2);
   class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
 			       + strlen (class) + 2);
 
-  sprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
+  esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
   sprintf (class_key, "%s.%s", EMACS_CLASS, class);
 
-  return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
-				name_key, class_key);
+  result = x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
+				  name_key, class_key);
+  SAFE_FREE ();
+  return result;
 }
 #endif

=== modified file 'src/gtkutil.c'
--- src/gtkutil.c	2011-08-05 02:19:34 +0000
+++ src/gtkutil.c	2011-08-29 20:57:42 +0000
@@ -20,6 +20,7 @@
 #include <config.h>
 
 #ifdef USE_GTK
+#include <float.h>
 #include <signal.h>
 #include <stdio.h>
 #include <setjmp.h>
@@ -567,7 +568,7 @@
     GtkStyleContext *gsty
       = gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f));
     GdkRGBA col;
-    char buf[64];
+    char buf[sizeof "rgbi://" + 3 * (DBL_MAX_10_EXP + sizeof "-1.000000" - 1)];
     int state = GTK_STATE_FLAG_SELECTED|GTK_STATE_FLAG_FOCUSED;
     if (get_fg)
       gtk_style_context_get_color (gsty, state, &col);
@@ -797,7 +798,7 @@
       int xneg = f->size_hint_flags & XNegative;
       int top = f->top_pos;
       int yneg = f->size_hint_flags & YNegative;
-      char geom_str[32];
+      char geom_str[sizeof "=x--" + 4 * INT_STRLEN_BOUND (int)];
 
       if (xneg)
         left = -left;

=== modified file 'src/keyboard.c'
--- src/keyboard.c	2011-08-05 02:19:34 +0000
+++ src/keyboard.c	2011-08-29 15:43:34 +0000
@@ -196,7 +196,7 @@
 int quit_char;
 
 /* Current depth in recursive edits.  */
-int command_loop_level;
+EMACS_INT command_loop_level;
 
 /* If not Qnil, this is a switch-frame event which we decided to put
    off until the end of a key sequence.  This should be read as the
@@ -998,7 +998,8 @@
 cmd_error (Lisp_Object data)
 {
   Lisp_Object old_level, old_length;
-  char macroerror[50];
+  char macroerror[sizeof "After..kbd macro iterations: "
+		  + INT_STRLEN_BOUND (EMACS_INT)];
 
 #ifdef HAVE_WINDOW_SYSTEM
   if (display_hourglass_p)
@@ -1010,7 +1011,7 @@
       if (executing_kbd_macro_iterations == 1)
 	sprintf (macroerror, "After 1 kbd macro iteration: ");
       else
-	sprintf (macroerror, "After %d kbd macro iterations: ",
+	sprintf (macroerror, "After %"pI"d kbd macro iterations: ",
 		 executing_kbd_macro_iterations);
     }
   else
@@ -6463,11 +6464,15 @@
 	value = Fcdr_safe (Fassq (symbol_int, name_alist_or_stem));
       else if (STRINGP (name_alist_or_stem))
 	{
-	  int len = SBYTES (name_alist_or_stem);
-	  char *buf = (char *) alloca (len + 50);
-          sprintf (buf, "%s-%"pI"d", SDATA (name_alist_or_stem),
-                   XINT (symbol_int) + 1);
+	  char *buf;
+	  ptrdiff_t len = (SBYTES (name_alist_or_stem)
+			   + sizeof "-" + INT_STRLEN_BOUND (EMACS_INT));
+	  USE_SAFE_ALLOCA;
+	  SAFE_ALLOCA (buf, char *, len);
+	  esprintf (buf, "%s-%"pI"d", SDATA (name_alist_or_stem),
+		    XINT (symbol_int) + 1);
 	  value = intern (buf);
+	  SAFE_FREE ();
 	}
       else if (name_table != 0 && name_table[symbol_num])
 	value = intern (name_table[symbol_num]);
@@ -6483,7 +6488,7 @@
 
       if (NILP (value))
 	{
-	  char buf[20];
+	  char buf[sizeof "key-" + INT_STRLEN_BOUND (EMACS_INT)];
 	  sprintf (buf, "key-%"pI"d", symbol_num);
 	  value = intern (buf);
 	}
@@ -10382,19 +10387,21 @@
 	  char *newmessage;
 	  int message_p = push_message ();
 	  int count = SPECPDL_INDEX ();
+	  ptrdiff_t newmessage_len, newmessage_alloc;
+	  USE_SAFE_ALLOCA;
 
 	  record_unwind_protect (pop_message_unwind, Qnil);
 	  binding = Fkey_description (bindings, Qnil);
-
-	  newmessage
-	    = (char *) alloca (SCHARS (SYMBOL_NAME (function))
-			       + SBYTES (binding)
-			       + 100);
-	  sprintf (newmessage, "You can run the command `%s' with %s",
-		   SDATA (SYMBOL_NAME (function)),
-		   SDATA (binding));
+	  newmessage_alloc =
+	    (sizeof "You can run the command `' with "
+	     + SBYTES (SYMBOL_NAME (function)) + SBYTES (binding));
+	  SAFE_ALLOCA (newmessage, char *, newmessage_alloc);
+	  newmessage_len =
+	    esprintf (newmessage, "You can run the command `%s' with %s",
+		      SDATA (SYMBOL_NAME (function)),
+		      SDATA (binding));
 	  message2 (newmessage,
-		    strlen (newmessage),
+		    newmessage_len,
 		    STRING_MULTIBYTE (binding));
 	  if (NUMBERP (Vsuggest_key_bindings))
 	    waited = sit_for (Vsuggest_key_bindings, 0, 2);
@@ -10404,6 +10411,7 @@
 	  if (!NILP (waited) && message_p)
 	    restore_message ();
 
+	  SAFE_FREE ();
 	  unbind_to (count, Qnil);
 	}
     }
@@ -10633,7 +10641,9 @@
   (void)
 {
   Lisp_Object temp;
-  XSETFASTINT (temp, command_loop_level + minibuf_level);
+  /* Wrap around reliably on integer overflow.  */
+  EMACS_INT sum = (command_loop_level & INTMASK) + (minibuf_level & INTMASK);
+  XSETINT (temp, sum);
   return temp;
 }

=== modified file 'src/keymap.c'
--- src/keymap.c	2011-08-14 06:40:45 +0000
+++ src/keymap.c	2011-08-29 15:43:34 +0000
@@ -2143,12 +2143,12 @@

 char *
-push_key_description (register unsigned int c, register char *p, int force_multibyte)
+push_key_description (EMACS_INT ch, char *p, int force_multibyte)
 {
-  unsigned c2;
+  int c, c2;
 
   /* Clear all the meaningless bits above the meta bit.  */
-  c &= meta_modifier | ~ - meta_modifier;
+  c = ch & (meta_modifier | ~ - meta_modifier);
   c2 = c & ~(alt_modifier | ctrl_modifier | hyper_modifier
 	     | meta_modifier | shift_modifier | super_modifier);
 
@@ -2283,10 +2283,15 @@
     {
       if (NILP (no_angles))
 	{
-	  char *buffer
-	    = (char *) alloca (SBYTES (SYMBOL_NAME (key)) + 5);
-	  sprintf (buffer, "<%s>", SDATA (SYMBOL_NAME (key)));
-	  return build_string (buffer);
+	  char *buffer;
+	  Lisp_Object result;
+	  USE_SAFE_ALLOCA;
+	  SAFE_ALLOCA (buffer, char *,
+		       sizeof "<>" + SBYTES (SYMBOL_NAME (key)));
+	  esprintf (buffer, "<%s>", SDATA (SYMBOL_NAME (key)));
+	  result = build_string (buffer);
+	  SAFE_FREE ();
+	  return result;
 	}
       else
 	return Fsymbol_name (key);

=== modified file 'src/lisp.h'
--- src/lisp.h	2011-08-14 06:40:45 +0000
+++ src/lisp.h	2011-08-29 15:43:34 +0000
@@ -2895,6 +2895,16 @@
 /* Defined in doprnt.c */
 extern ptrdiff_t doprnt (char *, ptrdiff_t, const char *, const char *,
 			 va_list);
+extern ptrdiff_t esprintf (char *, char const *, ...)
+  ATTRIBUTE_FORMAT_PRINTF (2, 3);
+extern ptrdiff_t esnprintf (char *, ptrdiff_t, char const *, ...)
+  ATTRIBUTE_FORMAT_PRINTF (3, 4);
+extern ptrdiff_t exprintf (char **, ptrdiff_t *, char const *, ptrdiff_t,
+			   char const *, ...)
+  ATTRIBUTE_FORMAT_PRINTF (5, 6);
+extern ptrdiff_t evxprintf (char **, ptrdiff_t *, char const *, ptrdiff_t,
+			    char const *, va_list)
+  ATTRIBUTE_FORMAT_PRINTF (5, 0);
 
 /* Defined in lread.c.  */
 extern Lisp_Object Qvariable_documentation, Qstandard_input;
@@ -3186,7 +3196,7 @@
 EXFUN (Feval_minibuffer, 2);
 EXFUN (Fread_string, 5);
 EXFUN (Fassoc_string, 3);
-extern Lisp_Object get_minibuffer (int);
+extern Lisp_Object get_minibuffer (EMACS_INT);
 extern void init_minibuf_once (void);
 extern void syms_of_minibuf (void);
 
@@ -3250,7 +3260,7 @@
 extern void init_keyboard (void);
 extern void syms_of_keyboard (void);
 extern void keys_of_keyboard (void);
-extern char *push_key_description (unsigned int, char *, int);
+extern char *push_key_description (EMACS_INT, char *, int);

 /* Defined in indent.c */

=== modified file 'src/lread.c'
--- src/lread.c	2011-08-18 08:41:19 +0000
+++ src/lread.c	2011-08-29 18:55:58 +0000
@@ -4295,14 +4295,20 @@
 void
 dir_warning (const char *format, Lisp_Object dirname)
 {
-  char *buffer
-    = (char *) alloca (SCHARS (dirname) + strlen (format) + 5);
-
   fprintf (stderr, format, SDATA (dirname));
-  sprintf (buffer, format, SDATA (dirname));
+
   /* Don't log the warning before we've initialized!! */
   if (initialized)
-    message_dolog (buffer, strlen (buffer), 0, STRING_MULTIBYTE (dirname));
+    {
+      char *buffer;
+      ptrdiff_t message_len;
+      USE_SAFE_ALLOCA;
+      SAFE_ALLOCA (buffer, char *,
+		   SBYTES (dirname) + strlen (format) - (sizeof "%s" - 1) + 1);
+      message_len = esprintf (buffer, format, SDATA (dirname));
+      message_dolog (buffer, message_len, 0, STRING_MULTIBYTE (dirname));
+      SAFE_FREE ();
+    }
 }
 
 void

=== modified file 'src/macros.c'
--- src/macros.c	2011-07-29 01:00:29 +0000
+++ src/macros.c	2011-08-29 19:07:18 +0000
@@ -35,7 +35,7 @@
    This is not bound at each level,
    so after an error, it describes the innermost interrupted macro.  */
 
-int executing_kbd_macro_iterations;
+EMACS_INT executing_kbd_macro_iterations;
 
 /* This is the macro that was executing.
    This is not bound at each level,
@@ -175,11 +175,11 @@
 
   if (XFASTINT (repeat) == 0)
     Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro), repeat, loopfunc);
-  else
+  else if (XINT (repeat) > 1)
     {
       XSETINT (repeat, XINT (repeat)-1);
-      if (XINT (repeat) > 0)
-	Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro), repeat, loopfunc);
+      Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro),
+			  repeat, loopfunc);
     }
   return Qnil;
 }
@@ -302,9 +302,9 @@
   Lisp_Object final;
   Lisp_Object tem;
   int pdlcount = SPECPDL_INDEX ();
-  int repeat = 1;
+  EMACS_INT repeat = 1;
   struct gcpro gcpro1, gcpro2;
-  int success_count = 0;
+  EMACS_INT success_count = 0;
 
   executing_kbd_macro_iterations = 0;

=== modified file 'src/macros.h'
--- src/macros.h	2011-01-25 04:08:28 +0000
+++ src/macros.h	2011-08-29 19:07:18 +0000
@@ -22,7 +22,7 @@
    This is not bound at each level,
    so after an error, it describes the innermost interrupted macro.  */
 
-extern int executing_kbd_macro_iterations;
+extern EMACS_INT executing_kbd_macro_iterations;
 
 /* This is the macro that was executing.
    This is not bound at each level,
@@ -42,4 +42,3 @@
 /* Store a character into kbd macro being defined */
 
 extern void store_kbd_macro_char (Lisp_Object);
-

=== modified file 'src/minibuf.c'
--- src/minibuf.c	2011-08-05 02:15:35 +0000
+++ src/minibuf.c	2011-08-29 15:43:34 +0000
@@ -49,7 +49,7 @@
 
 /* Depth in minibuffer invocations.  */
 
-int minibuf_level;
+EMACS_INT minibuf_level;
 
 /* The maximum length of a minibuffer history.  */
 
@@ -772,10 +772,10 @@
  used for nonrecursive minibuffer invocations.  */
 
 Lisp_Object
-get_minibuffer (int depth)
+get_minibuffer (EMACS_INT depth)
 {
   Lisp_Object tail, num, buf;
-  char name[24];
+  char name[sizeof " *Minibuf-*" + INT_STRLEN_BOUND (EMACS_INT)];
 
   XSETFASTINT (num, depth);
   tail = Fnthcdr (num, Vminibuffer_list);
@@ -787,7 +787,7 @@
   buf = Fcar (tail);
   if (NILP (buf) || NILP (BVAR (XBUFFER (buf), name)))
     {
-      sprintf (name, " *Minibuf-%d*", depth);
+      sprintf (name, " *Minibuf-%"pI"d*", depth);
       buf = Fget_buffer_create (build_string (name));
 
       /* Although the buffer's name starts with a space, undo should be

=== modified file 'src/nsterm.m'
--- src/nsterm.m	2011-08-15 05:30:45 +0000
+++ src/nsterm.m	2011-08-29 19:09:16 +0000
@@ -5316,7 +5316,7 @@
             strcpy (old_title, t);
           }
         size_title = xmalloc (strlen (old_title) + 40);
-        sprintf (size_title, "%s  —  (%d x %d)", old_title, cols, rows);
+	esprintf (size_title, "%s  —  (%d x %d)", old_title, cols, rows);
         [window setTitle: [NSString stringWithUTF8String: size_title]];
         [window display];
         xfree (size_title);

=== modified file 'src/print.c'
--- src/print.c	2011-07-28 20:23:19 +0000
+++ src/print.c	2011-08-29 19:14:47 +0000
@@ -1016,12 +1016,15 @@
 	{
 	  width = 0;
 	  do
-	    width = (width * 10) + (*cp++ - '0');
+	    {
+	      width = (width * 10) + (*cp++ - '0');
+	      if (DBL_DIG < width)
+		goto lose;
+	    }
 	  while (*cp >= '0' && *cp <= '9');
 
 	  /* A precision of zero is valid only for %f.  */
-	  if (width > DBL_DIG
-	      || (width == 0 && *cp != 'f'))
+	  if (width == 0 && *cp != 'f')
 	    goto lose;
 	}
 
@@ -1314,7 +1317,9 @@
 static void
 print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag)
 {
-  char buf[40];
+  char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT),
+		max (sizeof " . #" + INT_STRLEN_BOUND (printmax_t),
+		     40))];
 
   QUIT;
 
@@ -1614,8 +1619,7 @@
 	  PRINTCHAR ('(');
 
 	  {
-	    EMACS_INT print_length;
-	    int i;
+	    printmax_t i, print_length;
 	    Lisp_Object halftail = obj;
 
 	    /* Negative values of print-length are invalid in CL.
@@ -1623,7 +1627,7 @@
 	    if (NATNUMP (Vprint_length))
 	      print_length = XFASTINT (Vprint_length);
 	    else
-	      print_length = 0;
+	      print_length = TYPE_MAXIMUM (printmax_t);
 
 	    i = 0;
 	    while (CONSP (obj))
@@ -1634,7 +1638,7 @@
 		    /* Simple but imcomplete way.  */
 		    if (i != 0 && EQ (obj, halftail))
 		      {
-			sprintf (buf, " . #%d", i / 2);
+			sprintf (buf, " . #%"pMd, i / 2);
 			strout (buf, -1, -1, printcharfun);
 			goto end_of_list;
 		      }
@@ -1654,15 +1658,16 @@
 		      }
 		  }
 
-		if (i++)
+		if (i)
 		  PRINTCHAR (' ');
 
-		if (print_length && i > print_length)
+		if (print_length <= i)
 		  {
 		    strout ("...", 3, 3, printcharfun);
 		    goto end_of_list;
 		  }
 
+		i++;
 		print_object (XCAR (obj), printcharfun, escapeflag);
 
 		obj = XCDR (obj);
@@ -1798,19 +1803,17 @@
 	      PRINTCHAR (' ');
 	      strout (SDATA (SYMBOL_NAME (h->weak)), -1, -1, printcharfun);
 	      PRINTCHAR (' ');
-	      sprintf (buf, "%ld/%ld", (long) h->count,
-		       (long) ASIZE (h->next));
+	      sprintf (buf, "%"pI"d/%"pI"d", h->count, ASIZE (h->next));
 	      strout (buf, -1, -1, printcharfun);
 	    }
-	  sprintf (buf, " 0x%lx", (unsigned long) h);
+	  sprintf (buf, " %p", h);
 	  strout (buf, -1, -1, printcharfun);
 	  PRINTCHAR ('>');
 #endif
 	  /* Implement a readable output, e.g.:
 	    #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
 	  /* Always print the size. */
-	  sprintf (buf, "#s(hash-table size %ld",
-		   (long) ASIZE (h->next));
+	  sprintf (buf, "#s(hash-table size %"pI"d", ASIZE (h->next));
 	  strout (buf, -1, -1, printcharfun);
 
 	  if (!NILP (h->test))
@@ -2038,7 +2041,7 @@
 	if (MISCP (obj))
 	  sprintf (buf, "(MISC 0x%04x)", (int) XMISCTYPE (obj));
 	else if (VECTORLIKEP (obj))
-	  sprintf (buf, "(PVEC 0x%08lx)", (unsigned long) ASIZE (obj));
+	  sprintf (buf, "(PVEC 0x%08"pI"x)", ASIZE (obj));
 	else
 	  sprintf (buf, "(0x%02x)", (int) XTYPE (obj));
 	strout (buf, -1, -1, printcharfun);

=== modified file 'src/process.c'
--- src/process.c	2011-08-24 21:20:36 +0000
+++ src/process.c	2011-08-29 19:46:15 +0000
@@ -616,8 +616,8 @@
 {
   register Lisp_Object val, tem, name1;
   register struct Lisp_Process *p;
-  char suffix[10];
-  register int i;
+  char suffix[sizeof "<>" + INT_STRLEN_BOUND (printmax_t)];
+  printmax_t i;
 
   p = allocate_process ();
 
@@ -651,7 +651,7 @@
     {
       tem = Fget_process (name1);
       if (NILP (tem)) break;
-      sprintf (suffix, "<%d>", i);
+      sprintf (suffix, "<%"pMd">", i);
       name1 = concat2 (name, build_string (suffix));
     }
   name = name1;

=== modified file 'src/term.c'
--- src/term.c	2011-08-30 17:32:44 +0000
+++ src/term.c	2011-08-30 21:16:49 +0000
@@ -1817,7 +1817,7 @@
 {
   int face_id;
   int len;
-  char buf[9];
+  char buf[sizeof "\\x" + max (6, (sizeof it->c * CHAR_BIT + 3) / 4)];
   char const *str = "    ";
 
   /* Get a face ID for the glyph by utilizing a cache (the same way as

=== modified file 'src/window.h'
--- src/window.h	2011-07-02 10:36:48 +0000
+++ src/window.h	2011-08-29 15:43:34 +0000
@@ -847,11 +847,11 @@
 
 /* Depth in recursive edits.  */
 
-extern int command_loop_level;
+extern EMACS_INT command_loop_level;
 
 /* Depth in minibuffer invocations.  */
 
-extern int minibuf_level;
+extern EMACS_INT minibuf_level;
 
 /* true if we should redraw the mode lines on the next redisplay.  */

=== modified file 'src/xfaces.c'
--- src/xfaces.c	2011-08-19 14:28:36 +0000
+++ src/xfaces.c	2011-08-29 19:58:56 +0000
@@ -3549,6 +3549,8 @@
 	  rdb != NULL))
     {
       char line[512];
+      char *buf = line;
+      ptrdiff_t bufsize = sizeof line;
       Lisp_Object lface = lface_from_face_name (f, Qmenu, 1);
       struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
       const char *myname = SSDATA (Vx_resource_name);
@@ -3561,24 +3563,25 @@
 
       if (STRINGP (LFACE_FOREGROUND (lface)))
 	{
-	  sprintf (line, "%s.%s*foreground: %s",
-		   myname, popup_path,
-		   SDATA (LFACE_FOREGROUND (lface)));
+	  exprintf (&buf, &bufsize, line, -1, "%s.%s*foreground: %s",
+		    myname, popup_path,
+		    SDATA (LFACE_FOREGROUND (lface)));
 	  XrmPutLineResource (&rdb, line);
-	  sprintf (line, "%s.pane.menubar*foreground: %s",
-		   myname, SDATA (LFACE_FOREGROUND (lface)));
+	  exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*foreground: %s",
+		    myname, SDATA (LFACE_FOREGROUND (lface)));
 	  XrmPutLineResource (&rdb, line);
 	  changed_p = 1;
 	}
 
       if (STRINGP (LFACE_BACKGROUND (lface)))
 	{
-	  sprintf (line, "%s.%s*background: %s",
-		   myname, popup_path,
-		   SDATA (LFACE_BACKGROUND (lface)));
+	  exprintf (&buf, &bufsize, line, -1, "%s.%s*background: %s",
+		    myname, popup_path,
+		    SDATA (LFACE_BACKGROUND (lface)));
 	  XrmPutLineResource (&rdb, line);
-	  sprintf (line, "%s.pane.menubar*background: %s",
-		   myname, SDATA (LFACE_BACKGROUND (lface)));
+
+	  exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*background: %s",
+		    myname, SDATA (LFACE_BACKGROUND (lface)));
 	  XrmPutLineResource (&rdb, line);
 	  changed_p = 1;
 	}
@@ -3616,11 +3619,12 @@
 #else
 	      char *fontsetname = SSDATA (xlfd);
 #endif
-	      sprintf (line, "%s.pane.menubar*font%s: %s",
-		       myname, suffix, fontsetname);
+	      exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*font%s: %s",
+			myname, suffix, fontsetname);
 	      XrmPutLineResource (&rdb, line);
-	      sprintf (line, "%s.%s*font%s: %s",
-		       myname, popup_path, suffix, fontsetname);
+
+	      exprintf (&buf, &bufsize, line, -1, "%s.%s*font%s: %s",
+			myname, popup_path, suffix, fontsetname);
 	      XrmPutLineResource (&rdb, line);
 	      changed_p = 1;
 	      if (fontsetname != SSDATA (xlfd))
@@ -3630,6 +3634,9 @@
 
       if (changed_p && f->output_data.x->menubar_widget)
 	free_frame_menubar (f);
+
+      if (buf != line)
+	xfree (buf);
     }
 }

=== modified file 'src/xfns.c'
--- src/xfns.c	2011-08-05 02:15:35 +0000
+++ src/xfns.c	2011-08-29 19:59:51 +0000
@@ -2440,7 +2440,7 @@
   /* Do some needed geometry management.  */
   {
     ptrdiff_t len;
-    char *tem, shell_position[32];
+    char *tem, shell_position[sizeof "=x++" + 4 * INT_STRLEN_BOUND (int)];
     Arg gal[10];
     int gac = 0;
     int extra_borders = 0;

=== modified file 'src/xterm.c'
--- src/xterm.c	2011-08-05 02:19:34 +0000
+++ src/xterm.c	2011-08-29 20:03:30 +0000
@@ -7900,7 +7900,8 @@
 {
   char buf[256];
 
-  sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
+  snprintf (buf, sizeof buf, "Connection lost to X server `%s'",
+	    DisplayString (display));
   x_connection_closed (display, buf);
   return 0;
 }

=== modified file 'src/xterm.h'
--- src/xterm.h	2011-07-07 02:24:56 +0000
+++ src/xterm.h	2011-08-29 20:04:46 +0000
@@ -955,7 +955,8 @@
 extern int x_text_icon (struct frame *, const char *);
 extern int x_bitmap_icon (struct frame *, Lisp_Object);
 extern void x_catch_errors (Display *);
-extern void x_check_errors (Display *, const char *);
+extern void x_check_errors (Display *, const char *)
+  ATTRIBUTE_FORMAT_PRINTF (2, 0);
 extern int x_had_errors_p (Display *);
 extern int x_catching_errors (void);
 extern void x_uncatch_errors (void);