changeset: 6590:c8c76a6a1e61
user:      Karel Zak <k...@redhat.com>
date:      Sun Mar 20 17:06:16 2016 -0700
link:      http://dev.mutt.org/hg/mutt/rev/c8c76a6a1e61

Improve error handling in mutt_wstr_trunc().

This is Karel Zak's patch to fix handling of (illegal) multi-byte chars.

 * mutt_wstr_trunc():
 Reset mbstate after error in mbrtowc().
 Set wc=0 if wcwidth returns < 0.

Addresses: https://github.com/karelzak/mutt-kz/issues/58

Thanks to Richard Russon for bringing this patch to our attention.

changeset: 6591:a3450fd50d11
user:      Kevin McCarthy <ke...@8t8.us>
date:      Tue Mar 22 18:00:13 2016 -0700
link:      http://dev.mutt.org/hg/mutt/rev/a3450fd50d11

Clean up mutt_wstr_trunc() some more.

* Change return type to size_t.
  The return value is the cumulation of values from mbrtowc(), which
  returns size_t.  All callers already assign the return value to a
  size_t, requiring no external changes.

* Change the local variables n, w, l, and cl to size_t.
  n is the strlen of the src parameter.  l and cl are used for the
  return value.  w is assigned to the *width parameter, which is
  size_t.

  cw is kept as an int, because wcwidth returns type int.

* Change error handling of mbrtowc to be the same as other functions
  in mutt: only reset mbstate when the retval==-1.  When retvat==-2,
  set cl=n to break out of the loop.  Also, set wc to replacement_char
  and allow the logic below to determine the width instead of
  hardcoding to 1.

diffs (57 lines):

diff -r b302f9868d78 -r a3450fd50d11 curs_lib.c
--- a/curs_lib.c        Tue Mar 22 12:35:54 2016 -0700
+++ b/curs_lib.c        Tue Mar 22 18:00:13 2016 -0700
@@ -949,11 +949,11 @@
 
 /* See how many bytes to copy from string so its at most maxlen bytes
  * long and maxwid columns wide */
-int mutt_wstr_trunc (const char *src, size_t maxlen, size_t maxwid, size_t 
*width)
+size_t mutt_wstr_trunc (const char *src, size_t maxlen, size_t maxwid, size_t 
*width)
 {
   wchar_t wc;
-  int w = 0, l = 0, cl;
-  int cw, n;
+  size_t n, w = 0, l = 0, cl;
+  int cw;
   mbstate_t mbstate;
 
   if (!src)
@@ -965,15 +965,19 @@
   for (w = 0; n && (cl = mbrtowc (&wc, src, n, &mbstate)); src += cl, n -= cl)
   {
     if (cl == (size_t)(-1) || cl == (size_t)(-2))
-      cw = cl = 1;
-    else
     {
-      cw = wcwidth (wc);
-      /* hack because M_TREE symbols aren't turned into characters
-       * until rendered by print_enriched_string (#3364) */
-      if (cw < 0 && cl == 1 && src[0] && src[0] < M_TREE_MAX)
-       cw = 1;
+      if (cl == (size_t)(-1))
+        memset (&mbstate, 0, sizeof (mbstate));
+      cl = (cl == (size_t)(-1)) ? 1 : n;
+      wc = replacement_char ();
     }
+    cw = wcwidth (wc);
+    /* hack because M_TREE symbols aren't turned into characters
+     * until rendered by print_enriched_string (#3364) */
+    if (cw < 0 && cl == 1 && src[0] && src[0] < M_TREE_MAX)
+      cw = 1;
+    else if (cw < 0)
+      cw = 0;                  /* unprintable wchar */
     if (cl + l > maxlen || cw + w > maxwid)
       break;
     l += cl;
diff -r b302f9868d78 -r a3450fd50d11 protos.h
--- a/protos.h  Tue Mar 22 12:35:54 2016 -0700
+++ b/protos.h  Tue Mar 22 18:00:13 2016 -0700
@@ -356,7 +356,7 @@
 int mutt_smtp_send (const ADDRESS *, const ADDRESS *, const ADDRESS *,
                     const ADDRESS *, const char *, int);
 #endif
-int mutt_wstr_trunc (const char *, size_t, size_t, size_t *);
+size_t mutt_wstr_trunc (const char *, size_t, size_t, size_t *);
 int mutt_charlen (const char *s, int *);
 int mutt_strwidth (const char *);
 int mutt_compose_menu (HEADER *, char *, size_t, HEADER *, int);

Reply via email to