aboutsummaryrefslogtreecommitdiff
path: root/iconv/iconvconfig.c
diff options
context:
space:
mode:
authorSiddhesh Poyarekar <siddhesh@sourceware.org>2021-06-28 09:15:55 +0530
committerSiddhesh Poyarekar <siddhesh@sourceware.org>2021-06-28 09:15:55 +0530
commit9429049c178b3af3d6afeb3717ff1f2214dc9572 (patch)
tree5326e9e4118c65d9511ae55b3a7c2e20bf854ef9 /iconv/iconvconfig.c
parent5adda61f62b77384718b4c0d8336ade8f2b4b35c (diff)
downloadglibc-9429049c178b3af3d6afeb3717ff1f2214dc9572.tar
glibc-9429049c178b3af3d6afeb3717ff1f2214dc9572.tar.gz
glibc-9429049c178b3af3d6afeb3717ff1f2214dc9572.tar.bz2
glibc-9429049c178b3af3d6afeb3717ff1f2214dc9572.zip
iconvconfig: Fix multiple issues
It was noticed on big-endian systems that msgfmt would fail with the following error: msgfmt: gconv_builtin.c:70: __gconv_get_builtin_trans: Assertion `cnt < sizeof (map) / sizeof (map[0])' failed. Aborted (core dumped) This is only seen on installed systems because it was due to a corrupted gconv-modules.cache. iconvconfig had the following issues (it was specifically freeing fulldir that caused this issue, but other cleanups are also needed) that this patch fixes. - Add prefix only if dir starts with '/' - Use asprintf instead of mempcpy so that the directory string is NULL terminated - Make a copy of the directory reference in new_module so that fulldir can be freed within the same scope in handle_dir. Reviewed-by: Florian Weimer <fweimer@redhat.com>
Diffstat (limited to 'iconv/iconvconfig.c')
-rw-r--r--iconv/iconvconfig.c24
1 files changed, 9 insertions, 15 deletions
diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
index e69334d71c..783b2bbdbb 100644
--- a/iconv/iconvconfig.c
+++ b/iconv/iconvconfig.c
@@ -250,6 +250,7 @@ static const char gconv_module_ext[] = MODULE_EXT;
#include <programs/xmalloc.h>
+#include <programs/xasprintf.h>
/* C string table handling. */
@@ -519,11 +520,12 @@ module_compare (const void *p1, const void *p2)
/* Create new module record. */
static void
new_module (const char *fromname, size_t fromlen, const char *toname,
- size_t tolen, const char *directory,
+ size_t tolen, const char *dir_in,
const char *filename, size_t filelen, int cost, size_t need_ext)
{
struct module *new_module;
- size_t dirlen = strlen (directory) + 1;
+ size_t dirlen = strlen (dir_in) + 1;
+ const char *directory = xstrdup (dir_in);
char *tmp;
void **inserted;
@@ -654,20 +656,10 @@ handle_dir (const char *dir)
size_t dirlen = strlen (dir);
bool found = false;
- /* Add the prefix before sending it off to the parser. */
- char *fulldir = xmalloc (prefix_len + dirlen + 2);
- char *cp = mempcpy (mempcpy (fulldir, prefix, prefix_len), dir, dirlen);
+ char *fulldir = xasprintf ("%s%s%s", dir[0] == '/' ? prefix : "",
+ dir, dir[dirlen - 1] != '/' ? "/" : "");
- if (dir[dirlen - 1] != '/')
- {
- *cp++ = '/';
- *cp = '\0';
- dirlen++;
- }
-
- found = gconv_parseconfdir (fulldir, dirlen + prefix_len);
-
- free (fulldir);
+ found = gconv_parseconfdir (fulldir, strlen (fulldir));
if (!found)
{
@@ -679,6 +671,8 @@ handle_dir (const char *dir)
"configuration files with names ending in .conf.");
}
+ free (fulldir);
+
return found ? 0 : 1;
}