Bug 79055

Summary: Add an IFS regression test for shells
Product: Base System Reporter: David Magda <dmagda+fbugs>
Component: standardsAssignee: Graham Perrin <grahamperrin>
Status: Closed Overcome By Events    
Severity: Affects Only Me CC: standards
Priority: --- Keywords: feature
Version: 4.10-STABLE   
Hardware: Any   
OS: Any   
URL: https://web.archive.org/web/20051225040851/http://www.research.att.com/~gsf/public/ifs.sh
See Also: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=79067

Description David Magda 2005-03-20 18:00:10 UTC
Not so much a bug report but simply a way to test that the
IFS code in sh(1) is up to snuff.

Glenn Fowler at AT&T Research has a shell script [1] that tests how
good a shell's IFS code is. The script can be downloaded from [1] but
is also attached to the end of this PR.

[1] http://www.research.att.com/~gsf/public/ifs.sh

Fix: 

On my 4.10 box sh(1) has the following results:
[...]
# tests 6856 passed 1097 failed 5759 ordered 1644

I don't have any other systems to test on. Here's the script:


# Usage: $SHELL ifs.sh
#
# This script generates 6856 tests for the set(1) and read(1)
# builtins w.r.t. IFS whitespace and non-whitespace characters.
# Each failed test produces one line on the standard output that
# contains the test along with the expected and actual results.
# The last output line contains the test result counts.  ordered>0
# are the number of tests where IFS=": " produced different results
# than IFS=" :".  If a test fails the same way for IFS=": " and
# IFS=" :" then the second output line is suppressed.

TESTS=6856

ksh_read=0
echo 1 | read ksh_read
ksh_arith=0
eval '((ksh_arith+=1))' 2>/dev/null

failed=0
ordered=0
passed=0

split()
{
	i=$1 s=$2 r=$3 S='' R=''
	for ifs in ': ' ' :'
	do	IFS=$ifs
		set x $i
		shift
		IFS=' '
		g="[$#]"
		while	:
		do	case $# in
			0)	break ;;
			esac
			g="$g($1)"
			shift
		done
		case $g in
		"$s")	case $ksh_arith in
			1)	((passed+=1)) ;;
			*)	passed=`expr $passed + 1` ;;
			esac
			case $S in
			'')	S=$g
				;;
			"$g")	;;
			*)	case $ksh_arith in
				1)	((ordered+=1)) ;;
				*)	ordered=`expr $ordered + 1` ;;
				esac
				;;
			esac
			;;
		"$S")	case $ksh_arith in
			1)	((failed+=1)) ;;
			*)	failed=`expr $failed + 1` ;;
			esac
			;;
		*)	case $ksh_arith in
			1)	((failed+=1)) ;;
			*)	failed=`expr $failed + 1` ;;
			esac
			case $s in
			"$S")	;;
			?0*)	echo "IFS=\"$ifs\"; x=\"$i\"; set x \$x; shift; echo \"[\$#]\" # expected \"$s\" got \"$g\"" ;;
			?1*)	echo "IFS=\"$ifs\"; x=\"$i\"; set x \$x; shift; echo \"[\$#](\$1)\" # expected \"$s\" got \"$g\"" ;;
			?2*)	echo "IFS=\"$ifs\"; x=\"$i\"; set x \$x; shift; echo \"[\$#](\$1)(\$2)\" # expected \"$s\" got \"$g\"" ;;
			?3*)	echo "IFS=\"$ifs\"; x=\"$i\"; set x \$x; shift; echo \"[\$#](\$1)(\$2)(\$3)\" # expected \"$s\" got \"$g\"" ;;
			*)	echo TEST ERROR i="'$i'" s="'$s'" ;;
			esac
			case $S in
			'')	S=$g
				;;
			"$g")	;;
			*)	case $ksh_arith in
				1)	((ordered+=1)) ;;
				*)	ordered=`expr $ordered + 1` ;;
				esac
				;;
			esac
		esac
		case $ksh_read in
		1)	echo "$i" | IFS=$ifs read x y; g="($x)($y)" ;;
		*)	g=`export ifs; echo "$i" | ( IFS=$ifs; read x y; echo "($x)($y)" )` ;;
		esac
		case $g in
		"$r")	case $ksh_arith in
			1)	((passed+=1)) ;;
			*)	passed=`expr $passed + 1` ;;
			esac
			case $R in
			'')	R=$g
				;;
			"$g")	;;
			*)	case $ksh_arith in
				1)	((ordered+=1)) ;;
				*)	ordered=`expr $ordered + 1` ;;
				esac
				;;
			esac
			;;
		"$R")	case $ksh_arith in
			1)	((failed+=1)) ;;
			*)	failed=`expr $failed + 1` ;;
			esac
			;;
		*)	case $ksh_arith in
			1)	((failed+=1)) ;;
			*)	failed=`expr $failed + 1` ;;
			esac
			case $r in
			"$R")	;;
			*)	echo "echo \"$i\" | ( IFS=\"$ifs\" read x y; echo \"(\$x)(\$y)\" ) # expected \"$r\" got \"$g\"" ;;
			esac
			case $R in
			'')	R=$g
				;;
			"$g")	;;
			*)	case $ksh_arith in
				1)	((ordered+=1)) ;;
				*)	ordered=`expr $ordered + 1` ;;
				esac
				;;
			esac
			;;
		esac
	done
}

for str in 	\
	'-'	\
	'a'	\
	'- -'	\
	'- a'	\
	'a -'	\
	'a b'	\
	'- - -'	\
	'- - a'	\
	'- a -'	\
	'- a b'	\
	'a - -'	\
	'a - b'	\
	'a b -'	\
	'a b c'	\

