bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

striconveh fix


From: Bruno Haible
Subject: striconveh fix
Date: Sun, 7 Sep 2008 23:18:57 +0200
User-agent: KMail/1.5.4

striconveh assumes that when iconv() returns -1 with errno = EINVAL, it
has not incremented the input pointer. This does not hold with GNU libiconv
and with Solaris iconv e.g. when converting from UTF-7. Fixed like this:


2008-09-07  Bruno Haible  <address@hidden>

        Make striconveh work better with stateful encodings.
        * lib/striconveh.c (iconv_carefully, iconv_carefully_1): Don't assume
        that iconv does not increment the inptr when returning -1/EINVAL.

*** lib/striconveh.c.orig       2008-09-07 23:15:07.000000000 +0200
--- lib/striconveh.c    2008-09-07 19:51:17.000000000 +0200
***************
*** 79,87 ****
                       &outptr, &outsize);
          if (!(res == (size_t)(-1) && errno == EINVAL))
            break;
!         /* We expect that no input bytes have been consumed so far.  */
!         if (inptr != inptr_before)
!           abort ();
        }
  
        if (res == 0)
--- 79,91 ----
                       &outptr, &outsize);
          if (!(res == (size_t)(-1) && errno == EINVAL))
            break;
!         /* iconv can eat up a shift sequence but give EINVAL while attempting
!            to convert the first character.  E.g. libiconv does this.  */
!         if (inptr > inptr_before)
!           {
!             res = 0;
!             break;
!           }
        }
  
        if (res == 0)
***************
*** 117,147 ****
  # endif
  
  /* iconv_carefully_1 is like iconv_carefully, except that it stops after
!    converting one character.  */
  static size_t
  iconv_carefully_1 (iconv_t cd,
                   const char **inbuf, size_t *inbytesleft,
                   char **outbuf, size_t *outbytesleft,
                   bool *incremented)
  {
!   const char *inptr = *inbuf;
!   const char *inptr_end = inptr + *inbytesleft;
    char *outptr = *outbuf;
    size_t outsize = *outbytesleft;
-   const char *inptr_before = inptr;
    size_t res = (size_t)(-1);
    size_t insize;
  
!   for (insize = 1; inptr + insize <= inptr_end; insize++)
      {
        res = iconv (cd,
                   (ICONV_CONST char **) &inptr, &insize,
                   &outptr, &outsize);
        if (!(res == (size_t)(-1) && errno == EINVAL))
        break;
!       /* We expect that no input bytes have been consumed so far.  */
!       if (inptr != inptr_before)
!       abort ();
      }
  
    *inbuf = inptr;
--- 121,156 ----
  # endif
  
  /* iconv_carefully_1 is like iconv_carefully, except that it stops after
!    converting one character or one shift sequence.  */
  static size_t
  iconv_carefully_1 (iconv_t cd,
                   const char **inbuf, size_t *inbytesleft,
                   char **outbuf, size_t *outbytesleft,
                   bool *incremented)
  {
!   const char *inptr_before = *inbuf;
!   const char *inptr = inptr_before;
!   const char *inptr_end = inptr_before + *inbytesleft;
    char *outptr = *outbuf;
    size_t outsize = *outbytesleft;
    size_t res = (size_t)(-1);
    size_t insize;
  
!   for (insize = 1; inptr_before + insize <= inptr_end; insize++)
      {
+       inptr = inptr_before;
        res = iconv (cd,
                   (ICONV_CONST char **) &inptr, &insize,
                   &outptr, &outsize);
        if (!(res == (size_t)(-1) && errno == EINVAL))
        break;
!       /* iconv can eat up a shift sequence but give EINVAL while attempting
!        to convert the first character.  E.g. libiconv does this.  */
!       if (inptr > inptr_before)
!       {
!         res = 0;
!         break;
!       }
      }
  
    *inbuf = inptr;





reply via email to

[Prev in Thread] Current Thread [Next in Thread]