From dd2e61b4a4e0f5605588a9d7249ea5d9bd70287a Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 7 Apr 2009 21:15:40 -0700 Subject: [PATCH] Make create_iconv() properly distinguish converters by name. The code in create_iconv() assumed that every pair of different converters had a different hash value. This is a bad assumption: eventually, we will be unlucky, and two different converters will hash to the same value, and we will get a bad conversion. So we have to compare (and store) the names of the codes that each converters converts to and from. Also, compute the hash value without making an extra copy of fromcode and tocode. --- src/libpspp/i18n.c | 63 +++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/src/libpspp/i18n.c b/src/libpspp/i18n.c index a4e9b63f..74ec1f1f 100644 --- a/src/libpspp/i18n.c +++ b/src/libpspp/i18n.c @@ -39,6 +39,13 @@ #include #endif +struct converter + { + const char *tocode; + const char *fromcode; + iconv_t conv; + }; + static char *default_encoding; static struct hmapx map; @@ -46,42 +53,34 @@ static struct hmapx map; static iconv_t create_iconv (const char* tocode, const char* fromcode) { - iconv_t conv; + size_t hash; struct hmapx_node *node; - size_t hash ; - char *key = alloca (strlen (tocode) + strlen (fromcode) + 2); - - strcpy (key, tocode); - strcat (key, "\n"); /* hopefully no encoding names contain '\n' */ - strcat (key, fromcode); - - hash = hsh_hash_string (key); - - node = hmapx_first_with_hash (&map, hash); - - if (!node) - { - conv = iconv_open (tocode, fromcode); - - /* I don't think it's safe to translate this string or to use messaging - as the convertors have not yet been set up */ - if ( (iconv_t) -1 == conv && 0 != strcmp (tocode, fromcode)) - { - const int err = errno; - fprintf (stderr, - "Warning: " - "cannot create a convertor for \"%s\" to \"%s\": %s\n", - fromcode, tocode, strerror (err)); - } - - hmapx_insert (&map, conv, hash); - } - else + struct converter *converter; + + hash = hsh_hash_string (tocode) ^ hsh_hash_string (fromcode); + HMAPX_FOR_EACH_WITH_HASH (converter, node, hash, &map) + if (!strcmp (tocode, converter->tocode) + && !strcmp (fromcode, converter->fromcode)) + return converter->conv; + + converter = xmalloc (sizeof *converter); + converter->tocode = xstrdup (tocode); + converter->fromcode = xstrdup (fromcode); + converter->conv = iconv_open (tocode, fromcode); + hmapx_insert (&map, converter, hash); + + /* I don't think it's safe to translate this string or to use messaging + as the convertors have not yet been set up */ + if ( (iconv_t) -1 == converter->conv && 0 != strcmp (tocode, fromcode)) { - conv = hmapx_node_data (node); + const int err = errno; + fprintf (stderr, + "Warning: " + "cannot create a convertor for \"%s\" to \"%s\": %s\n", + fromcode, tocode, strerror (err)); } - return conv; + return converter->conv; } /* Return a string based on TEXT converted according to HOW. -- 2.30.2