do
	IFS=' '
	set x $str

	shift
	case $# in
	0)	continue ;;
	esac

	f1=$1
	case $f1 in
	'-')	f1='' ;;
	esac

	shift
	case $# in
	0)	for d0 in '' ' '
		do
			for d1 in '' ' ' ':' ' :' ': ' ' : '
			do
				case $f1$d1 in
				'')	split "$d0$f1$d1" "[0]" "()()" ;;
				' ')	;;
				*)	split "$d0$f1$d1" "[1]($f1)" "($f1)()" ;;
				esac
			done
		done
		continue
		;;
	esac
	f2=$1
	case $f2 in
	'-')	f2='' ;;
	esac

	shift
	case $# in
	0)	for d0 in '' ' '
		do
			for d1 in ' ' ':' ' :' ': ' ' : '
			do
				case ' ' in
				$f1$d1|$d1$f2)	continue ;;
				esac
				for d2 in '' ' ' ':' ' :' ': ' ' : '
				do
					case $f2$d2 in
					'')	split "$d0$f1$d1$f2$d2" "[1]($f1)" "($f1)()" ;;
					' ')	;;
					*)	split "$d0$f1$d1$f2$d2" "[2]($f1)($f2)" "($f1)($f2)" ;;
					esac
				done
			done
		done
		continue
		;;
	esac
	f3=$1
	case $f3 in
	'-')	f3='' ;;
	esac

	shift
	case $# in
	0)	for d0 in '' ' '
		do
			for d1 in ':' ' :' ': ' ' : '
			do
				case ' ' in
				$f1$d1|$d1$f2)	continue ;;
				esac
				for d2 in ' ' ':' ' :' ': ' ' : '
				do
					case $f2$d2 in
					' ')	continue ;;
					esac
					case ' ' in
					$f2$d2|$d2$f3)	continue ;;
					esac
					for d3 in '' ' ' ':' ' :' ': ' ' : '
					do
						case $f3$d3 in
						'')	split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;;
						' ')	;;
						*)	x=$f2$d2$f3$d3
							x=${x#' '}
							x=${x%' '}
							split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)"
							;;
						esac
					done
				done
			done
		done
		continue
		;;
	esac
done
case $ksh_arith in
1)	((tests=passed+failed)) ;;
*)	tests=`expr $passed + $failed` ;;
esac
case $ordered in
0)	ordered="" ;;
*)	ordered=" ordered $ordered" ;;
esac
case $tests in
$TESTS)	fatal="" ;;
*)	fatal=" -- fundamental IFS error -- $TESTS tests expected"
esac
echo "# tests $tests passed $passed failed $failed$ordered$fatal"
How-To-Repeat: 
/bin/sh ifs.sh
Comment 1 Craig Rodrigues freebsd_committer freebsd_triage 2006-05-16 05:39:24 UTC
Responsible Changed
From-To: freebsd-standards->stefanf

Stefan has been doing a lot of work lately writing regression 
tests for /bin/sh.
Comment 2 Jilles Tjoelker freebsd_committer freebsd_triage 2009-04-04 14:39:01 UTC
standards/79067 mentions this test script too but also has patches to
fix the problems

-- 
Jilles Tjoelker
Comment 3 dmagda 2009-04-04 15:50:08 UTC
On Sat, April 4, 2009 09:39, Jilles Tjoelker wrote:
> standards/79067 mentions this test script too but also has patches to
> fix the problems

If you want to marked it a dupe of the other, or close it if the patch
fixes things, that's fine with me.

I filed the bug a while ago, and no longer have a FreeBSD to test things on.
Comment 4 Stefan Farfeleder freebsd_committer freebsd_triage 2015-01-17 08:59:33 UTC
I'm not working on /bin/sh anymore.
Comment 5 Eitan Adler freebsd_committer freebsd_triage 2018-05-28 19:41:40 UTC
batch change:

For bugs that match the following
-  Status Is In progress 
AND
- Untouched since 2018-01-01.
AND
- Affects Base System OR Documentation

DO:

Reset to open status.


Note:
I did a quick pass but if you are getting this email it might be worthwhile to double check to see if this bug ought to be closed.
Comment 6 Graham Perrin freebsd_committer freebsd_triage 2022-10-17 12:37:58 UTC
Keyword: 

    patch
or  patch-ready

– in lieu of summary line prefix: 

    [patch]

* bulk change for the keyword
* summary lines may be edited manually (not in bulk). 

Keyword descriptions and search interface: 

    <https://bugs.freebsd.org/bugzilla/describekeywords.cgi>
Comment 7 Graham Perrin 2023-09-24 05:51:40 UTC
(In reply to David Magda from 2005 comment #0)

> [1] http://www.research.att.com/~gsf/public/ifs.sh

No longer available. Linked: a capture in the Wayback Machine. 


(In reply to Jilles Tjoelker from 2009 comment #2)

> standards/79067 mentions this test script too but also has patches to fix 
> the problems

(In reply to Eitan Adler from 2018 comment #5)

> … I did a quick pass but if you are getting this email it might be 
> worthwhile to double check to see if this bug ought to be closed.

----

^Triage: bug 79067 was fixed in 2009 with <https://github.com/freebsd/freebsd-src/commit/f19a2f6c574ce3dc437d9998a879ad65e8666c5d> so let's close here, as overcome by events. 

If necessary, please reopen or make a new report. Thanks.

f19a2f6c574c Fix some weirdnesses in the NetBSD IFS code, in particular "$@"$ifschar if the final positional parameter is empty. With the NetBSD code, adding the $ifschar removes a parameter.