Fix lots of bugs.
authordrepper <drepper>
Mon, 24 Nov 1997 02:03:50 +0000 (02:03 +0000)
committerdrepper <drepper>
Mon, 24 Nov 1997 02:03:50 +0000 (02:03 +0000)
12 files changed:
iconv/gconv.c
iconv/gconv.h
iconv/gconv_builtin.h
iconv/gconv_close.c
iconv/gconv_conf.c
iconv/gconv_db.c
iconv/gconv_dl.c
iconv/gconv_open.c
iconv/gconv_simple.c
iconv/iconv.c
iconv/iconv_close.c
iconv/iconv_open.c

index 0cbb052..5df1635 100644 (file)
@@ -30,6 +30,9 @@ __gconv (gconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf,
   size_t oldinbytes = *inbytesleft;
   int result;
 
+  if (cd == (gconv_t) -1L)
+    return GCONV_ILLEGAL_DESCRIPTOR;
+
   cd->data[last_step].outbuf = *outbuf;
   cd->data[last_step].outbufavail = 0;
   cd->data[last_step].outbufsize = *outbytesleft;
index 2c42f99..879db49 100644 (file)
@@ -37,6 +37,7 @@ enum
   GCONV_EMPTY_INPUT,
   GCONV_FULL_OUTPUT,
   GCONV_ILLEGAL_INPUT,
+  GCONV_INCOMPLETE_INPUT,
 
   GCONV_ILLEGAL_DESCRIPTOR,
   GCONV_INTERNAL_ERROR
index a3070a5..8dcc3aa 100644 (file)
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-BUILTIN_TRANSFORMATION ("\\([^/]+\\)/UCS4/\\([^/]*\\)", NULL, 0,
+BUILTIN_TRANSFORMATION ("([^/]+)/UCS4/([^/]*)", NULL, 0,
                        "\\1/UTF8/\\2", 1, "=ucs4->utf8",
                        __gconv_transform_ucs4_utf8,
                        __gconv_transform_init_rstate,
                        __gconv_transform_end_rstate)
 
-BUILTIN_TRANSFORMATION ("\\([^/]+\\)/UTF8/\\([^/]*\\)", NULL, 0,
+BUILTIN_TRANSFORMATION ("([^/]+)/UTF8/([^/]*)", NULL, 0,
                        "\\1/UCS4/\\2", 1, "=utf8->ucs4",
                        __gconv_transform_utf8_ucs4,
                        __gconv_transform_init_rstate,
                        __gconv_transform_end_rstate)
 
-BUILTIN_TRANSFORMATION ("\\(.*\\)", NULL, 0, "\\1", 1, "=dummy",
+BUILTIN_TRANSFORMATION ("(.*)", NULL, 0, "\\1", 1, "=dummy",
                        __gconv_transform_dummy, NULL, NULL)
index d3d023f..791c025 100644 (file)
@@ -48,9 +48,8 @@ __gconv_close (gconv_t cd)
 
       /* Next step.  */
       ++srunp;
-      ++drunp;
     }
-  while (!drunp->is_last);
+  while (!(drunp++)->is_last);
 
   /* Save the pointer, we need it below.  */
   srunp = cd->steps;
index d3c13d7..8a72c7a 100644 (file)
@@ -19,6 +19,7 @@
    Boston, MA 02111-1307, USA.  */
 
 #include <ctype.h>
+#include <errno.h>
 #include <gconv.h>
 #include <search.h>
 #include <stdio.h>
@@ -35,6 +36,12 @@ static const char default_gconv_path[] = GCONV_PATH;
    along the path.  */
 static const char gconv_conf_filename[] = "gconv-modules";
 
+/* Filename extension for the modules.  */
+#ifndef MODULE_EXT
+# define MODULE_EXT ".so"
+#endif
+static const char gconv_module_ext[] = MODULE_EXT;
+
 /* We have a few builtin transformations.  */
 static struct gconv_module builtin_modules[] =
 {
@@ -111,15 +118,18 @@ add_alias (char *rp)
 
   new_alias = (struct gconv_alias *)
     malloc (sizeof (struct gconv_alias) + (wp - from));
-  new_alias->fromname = memcpy ((char *) new_alias
-                               + sizeof (struct gconv_alias),
-                               from, to - from);
-  new_alias->toname = memcpy ((char *) new_alias + sizeof (struct gconv_alias)
-                             + (to - from), to, wp - to);
-
-  if (__tsearch (new_alias, &__gconv_alias_db, __gconv_alias_compare) == NULL)
-    /* Something went wrong, free this entry.  */
-    free (new_alias);
+  if (new_alias != NULL)
+    {
+      new_alias->fromname = memcpy ((char *) new_alias
+                                   + sizeof (struct gconv_alias),
+                                   from, wp - from);
+      new_alias->toname = new_alias->fromname + (to - from);
+
+      if (__tsearch (new_alias, &__gconv_alias_db, __gconv_alias_compare)
+         == NULL)
+       /* Something went wrong, free this entry.  */
+       free (new_alias);
+    }
 }
 
 
@@ -138,6 +148,7 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
   char *from, *to, *module, *wp;
   size_t const_len;
   int from_is_regex;
+  int need_ext;
   int cost;
 
   while (isspace (*rp))
@@ -195,65 +206,68 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
     /* Increment by one for the slash.  */
     ++dir_len;
 
+  /* See whether we must add the ending.  */
+  need_ext = 0;
+  if (wp - module < sizeof (gconv_module_ext)
+      || memcmp (wp - sizeof (gconv_module_ext), gconv_module_ext,
+                sizeof (gconv_module_ext)) != 0)
+    /* We must add the module extension.  */
+    need_ext = sizeof (gconv_module_ext) - 1;
+
   /* We've collected all the information, now create an entry.  */
 
-  const_len = 0;
   if (from_is_regex)
-    do
-      ++const_len;
-    while (isalnum (from[const_len]) || from[const_len] == '-'
-          || from[const_len] == '/' || from[const_len] == '.'
-          || from[const_len] == '_');
+    {
+      const_len = 0;
+      while (isalnum (from[const_len]) || from[const_len] == '-'
+            || from[const_len] == '/' || from[const_len] == '.'
+            || from[const_len] == '_')
+       ++const_len;
+    }
+  else
+    const_len = to - from - 1;
 
   new_module = (struct gconv_module *) malloc (sizeof (struct gconv_module)
-                                              + (wp - from) + const_len
-                                              + dir_len);
+                                              + (wp - from)
+                                              + dir_len + need_ext);
   if (new_module != NULL)
     {
+      char *tmp;
+
+      new_module->from_constpfx = memcpy ((char *) new_module
+                                         + sizeof (struct gconv_module),
+                                         from, to - from);
       if (from_is_regex)
-       {
-         new_module->from_pattern = memcpy ((char *) new_module
-                                            + sizeof (struct gconv_module),
-                                            from, to - from);
-         new_module->from_constpfx = memcpy ((char *) new_module->from_pattern
-                                             + (to - from),
-                                             from, const_len);
-         ((char *) new_module->from_constpfx)[const_len] = '\0';
-         new_module->from_constpfx_len = const_len;
-         ++const_len;
-       }
+       new_module->from_pattern = new_module->from_constpfx;
       else
-       {
-         new_module->from_pattern = NULL;
-         new_module->from_constpfx = memcpy ((char *) new_module
-                                             + sizeof (struct gconv_module),
-                                             from, to - from);
-         new_module->from_constpfx_len = to - from - 1;
-         const_len = to - from;
-       }
+       new_module->from_pattern = NULL;
+
+      new_module->from_constpfx_len = const_len;
+
       new_module->from_regex = NULL;
 
       new_module->to_string = memcpy ((char *) new_module->from_constpfx
-                                     + const_len + 1, to, module - to);
+                                     + (to - from), to, module - to);
 
       new_module->cost = cost;
 
+      new_module->module_name = (char *) new_module->to_string + (module - to);
+
       if (dir_len == 0)
-       new_module->module_name = memcpy ((char *) new_module->to_string
-                                         + (module - to),
-                                         module, wp - module);
+       tmp = (char *) new_module->module_name;
       else
        {
-         char *tmp;
-         new_module->module_name = ((char *) new_module->to_string
-                                    + (module - to));
          tmp = __mempcpy ((char *) new_module->module_name,
                           directory, dir_len - 1);
          *tmp++ = '/';
-         memcpy (tmp, module, wp - module);
        }
 
-      if (__tfind (new_module, *modules, module_compare) != NULL)
+      tmp = __mempcpy (tmp, module, wp - module);
+
+      if (need_ext)
+       memcpy (tmp - 1, gconv_module_ext, sizeof (gconv_module_ext));
+
+      if (__tfind (new_module, modules, module_compare) == NULL)
        if (__tsearch (new_module, modules, module_compare) == NULL)
          /* Something went wrong while inserting the new module.  */
          free (new_module);
@@ -267,7 +281,7 @@ static void
 insert_module (const void *nodep, VISIT value, int level)
 {
   if (value == preorder || value == leaf)
-    __gconv_modules_db[__gconv_nmodules++] = (struct gconv_module *) nodep;
+    __gconv_modules_db[__gconv_nmodules++] = *(struct gconv_module **) nodep;
 }
 
 static void
@@ -302,8 +316,6 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
        break;
 
       rp = line;
-      while (isspace (*rp))
-       ++rp;
       /* Terminate the line (excluding comments or newline) by an NUL byte
         to simplify the following code.  */
       endp = strchr (rp, '#');
@@ -316,6 +328,9 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
            *endp = '\0';
        }
 
+      while (isspace (*rp))
+       ++rp;
+
       /* If this is an empty line go on with the next one.  */
       if (rp == endp)
        continue;
@@ -325,10 +340,10 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
        ++rp;
 
       if (rp - word == sizeof ("alias") - 1
-         && memcpy (word, "alias", sizeof ("alias") - 1) == 0)
+         && memcmp (word, "alias", sizeof ("alias") - 1) == 0)
        add_alias (rp);
       else if (rp - word == sizeof ("module") - 1
-              && memcpy (word, "module", sizeof ("module") - 1) == 0)
+              && memcmp (word, "module", sizeof ("module") - 1) == 0)
        add_module (rp, directory, dir_len, modules, nmodules);
       /* else */
        /* Otherwise ignore the line.  */
