X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fstriconveh.c;h=10cb06f9d65af1f4c065c49588c7d887cc9ac526;hb=671c9011cb6944a63f0d15f60252c31bf0ee8e9b;hp=2b6730536b8aa617a08529d53ca2b4dbea0237fe;hpb=2ec42242c58ea05c1d31ff199d8436420049e189;p=gnulib.git diff --git a/lib/striconveh.c b/lib/striconveh.c index 2b6730536..10cb06f9d 100644 --- a/lib/striconveh.c +++ b/lib/striconveh.c @@ -1,11 +1,11 @@ /* Character set conversion with error handling. - Copyright (C) 2001-2007 Free Software Foundation, Inc. + Copyright (C) 2001-2008 Free Software Foundation, Inc. Written by Bruno Haible and Simon Josefsson. - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -13,8 +13,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ #include @@ -80,9 +79,13 @@ iconv_carefully (iconv_t cd, &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 (); + /* 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) @@ -118,31 +121,36 @@ iconv_carefully (iconv_t cd, # endif /* iconv_carefully_1 is like iconv_carefully, except that it stops after - converting one character. */ + 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 = *inbuf; - const char *inptr_end = inptr + *inbytesleft; + const char *inptr_before = *inbuf; + const char *inptr = inptr_before; + const char *inptr_end = inptr_before + *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++) + 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; - /* We expect that no input bytes have been consumed so far. */ - if (inptr != inptr_before) - abort (); + /* 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; @@ -871,9 +879,10 @@ mem_cd_iconveh_internal (const char *src, size_t srclen, /* Now the final memory allocation. */ if (result == tmpbuf) { + size_t memsize = length + extra_alloc; char *memory; - memory = (char *) malloc (length + extra_alloc); + memory = (char *) malloc (memsize > 0 ? memsize : 1); if (memory != NULL) { memcpy (memory, tmpbuf, length); @@ -888,9 +897,10 @@ mem_cd_iconveh_internal (const char *src, size_t srclen, else if (result != *resultp && length + extra_alloc < allocated) { /* Shrink the allocated memory if possible. */ + size_t memsize = length + extra_alloc; char *memory; - memory = (char *) realloc (result, length + extra_alloc); + memory = (char *) realloc (result, memsize > 0 ? memsize : 1); if (memory != NULL) result = memory; } @@ -1016,7 +1026,11 @@ mem_iconveh (const char *src, size_t srclen, } } - if (STRCASEEQ (to_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0)) + if (STRCASEEQ (to_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0) +# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 || _LIBICONV_VERSION >= 0x0105 + || c_strcasecmp (to_codeset, "UTF-8//TRANSLIT") == 0 +# endif + ) cd2 = (iconv_t)(-1); else { @@ -1152,7 +1166,11 @@ str_iconveh (const char *src, } } - if (STRCASEEQ (to_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0)) + if (STRCASEEQ (to_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0) +# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 || _LIBICONV_VERSION >= 0x0105 + || c_strcasecmp (to_codeset, "UTF-8//TRANSLIT") == 0 +# endif + ) cd2 = (iconv_t)(-1); else {