[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