@@ -349,6 +364,7 @@ __gconv_read_conf (void)
   char *gconv_path, *elem;
   void *modules = NULL;
   size_t nmodules = 0;
+  int save_errno = errno;
 
   if (user_path == NULL)
     /* No user-defined path.  Make a modifiable copy of the default path.  */
@@ -390,31 +406,31 @@ __gconv_read_conf (void)
 
   /* If the configuration files do not contain any valid module specification
      remember this by setting the pointer to the module array to NULL.  */
-  nmodules = sizeof (builtin_modules) / sizeof (struct gconv_module);
+  nmodules += sizeof (builtin_modules) / sizeof (builtin_modules[0]);
   if (nmodules == 0)
+    __gconv_modules_db = NULL;
+  else
     {
-      __gconv_modules_db = NULL;
-      return;
-    }
+      __gconv_modules_db =
+       (struct gconv_module **) malloc (nmodules
+                                        * sizeof (struct gconv_module));
+      if (__gconv_modules_db != NULL)
+       {
+         size_t cnt;
 
-  __gconv_modules_db =
-    (struct gconv_module **) malloc (nmodules * sizeof (struct gconv_module));
-  if (__gconv_modules_db == NULL)
-    /* We cannot do anything.  */
-    return;
+         /* Insert all module entries into the array.  */
+         __twalk (modules, insert_module);
 
-  /* First insert the builtin transformations.  */
-  while (__gconv_nmodules < (sizeof (builtin_modules)
-                            / sizeof (struct gconv_module)))
-    {
-      __gconv_modules_db[__gconv_nmodules] =
-       &builtin_modules[__gconv_nmodules];
-      ++__gconv_nmodules;
-    }
+         /* No remove the tree data structure.  */
+         __tdestroy (modules, nothing);
 
-  /* Insert all module entries into the array.  */
-  __twalk (modules, insert_module);
+         /* Finally insert the builtin transformations.  */
+         for (cnt = 0; cnt < (sizeof (builtin_modules)
+                              / sizeof (struct gconv_module)); ++cnt)
+           __gconv_modules_db[__gconv_nmodules++] = &builtin_modules[cnt];
+       }
+    }
 
