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

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



The following reply was made to PR mutt/1536; it has been noted by GNATS.

From: Brendan Cully <brendan@xxxxxxxxxx>
To: Mutt Developers <mutt-dev@xxxxxxxx>
Cc: bug-any@xxxxxxxxxxxxx
Subject: mutt/1536: Segment fault with long lines when LANG=*.UTF-8
Date: Sat, 06 Aug 2005 11:20:48 -0700

 --5mCyUwZo2JvN/JJP
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 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.
 
 --5mCyUwZo2JvN/JJP
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename="mbyte.diff"
 
 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)
 
 --5mCyUwZo2JvN/JJP--