Author: tijl
Date: Sun May 24 15:47:06 2015
New Revision: 283418
URL: https://svnweb.freebsd.org/changeset/base/283418

Log:
  When only 2 bytes can be read from a 4 byte UTF-16 character in a base64
  encoded chunk of a UTF-7 string, treat that as an incomplete character and
  return an error instead of a shift sequence and no error.
  
  Also check that the low 2 bytes have a valid value.
  
  MFC after:    1 week

Modified:
  head/lib/libiconv_modules/UTF7/citrus_utf7.c

Modified: head/lib/libiconv_modules/UTF7/citrus_utf7.c
==============================================================================
--- head/lib/libiconv_modules/UTF7/citrus_utf7.c        Sun May 24 15:45:36 
2015        (r283417)
+++ head/lib/libiconv_modules/UTF7/citrus_utf7.c        Sun May 24 15:47:06 
2015        (r283418)
@@ -62,8 +62,7 @@ typedef struct {
        unsigned int
                mode: 1,        /* whether base64 mode */
                bits: 4,        /* need to hold 0 - 15 */
-               cache: 22,      /* 22 = BASE64_BIT + UTF16_BIT */
-               surrogate: 1;   /* whether surrogate pair or not */
+               cache: 22;      /* 22 = BASE64_BIT + UTF16_BIT */
        int chlen;
        char ch[4]; /* BASE64_IN, 3 * 6 = 18, most closed to UTF16_BIT */
 } _UTF7State;
@@ -253,34 +252,31 @@ _citrus_UTF7_mbrtowc_priv(_UTF7EncodingI
                *nresult = (size_t)_ENCODING_IS_STATE_DEPENDENT;
                return (0);
        }
-       if (psenc->surrogate) {
-               hi = (psenc->cache >> psenc->bits) & UTF16_MAX;
-               if (hi < HISRG_MIN || hi > HISRG_MAX)
-                       return (EINVAL);
-               siz = 0;
-       } else {
-               err = _citrus_UTF7_mbtoutf16(ei, &hi, s, n, psenc, &nr);
-               if (nr == (size_t)-1 || nr == (size_t)-2) {
-                       *nresult = nr;
-                       return (err);
-               }
-               if (err != 0)
-                       return (err);
-               n -= nr;
-               siz = nr;
-               if (hi < HISRG_MIN || hi > HISRG_MAX) {
-                       u32 = (uint32_t)hi;
-                       goto done;
-               }
-               psenc->surrogate = 1;
+       err = _citrus_UTF7_mbtoutf16(ei, &hi, s, n, psenc, &nr);
+       if (nr == (size_t)-1 || nr == (size_t)-2) {
+               *nresult = nr;
+               return (err);
+       }
+       if (err != 0)
+               return (err);
+       n -= nr;
+       siz = nr;
+       if (hi < HISRG_MIN || hi > HISRG_MAX) {
+               u32 = (uint32_t)hi;
+               goto done;
        }
        err = _citrus_UTF7_mbtoutf16(ei, &lo, s, n, psenc, &nr);
        if (nr == (size_t)-1 || nr == (size_t)-2) {
+               psenc->chlen = 1; /* make get_state_desc return incomplete */
                *nresult = nr;
                return (err);
        }
        if (err != 0)
                return (err);
+       if (lo < LOSRG_MIN || lo > LOSRG_MAX) {
+               *nresult = (size_t)-1;
+               return (EILSEQ);
+       }
        hi -= HISRG_MIN;
        lo -= LOSRG_MIN;
        u32 = (hi << 10 | lo) + SRG_BASE;
@@ -293,7 +289,6 @@ done:
                _citrus_UTF7_init_state(ei, psenc);
        } else {
                *nresult = siz;
-               psenc->surrogate = 0;
        }
        return (err);
 }
@@ -392,7 +387,7 @@ _citrus_UTF7_put_state_reset(_UTF7Encodi
 {
        int bits, pos;
 
-       if (psenc->chlen != 0 || psenc->bits > BASE64_BIT || psenc->surrogate)
+       if (psenc->chlen != 0 || psenc->bits > BASE64_BIT)
                return (EINVAL);
 
        if (psenc->mode) {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to