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
This commit is contained in:
Tijl Coosemans 2015-05-24 15:47:06 +00:00
parent 36204c3016
commit f171d54687

View File

@ -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,12 +252,6 @@ _citrus_UTF7_mbrtowc_priv(_UTF7EncodingInfo * __restrict ei,
*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;
@ -272,15 +265,18 @@ _citrus_UTF7_mbrtowc_priv(_UTF7EncodingInfo * __restrict ei,
u32 = (uint32_t)hi;
goto done;
}
psenc->surrogate = 1;
}
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 @@ _citrus_UTF7_mbrtowc_priv(_UTF7EncodingInfo * __restrict ei,
_citrus_UTF7_init_state(ei, psenc);
} else {
*nresult = siz;
psenc->surrogate = 0;
}
return (err);
}
@ -392,7 +387,7 @@ _citrus_UTF7_put_state_reset(_UTF7EncodingInfo * __restrict ei __unused,
{
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) {