Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 Mar 2009 22:46:34 +0100
From:      Jilles Tjoelker <jilles@stack.nl>
To:        Oliver Fromme <olli@lurza.secnetix.de>
Cc:        freebsd-standards@FreeBSD.ORG
Subject:   Re: Suspecting bug in /bin/sh's IFS
Message-ID:  <20090321214634.GA36395@stack.nl>
In-Reply-To: <200903191412.n2JECdbl011120@lurza.secnetix.de>
References:  <200903181213.n2ICDPpT042350@lurza.secnetix.de> <200903191412.n2JECdbl011120@lurza.secnetix.de>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, Mar 19, 2009 at 03:12:39PM +0100, Oliver Fromme wrote:
> Further debugging reveals that this is not a generic
> problem with field splitting, but it affects the read
> command only.

> I tried to use "set" instead of "read":

>  ORIG_IFS="$IFS"
>  while read line; do
>          IFS="$IFS="
>          set -- $line
>          IFS="$ORIG_IFS"
>          key="$1"
>          shift
>          val="$*"
>          echo "'$key'  --  '$val'"
>  done < config

> Now i get correct output for both " \t\n=" and "= \t\n"
> as the IFS value.  So the bug is in the "read" builtin.

> The following patch fixes the problem:

> --- bin/sh/miscbltin.c.orig     2006-02-04 15:37:50.000000000 +0100
> +++ bin/sh/miscbltin.c  2009-03-19 15:01:43.000000000 +0100
> @@ -188,7 +188,7 @@
>  		}
>  		if (c == '\n')
>  			break;
> -		if (startword && *ifs == ' ' && strchr(ifs, c)) {
> +		if (startword && strchr(ifs, c)) {
>  			continue;
>  		}
>  		startword = 0;

> The bug seems to exist for at least 15 years; the bogus
> comparison was already present in the initial import in
> the FreeBSD CVS repository in 1994.

> Any opinions on this?

The code is wrong, but your patched code is also wrong. The read builtin
should use the same logic as normal field splitting, with additional
rules if there are more fields in the input than variables.

I have noticed that NetBSD has already fixed this. I have ported these
fixes over: http://www.stack.nl/~jilles/unix/sh-read-split.patch
The patch is against RELENG_7, I hope it applies to -CURRENT as well.

The NetBSD commit message also refers to
http://www.research.att.com/~gsf/public/ifs.sh
Just like their /bin/sh, our /bin/sh with the patch now passes the
'read' tests from there (there are still many other failures though).

By the way, to avoid all processing by read, one must IFS= read -r VAR.
Without the IFS specification, leading and trailing whitespace will
still be stripped.

-- 
Jilles Tjoelker



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090321214634.GA36395>