[PATCH v2] iconv: Fix iconv functions not following symlinks [BZ #32339]
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Tue Aug 5 16:19:28 GMT 2025
On 14/07/25 13:04, Avinal Kumar wrote:
> On some file systems iconv do not follow symlinks. This happens because
> read_conf_file() function's directory traversal loop reject symbolic
> links and then lstat64() call do not follow symlinks.
>
> This commit fixes the directory traversal loop to accept symbolic links
> and then follow the link using stat64().
>
> The test works by creating a temporary directory and placing a symbolic
> link inside it that points to a configuration file. It then runs
> iconvconfig on this directory.
>
> The test passes if iconvconfig successfully follows the symlink and
> generates the cache correctly, confirming that the directory traversal
> logic now properly handles symbolic links.
>
> Signed-off-by: Avinal Kumar <avinal.xlvii@gmail.com>
> Co-authored-by: Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>
LGTM, thanks.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> ---
> It took some time and help to figure out how to cleanly apply the patches,
> there were some whitespace issues and my first time going though a series.
> Thanks Arjun for the help :)
>
> I tested it with and without the patch and I think it is good for now. Thank
> you Adhemerval for the tests.
> ---
> iconv/Makefile | 6 +++++
> iconv/gconv_parseconfdir.h | 8 ++++---
> iconv/tst-iconvconfig.sh | 48 ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 59 insertions(+), 3 deletions(-)
> create mode 100755 iconv/tst-iconvconfig.sh
>
> diff --git a/iconv/Makefile b/iconv/Makefile
> index 9a94a41ba4..3ed30dc89b 100644
> --- a/iconv/Makefile
> +++ b/iconv/Makefile
> @@ -85,6 +85,7 @@ tests-special += \
> $(objpfx)tst-iconv_prog-buffer-tiny.out \
> $(objpfx)tst-iconv_prog-buffer.out \
> $(objpfx)tst-iconv_prog.out \
> + $(objpfx)tst-iconvconfig.out \
This indentation seems off here (space vs tab), I will fix it before
installing it.
> $(objpfx)tst-translit-mchar.out \
> # tests-special
> endif
> @@ -164,3 +165,8 @@ $(objpfx)tst-iconv_prog-buffer-large.out: \
> tst-iconv_prog-buffer.sh $(objpfx)iconv_prog
> $(BASH) $< $(common-objdir) '$(run-program-prefix)' '' '22' > $@; \
> $(evaluate-test)
> +
> +$(objpfx)tst-iconvconfig.out: tst-iconvconfig.sh $(objpfx)iconvconfig
> + $(BASH) $< $(common-objdir) '$(test-wrapper-env)' \
> + '$(run-program-env)' > $@; \
> + $(evaluate-test)
> diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
> index a7ebfd80cc..31f8f1c421 100644
> --- a/iconv/gconv_parseconfdir.h
> +++ b/iconv/gconv_parseconfdir.h
> @@ -33,9 +33,10 @@
> # define closedir __closedir
> # define mempcpy __mempcpy
> # define struct_stat64 struct __stat64_t64
> -# define lstat64 __lstat64_time64
> +# define stat64_impl __stat64_time64
> # define feof_unlocked __feof_unlocked
> #else
> +# define stat64_impl stat64
> # define struct_stat64 struct stat64
> #endif
>
> @@ -151,7 +152,8 @@ gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len)
> struct dirent64 *ent;
> while ((ent = readdir64 (confdir)) != NULL)
> {
> - if (ent->d_type != DT_REG && ent->d_type != DT_UNKNOWN)
> + if (ent->d_type != DT_REG && ent->d_type != DT_UNKNOWN
> + && ent->d_type != DT_LNK)
> continue;
>
> size_t len = strlen (ent->d_name);
> @@ -166,7 +168,7 @@ gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len)
> continue;
>
> if (ent->d_type != DT_UNKNOWN
> - || (lstat64 (conf, &st) != -1 && S_ISREG (st.st_mode)))
> + || (stat64_impl (conf, &st) != -1 && S_ISREG (st.st_mode)))
> found |= read_conf_file (conf, dir, dir_len);
>
> free (conf);
> diff --git a/iconv/tst-iconvconfig.sh b/iconv/tst-iconvconfig.sh
> new file mode 100755
> index 0000000000..0b16b17f0d
> --- /dev/null
> +++ b/iconv/tst-iconvconfig.sh
> @@ -0,0 +1,48 @@
> +#!/bin/bash
> +# Check if iconvconfig correctly handle config links (BZ 32339)
> +# Copyright (C) 2025 Free Software Foundation, Inc.
> +# This file is part of the GNU C Library.
> +
> +# The GNU C Library is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU Lesser General Public
> +# License as published by the Free Software Foundation; either
> +# version 2.1 of the License, or (at your option) any later version.
> +
> +# The GNU C Library is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> +# Lesser General Public License for more details.
> +
> +# You should have received a copy of the GNU Lesser General Public
> +# License along with the GNU C Library; if not, see
> +# <https://www.gnu.org/licenses/>.
> +
> +set -e
> +
> +build_dir=$1
> +test_wrapper_env="$2"
> +run_program_env="$3"
> +
> +# We have to have some directories in the library path.
> +LIBPATH=$build_dir:$build_dir/iconvdata
> +
> +ICONVCONFIG="
> +$build_dir/elf/ld.so --library-path $LIBPATH $build_dir/iconv/iconvconfig
> +"
> +
> +ICONVCONFIG="$test_wrapper_env $run_program_env $ICONVCONFIG"
> +
> +TIMEOUTFACTOR=${TIMEOUTFACTOR:-1}
> +
> +tmpdir=$(mktemp -d $build_dir/iconv/tst-iconvconfig.XXXXXX)
> +#trap 'rm -fr $tmpdir' 0 1 2 3 15 EXIT
> +
> +touch $tmpdir/gconv-modules-extra.conf
> +mkdir $tmpdir/gconv-modules.d
> +cd $tmpdir/gconv-modules.d && ln -s ../gconv-modules-extra.conf . && cd -
> +
> +$ICONVCONFIG --nostdlib $tmpdir -o $tmpdir/gconv-modules.cache
> +
> +[ ! -e $tmpdir/tmpdir/gconv-modules.cache ] || exit 1
> +
> +exit 0
More information about the Libc-alpha
mailing list