Suspecting bug in /bin/sh's IFS

Jilles Tjoelker jilles at stack.nl
Sat Mar 21 15:04:01 PDT 2009


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


More information about the freebsd-standards mailing list