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);