diff options
Diffstat (limited to 'iconv')
-rw-r--r-- | iconv/gconv_close.c | 10 | ||||
-rw-r--r-- | iconv/gconv_simple.c | 55 |
2 files changed, 49 insertions, 16 deletions
diff --git a/iconv/gconv_close.c b/iconv/gconv_close.c index 791c0259a3..912fa26d13 100644 --- a/iconv/gconv_close.c +++ b/iconv/gconv_close.c @@ -40,11 +40,11 @@ __gconv_close (gconv_t cd) if (srunp->end_fct != NULL) (*srunp->end_fct) (drunp); else - { - free (drunp->outbuf); - if (drunp->data != NULL) - free (drunp->data); - } + if (drunp->data != NULL) + free (drunp->data); + + if (!drunp->is_last && drunp->outbuf != NULL) + free (drunp->outbuf); /* Next step. */ ++srunp; diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c index f769795273..51e4673b2d 100644 --- a/iconv/gconv_simple.c +++ b/iconv/gconv_simple.c @@ -18,6 +18,7 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <errno.h> #include <gconv.h> #include <stdlib.h> #include <string.h> @@ -112,16 +113,20 @@ __gconv_transform_ucs4_utf8 (struct gconv_step *step, } else { + int save_errno = errno; do_write = 0; do { const char *newinbuf = inbuf; - size_t actually = __wmemrtombs (&data->outbuf[data->outbufavail], - (const wchar_t **) &newinbuf, - *inlen / sizeof (wchar_t), - data->outbufsize - data->outbufavail, - (mbstate_t *) data->data); + size_t actually; + + errno = 0; + actually = __wmemrtombs (&data->outbuf[data->outbufavail], + (const wchar_t **) &newinbuf, + *inlen / sizeof (wchar_t), + data->outbufsize - data->outbufavail, + (mbstate_t *) data->data); /* Remember how much we converted. */ do_write += newinbuf - inbuf; @@ -129,6 +134,13 @@ __gconv_transform_ucs4_utf8 (struct gconv_step *step, data->outbufavail += actually; + /* Check whether an illegal character appeared. */ + if (errno != 0) + { + result = GCONV_ILLEGAL_INPUT; + break; + } + if (data->is_last) { /* This is the last step. */ @@ -159,6 +171,8 @@ __gconv_transform_ucs4_utf8 (struct gconv_step *step, } } while (*inlen > 0 && result == GCONV_EMPTY_INPUT); + + __set_errno (save_errno); } if (written != NULL && data->is_last) @@ -201,17 +215,20 @@ __gconv_transform_utf8_ucs4 (struct gconv_step *step, } else { + int save_errno = errno; do_write = 0; do { const char *newinbuf = inbuf; - size_t actually = __wmemrtowcs ((wchar_t *) &data->outbuf[data->outbufavail], - &newinbuf, *inlen, - ((data->outbufsize - - data->outbufavail) - / sizeof (wchar_t)), - (mbstate_t *) data->data); + size_t actually; + + errno = 0; + actually = __wmemrtowcs ((wchar_t *) &data->outbuf[data->outbufavail], + &newinbuf, *inlen, + ((data->outbufsize + - data->outbufavail) / sizeof (wchar_t)), + (mbstate_t *) data->data); /* Remember how much we converted. */ do_write += actually; @@ -219,6 +236,20 @@ __gconv_transform_utf8_ucs4 (struct gconv_step *step, data->outbufavail += actually * sizeof (wchar_t); + /* Check whether an illegal character appeared. */ + if (errno != 0) + { + result = GCONV_ILLEGAL_INPUT; + break; + } + + if (*inlen == 0 && !mbsinit ((mbstate_t *) data->data)) + { + /* We have an incomplete character at the end. */ + result = GCONV_INCOMPLETE_INPUT; + break; + } + if (data->is_last) { /* This is the last step. */ @@ -249,6 +280,8 @@ __gconv_transform_utf8_ucs4 (struct gconv_step *step, } } while (*inlen > 0 && result == GCONV_EMPTY_INPUT); + + __set_errno (save_errno); } if (written != NULL && data->is_last) |