<<< Date Index >>>     <<< Thread Index >>>

mutt/1536: Segment fault with long lines when LANG=*.UTF-8



On Sunday, 07 August 2005 at 01:36, TAKAHASHI Tamotsu wrote:
> On Fri, 05 Aug 2005, Brendan Cully wrote:
> > Ok, this sounds a little bit risky. How about another suggestion: we
> > only do the check when b_read == blen - 2? that is, when fgets has run
> > all the way to the end of the buffer. That should keep things speedy
> > in the normal case.
> 
> Sounds good!
> 
> 
> But please don't forget the following issue:
> 
> > On Friday, 05 August 2005 at 18:40, TAKAHASHI Tamotsu wrote:
> > > And I'm afraid the patches should malloc, clear and use mbstate
> > > instead of NULL. Every other mbrtowc() in mutt is using its own
> > > mbstate, AFAIK. It could work well even without its own mbstate,
> > > but it would be hard to debug once a problem occurred.

Does this work? I've never been able to reproduce the segfault, so I
don't know whether or not I've introduced an off-by-one error or
something.
Index: pager.c
===================================================================
RCS file: /home/roessler/cvs/mutt/pager.c,v
retrieving revision 3.21
diff -u -p -r3.21 pager.c
--- pager.c     30 Jul 2005 04:40:45 -0000      3.21
+++ pager.c     6 Aug 2005 18:04:04 -0000
@@ -969,13 +969,34 @@ static int grok_ansi(unsigned char *buf,
   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,9 @@ fill_buffer (FILE *f, long *last_pos, lo
     b_read = (int) (*last_pos - offset);
     *buf_ready = 1;
 
+    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)