-  /* No remove the tree data structure.  */
-  __tdestroy (modules, nothing);
+  /* Restore the error number.  */
+  __set_errno (save_errno);
 }
index ceb94be..b1320ac 100644 (file)
@@ -99,7 +99,7 @@ derivation_lookup (const char *fromset, const char *toset,
   struct known_derivation key = { fromset, toset, NULL, 0 };
   struct known_derivation *result;
 
-  result = __tfind (&key, known_derivations, derivation_compare);
+  result = __tfind (&key, &known_derivations, derivation_compare);
 
   if (result == NULL)
     return GCONV_NOCONV;
@@ -169,11 +169,18 @@ gen_steps (struct derivation_step *best, const char *toset,
                                         * step_cnt);
   if (result != NULL)
     {
+      int failed = 0;
+
+      *nsteps = step_cnt;
       current = best;
       while (step_cnt-- > 0)
        {
-         result[step_cnt].from_name = current->last->result_set;
-         result[step_cnt].to_name = current->result_set;
+         result[step_cnt].from_name = (step_cnt == 0
+                                       ? __strdup (fromset)
+                                       : current->last->result_set);
+         result[step_cnt].to_name = (step_cnt + 1 == *nsteps
+                                     ? __strdup (current->result_set)
+                                     : result[step_cnt + 1].from_name);
 
          if (current->code->module_name[0] == '/')
            {
@@ -182,7 +189,10 @@ gen_steps (struct derivation_step *best, const char *toset,
                __gconv_find_shlib (current->code->module_name);
 
              if (shlib_handle == NULL)
-               break;
+               {
+                 failed = 1;
+                 break;
+               }
 
              result[step_cnt].shlib_handle = shlib_handle;
 
@@ -192,6 +202,7 @@ gen_steps (struct derivation_step *best, const char *toset,
                  /* Argh, no conversion function.  There is something
                     wrong here.  */
                  __gconv_release_shlib (result[step_cnt].shlib_handle);
+                 failed = 1;
                  break;
                }
 
@@ -208,18 +219,18 @@ gen_steps (struct derivation_step *best, const char *toset,
          current = current->last;
        }
 
-      if (step_cnt != 0)
+      if (failed != 0)
        {
          /* Something went wrong while initializing the modules.  */
-         while (step_cnt-- > 0)
+         while (++step_cnt < *nsteps)
            __gconv_release_shlib (result[step_cnt].shlib_handle);
          free (result);
+         *nsteps = 0;
          status = GCONV_NOCONV;
        }
       else
        {
          *handle = result;
-         *nsteps = step_cnt;
          status = GCONV_OK;
        }
     }
@@ -231,12 +242,13 @@ gen_steps (struct derivation_step *best, const char *toset,
 /* The main function: find a possible derivation from the `fromset' (either
    the given name or the alias) to the `toset' (again with alias).  */
 static int
+internal_function
 find_derivation (const char *toset, const char *toset_expand,
                 const char *fromset, const char *fromset_expand,
                 struct gconv_step **handle, size_t *nsteps)
 {
   __libc_lock_define_initialized (static, lock)
-  struct derivation_step *current, **lastp, *best = NULL;
+  struct derivation_step *first, *current, **lastp, *best = NULL;
   int best_cost = 0;
   int result;
 
@@ -260,16 +272,17 @@ find_derivation (const char *toset, const char *toset_expand,
      The task is to match the `toset' with any of the available.  */
   if (fromset_expand != NULL)
     {
-      current = NEW_STEP (fromset_expand, NULL, NULL);
-      current->next = NEW_STEP (fromset, NULL, NULL);
-      lastp = &current->next->next;
+      first = NEW_STEP (fromset_expand, NULL, NULL);
+      first->next = NEW_STEP (fromset, NULL, NULL);
+      lastp = &first->next->next;
     }
   else
     {
-      current = NEW_STEP (fromset, NULL, NULL);
-      lastp = &current->next;
+      first = NEW_STEP (fromset, NULL, NULL);
+      lastp = &first->next;
     }
 
+  current = first;
   while (current != NULL)
     {
       /* Now match all the available module specifications against the
@@ -419,13 +432,28 @@ find_derivation (const char *toset, const char *toset_expand,
                }
              else
                {
-                 /* Append at the end.  */
-                 *lastp = NEW_STEP (result_set, __gconv_modules_db[cnt],
-                                    current);
-                 lastp = &(*lastp)->next;
+                 /* Append at the end if there is no entry with this name.  */
+                 struct derivation_step *runp = first;
+
+                 while (runp != NULL)
+                   {
+                     if (__strcasecmp (result_set, runp->result_set) == 0)
+                       break;
+                     runp = runp->next;
+                   }
+
+                 if (runp == NULL)
+                   {
+                     *lastp = NEW_STEP (result_set, __gconv_modules_db[cnt],
+                                        current);
+                     lastp = &(*lastp)->next;
+                   }
                 }
            }
        }
+
+      /* Go on with the next entry.  */
+      current = current->next;
     }
 
   if (best != NULL)
@@ -470,15 +498,15 @@ __gconv_find_transform (const char *toset, const char *fromset,
   if (__gconv_alias_db != NULL)
     {
       struct gconv_alias key;
-      struct gconv_alias *found;
+      struct gconv_alias **found;
 
       key.fromname = fromset;
-      found = __tfind (&key, __gconv_alias_db, __gconv_alias_compare);
-      fromset_expand = found != NULL ? found->toname : NULL;
+      found = __tfind (&key, &__gconv_alias_db, __gconv_alias_compare);
+      fromset_expand = found != NULL ? (*found)->toname : NULL;
 
       key.fromname = toset;
-      found = __tfind (&key, __gconv_alias_db, __gconv_alias_compare);
-      toset_expand = found != NULL ? found->toname : NULL;
+      found = __tfind (&key, &__gconv_alias_db, __gconv_alias_compare);
+      toset_expand = found != NULL ? (*found)->toname : NULL;
     }
 
   result = find_derivation (toset, toset_expand, fromset, fromset_expand,
index a0003a8..a80e5ef 100644 (file)
@@ -84,6 +84,7 @@ do_open (void *a)
 
 
 static int
+internal_function
 dlerror_run (void (*operate) (void *), void *args)
 {
   char *last_errstring = NULL;
@@ -156,7 +157,7 @@ __gconv_find_shlib (const char *name)
      enough to a pointer to our structure to use as a lookup key that
      will be passed to `known_compare' (above).  */
 
-  found = __tfind (&name, loaded, known_compare);
+  found = __tfind (&name, &loaded, known_compare);
   if (found == NULL)
     {
       /* This name was not known before.  */
@@ -208,7 +209,7 @@ static void *release_handle;
 static void
 do_release_shlib (const void *nodep, VISIT value, int level)
 {
-  struct loaded_object *obj = (struct loaded_object *) nodep;
+  struct loaded_object *obj = *(struct loaded_object **) nodep;
 
   if (value != preorder && value != leaf)
     return;
index 0e789df..343cb70 100644 (file)
@@ -69,19 +69,19 @@ __gconv_open (const char *toset, const char *fromset, gconv_t *handle)
                      if (res != GCONV_OK)
                        break;
                    }
-                 else
-                   if (!data[cnt].is_last)
-                     {
-                       data[cnt].outbufsize = GCONV_DEFAULT_BUFSIZE;
-                       data[cnt].outbuf =
-                         (char *) malloc (data[cnt].outbufsize);
-                       if (data[cnt].outbuf == NULL)
-                         {
-                           res = GCONV_NOMEM;
-                           break;
-                         }
-                       data[cnt].outbufavail = 0;
-                     }
+
+                 if (!data[cnt].is_last && data[cnt].outbuf == NULL)
+                   {
+                     data[cnt].outbufsize = GCONV_DEFAULT_BUFSIZE;
+                     data[cnt].outbuf =
+                       (char *) malloc (data[cnt].outbufsize);
+                     if (data[cnt].outbuf == NULL)
+                       {
+                         res = GCONV_NOMEM;
+                         break;
+                       }
+                     data[cnt].outbufavail = 0;
+                   }
                }
            }
        }
index 582c6f5..f769795 100644 (file)
@@ -117,7 +117,7 @@ __gconv_transform_ucs4_utf8 (struct gconv_step *step,
       do
        {
          const char *newinbuf = inbuf;
-         size_t actually = __wcsnrtombs (&data->outbuf[data->outbufavail],
+         size_t actually = __wmemrtombs (&data->outbuf[data->outbufavail],
                                          (const wchar_t **) &newinbuf,
                                          *inlen / sizeof (wchar_t),
                                          data->outbufsize - data->outbufavail,
@@ -206,7 +206,7 @@ __gconv_transform_utf8_ucs4 (struct gconv_step *step,
       do
        {
          const char *newinbuf = inbuf;
-         size_t actually = __mbsnrtowcs ((wchar_t *) &data->outbuf[data->outbufavail],
+         size_t actually = __wmemrtowcs ((wchar_t *) &data->outbuf[data->outbufavail],
                                          &newinbuf, *inlen,
                                          ((data->outbufsize
                                            - data->outbufavail)
index e5b0eb7..8804e85 100644 (file)
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <errno.h>
 #include <iconv.h>
 #include <gconv.h>
 
+#include <assert.h>
+
 
 size_t
 iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf,
@@ -29,10 +32,39 @@ iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf,
 {
   gconv_t gcd = (gconv_t) cd;
   size_t converted;
+  int result;
+
+  result = __gconv (gcd, inbuf, inbytesleft, outbuf, outbytesleft, &converted);
+  switch (result)
+    {
+    case GCONV_ILLEGAL_DESCRIPTOR:
+      __set_errno (EBADF);
+      converted = (size_t) -1L;
+      break;
+
+    case GCONV_ILLEGAL_INPUT:
+      __set_errno (EILSEQ);
+      converted = (size_t) -1L;
+      break;
+
+    case GCONV_FULL_OUTPUT:
+      __set_errno (E2BIG);
+      converted = (size_t) -1L;
+      break;
+
+    case GCONV_INCOMPLETE_INPUT:
+      __set_errno (EINVAL);
+      converted = (size_t) -1L;
+      break;
+
+    case GCONV_EMPTY_INPUT:
+    case GCONV_OK:
+      /* Nothing.  */
+      break;
 
-  if (__gconv (gcd, inbuf, inbytesleft, outbuf, outbytesleft, &converted)
-      != GCONV_OK)
-    return (size_t) -1;
+    default:
+      assert (!"Nothing like this should happen");
+    }
 
   return converted;
 }
index d3123e2..ccd9d5f 100644 (file)
@@ -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 <iconv.h>
 
 #include <gconv.h>
 int
 iconv_close (iconv_t cd)
 {
+  if (cd == (iconv_t *) -1L)
+    {
+      __set_errno (EBADF);
+      return -1;
+    }
+
   return __gconv_close ((gconv_t) cd) ? -1 : 0;
 }
index 30b6c21..bfff00d 100644 (file)
 
 
 static inline void
-strip (char *s)
+strip (char *wp, const char *s)
 {
   int slash_count = 0;
-  char *wp;
-  wp = s;
 
   while (*s != '\0')
     {
@@ -39,7 +37,7 @@ strip (char *s)
        *wp++ = *s;
       else if (*s == '/')
        {
-         if (++slash_count == 2)
+         if (++slash_count == 3)
            break;
          *wp++ = '/';
        }
@@ -67,11 +65,11 @@ iconv_open (const char *tocode, const char *fromcode)
      '_', '-', '/', and '.'.  */
   tocode_len = strlen (tocode);
   tocode_conv = alloca (tocode_len + 3);
-  strip (memcpy (tocode_conv, tocode, tocode_len + 1));
+  strip (tocode_conv, tocode);
 
   fromcode_len = strlen (fromcode);
   fromcode_conv = alloca (fromcode_len + 3);
-  strip (memcpy (fromcode_conv, fromcode, fromcode_len + 1));
+  strip (fromcode_conv, fromcode);
 
   res = __gconv_open (tocode_conv[2] == '\0' ? tocode : tocode_conv,
                      fromcode_conv[2] == '\0' ? fromcode : fromcode_conv,