about summary refs log tree commit diff
path: root/iconv
diff options
context:
space:
mode:
Diffstat (limited to 'iconv')
-rw-r--r--iconv/gconv_close.c10
-rw-r--r--iconv/gconv_simple.c55
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)