From: Eli Zaretskii <eliz@gnu.org>
Date: Mon, 12 Nov 2012 15:25:34 +0000 (+0200)
Subject: Fix bug #12867 with crashes due to large field width in mode-line format.
X-Git-Tag: emacs-24.2.90~102
X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=325202732506c35fec0a7bd772d218eaf0ac659f;p=emacs.git

Fix bug #12867 with crashes due to large field width in mode-line format.

 src/xdisp.c (decode_mode_spec): Limit the value of WIDTH argument
 passed to pint2str and pint2hrstr to be at most the size of the
 frame's decode_mode_spec_buffer.  This avoids crashes with very
 large values of FIELD_WIDTH argument to decode_mode_spec.
---

diff --git a/src/ChangeLog b/src/ChangeLog
index 9e0f92f557e..494b2179516 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
+2012-11-12  Eli Zaretskii  <eliz@gnu.org>
+
+	* xdisp.c (decode_mode_spec): Limit the value of WIDTH argument
+	passed to pint2str and pint2hrstr to be at most the size of the
+	frame's decode_mode_spec_buffer.  This avoids crashes with very
+	large values of FIELD_WIDTH argument to decode_mode_spec.
+	(Bug#12867)
+
 2012-11-07  Martin Rudalics  <rudalics@gmx.at>
 
 	* window.c (Fsplit_window_internal): Set combination limit of
diff --git a/src/xdisp.c b/src/xdisp.c
index c7195504c4c..290c3a07fe9 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -21380,6 +21380,12 @@ decode_mode_spec (struct window *w, register int c, int field_width,
   Lisp_Object obj;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
+  /* We are going to use f->decode_mode_spec_buffer as the buffer to
+     produce strings from numerical values, so limit preposterously
+     large values of FIELD_WIDTH to avoid overrunning the buffer's
+     end.  The size of the buffer is enough for FRAME_MESSAGE_BUF_SIZE
+     bytes plus the terminating null.  */
+  int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
   struct buffer *b = current_buffer;
 
   obj = Qnil;
@@ -21475,7 +21481,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
 	{
 	  ptrdiff_t col = current_column ();
 	  wset_column_number_displayed (w, make_number (col));
-	  pint2str (decode_mode_spec_buf, field_width, col);
+	  pint2str (decode_mode_spec_buf, width, col);
 	  return decode_mode_spec_buf;
 	}
 
@@ -21506,14 +21512,14 @@ decode_mode_spec (struct window *w, register int c, int field_width,
     case 'i':
       {
 	ptrdiff_t size = ZV - BEGV;
-	pint2str (decode_mode_spec_buf, field_width, size);
+	pint2str (decode_mode_spec_buf, width, size);
 	return decode_mode_spec_buf;
       }
 
     case 'I':
       {
 	ptrdiff_t size = ZV - BEGV;
-	pint2hrstr (decode_mode_spec_buf, field_width, size);
+	pint2hrstr (decode_mode_spec_buf, width, size);
 	return decode_mode_spec_buf;
       }
 
@@ -21620,12 +21626,12 @@ decode_mode_spec (struct window *w, register int c, int field_width,
 	line_number_displayed = 1;
 
 	/* Make the string to show.  */
-	pint2str (decode_mode_spec_buf, field_width, topline + nlines);
+	pint2str (decode_mode_spec_buf, width, topline + nlines);
 	return decode_mode_spec_buf;
     no_value:
         {
 	  char* p = decode_mode_spec_buf;
-	  int pad = field_width - 2;
+	  int pad = width - 2;
 	  while (pad-- > 0)
 	    *p++ = ' ';
 	  *p++ = '?';