Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 2 Jun 2015 09:42:00 +0000 (UTC)
From:      Tijl Coosemans <tijl@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r283908 - stable/10/lib/libiconv_modules/UTF7
Message-ID:  <201506020942.t529g0qD001737@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tijl
Date: Tue Jun  2 09:42:00 2015
New Revision: 283908
URL: https://svnweb.freebsd.org/changeset/base/283908

Log:
  MFC r283406,283418:
  
  Fix decoding of UTF-7 when a base64 encoded chunk appears at the end of
  the input buffer.
  
  _citrus_UTF7_mbtoutf16 stored the decoder state at the beginning so it
  could restore this state on an incomplete character such that the next
  call would restart the decoding.  The problem was that "-" (end of base64
  mode) at the end of a string was also treated as an incomplete character
  but was also removed from the state buffer.  So the initial state would be
  restored (with base64 mode) and the next call would no longer see the "-"
  so it continued in base64 mode.
  
  This state saving/restoring isn't needed here.  It's already handled
  elsewhere (citrus_iconv_std.c:_citrus_iconv_std_iconv_convert) so just
  remove it.
  
  Also initialise *nresult.
  
  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.
  
  PR:		200398

Modified:
  stable/10/lib/libiconv_modules/UTF7/citrus_utf7.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libiconv_modules/UTF7/citrus_utf7.c
==============================================================================
--- stable/10/lib/libiconv_modules/UTF7/citrus_utf7.c	Tue Jun  2 09:05:45 2015	(r283907)
+++ stable/10/lib/libiconv_modules/UTF7/citrus_utf7.c	Tue Jun  2 09:42:00 2015	(r283908)
@@ -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;
@@ -154,21 +153,17 @@ _citrus_UTF7_mbtoutf16(_UTF7EncodingInfo
     uint16_t * __restrict u16, char ** __restrict s, size_t n,
     _UTF7State * __restrict psenc, size_t * __restrict nresult)
 {
-	_UTF7State sv;
 	char *s0;
 	int done, i, len;
 
+	*nresult = 0;
 	s0 = *s;
-	sv = *psenc;
 
 	for (i = 0, done = 0; done == 0; i++) {
 		if (i == psenc->chlen) {
 			if (n-- < 1) {
 				*nresult = (size_t)-2;
 				*s = s0;
-				sv.chlen = psenc->chlen;
-				memcpy(sv.ch, psenc->ch, sizeof(sv.ch));
-				*psenc = sv;
 				return (0);
 			}
 			psenc->ch[psenc->chlen++] = *s0++;
@@ -257,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;
@@ -297,7 +289,6 @@ done:
 		_citrus_UTF7_init_state(ei, psenc);
 	} else {
 		*nresult = siz;
-		psenc->surrogate = 0;
 	}
 	return (err);
 }
@@ -396,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) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506020942.t529g0qD001737>