aboutsummaryrefslogtreecommitdiff
path: root/lib/libiconv_modules/UTF7/citrus_utf7.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libiconv_modules/UTF7/citrus_utf7.c')
-rw-r--r--lib/libiconv_modules/UTF7/citrus_utf7.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/lib/libiconv_modules/UTF7/citrus_utf7.c b/lib/libiconv_modules/UTF7/citrus_utf7.c
index f924366551f1..e7c6a0862c54 100644
--- a/lib/libiconv_modules/UTF7/citrus_utf7.c
+++ b/lib/libiconv_modules/UTF7/citrus_utf7.c
@@ -296,7 +296,7 @@ done:
static int
_citrus_UTF7_utf16tomb(_UTF7EncodingInfo * __restrict ei,
- char * __restrict s, size_t n __unused, uint16_t u16,
+ char * __restrict s, size_t n, uint16_t u16,
_UTF7State * __restrict psenc, size_t * __restrict nresult)
{
int bits, i;
@@ -336,6 +336,8 @@ _citrus_UTF7_utf16tomb(_UTF7EncodingInfo * __restrict ei,
psenc->ch[psenc->chlen++] = base64[i];
}
}
+ if (n < (size_t)psenc->chlen)
+ return (E2BIG);
memcpy(s, psenc->ch, psenc->chlen);
*nresult = psenc->chlen;
psenc->chlen = 0;
@@ -352,6 +354,8 @@ _citrus_UTF7_wcrtomb_priv(_UTF7EncodingInfo * __restrict ei,
uint16_t u16[2];
int err, i, len;
size_t nr, siz;
+ char buf[8], *bufp = buf;
+ _UTF7State psenc_save = *psenc;
u32 = (uint32_t)wchar;
if (u32 <= UTF16_MAX) {
@@ -367,14 +371,20 @@ _citrus_UTF7_wcrtomb_priv(_UTF7EncodingInfo * __restrict ei,
return (EILSEQ);
}
siz = 0;
+ if (n > sizeof(buf))
+ n = sizeof(buf);
for (i = 0; i < len; ++i) {
- err = _citrus_UTF7_utf16tomb(ei, s, n, u16[i], psenc, &nr);
- if (err != 0)
- return (err); /* XXX: state has been modified */
- s += nr;
+ err = _citrus_UTF7_utf16tomb(ei, bufp, n, u16[i], psenc, &nr);
+ if (err != 0) {
+ *nresult = (size_t)-1;
+ *psenc = psenc_save; /* restore state */
+ return (err);
+ }
+ bufp += nr;
n -= nr;
siz += nr;
}
+ memcpy(s, buf, siz);
*nresult = siz;
return (0);