]> granicus.if.org Git - neomutt/commitdiff
Certain versions of libc may segfault during regex processing if given
authorAnders Helmersson <anders.helmersson.utsikt@wasadata.net>
Sun, 7 Aug 2005 06:20:37 +0000 (06:20 +0000)
committerAnders Helmersson <anders.helmersson.utsikt@wasadata.net>
Sun, 7 Aug 2005 06:20:37 +0000 (06:20 +0000)
incomplete multibyte characters. Work around this by manually trimming
the display buffer. I modified it somewhat to only check when the
situation is most likely to occur: fgets has read all the way to the
capacity of the buffer. Thanks also to Tamo for his comments.

pager.c

diff --git a/pager.c b/pager.c
index 898f380fc7e3037a5c7d75c8b9a4f175cb2134b8..e40d34ce7e6e326d519baadfc1d643c7e79b4b9d 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -969,13 +969,34 @@ static int grok_ansi(unsigned char *buf, int pos, ansi_attr *a)
   return pos;
 }
 
+/* trim tail of buf so that it contains complete multibyte characters */
+static int
+trim_incomplete_mbyte(unsigned char *buf, size_t len)
+{
+  mbstate_t mbstate;
+  size_t k;
+
+  memset (&mbstate, 0, sizeof (mbstate));
+  for (; len > 0; buf += k, len -= k)
+  {
+    k = mbrtowc (NULL, (char *) buf, len, &mbstate);
+    if (k == -2) 
+      break; 
+    else if (k == -1 || k == 0) 
+      k = 1;
+  }
+  *buf = '\0';
+
+  return len;
+}
+
 static int
 fill_buffer (FILE *f, long *last_pos, long offset, unsigned char *buf, 
             unsigned char *fmt, size_t blen, int *buf_ready)
 {
   unsigned char *p;
   static int b_read;
-
+  
   if (*buf_ready == 0)
   {
     buf[blen - 1] = 0;
@@ -990,6 +1011,11 @@ fill_buffer (FILE *f, long *last_pos, long offset, unsigned char *buf,
     b_read = (int) (*last_pos - offset);
     *buf_ready = 1;
 
+    /* incomplete mbyte characters trigger a segfault in regex processing for
+     * certain versions of glibc. Trim them if necessary. */
+    if (b_read == blen - 2)
+      b_read -= trim_incomplete_mbyte(buf, b_read);
+    
     /* copy "buf" to "fmt", but without bold and underline controls */
     p = buf;
     while (*p)