Subject: /bin/sh messes up quoting when ${var:+$var} substitution includes quotes
To: NetBSD Userlevel Technical Discussion List <tech-userlevel@NetBSD.ORG>
From: Greg A. Woods <woods@weird.com>
List: tech-userlevel
Date: 06/21/2004 18:34:54
I've encountered a bug in how /bin/sh handles parameter quoting when the
text in a "${FOO:+$BAR}" variable substitution includes quotes in $BAR.

This problem affects both netbsd-1-6 and netbsd-2-0.

I think this is an un-reported bug and that this post should be a PR,
but I wanted to ask first as even though I've been unable to find any
similar PR, I'm not confident that my searching could have been
successful.

I discovered this through a little trick with variable expansion that I
to show the actual quoting on debug output in shell scripts (and to make
the debug output cut & pastable).  I recently had a need to use the
"${VAR:+expansion}" form where the expansion included a variable that
expanded to text including double-quote characters, and I found this
failed with /bin/sh, but worked with /bin/ksh.

Here's a test script.  As-is it'll bail out with what appears to be a
weird sed error when executed with /bin/sh, but it runs silently when
run with /bin/ksh:

	$ sh ~/src/tquote.sh      
	sed: unknown option -- g
	usage:  sed script [-anE] [file ...]
	        sed [-an] [-e script] ... [-f script_file] ... [file ...]

	$ ksh ~/src/tquote.sh 
	$

Change the 'DEBUG=false' to 'DEBUG=true' to see the debug output with quoting.

-------------------- tquotevar.sh --------------------
DEBUG=false

BUILD_FLAGS="CFLAGS=\"-O2 -W\""
BUILD_DEBUG="\"-Werror -g\""

if $DEBUG; then
	DQ="'"	# used to wrap multi-token params
	DEBUG_ECHO="echo"
else
	DQ=""
	DEBUG_ECHO=""
fi

# this is OK with sh and ksh
#
${DEBUG_ECHO} \
sed -e ${DQ}'s/^/to test/'${DQ} \
    -e ${DQ}"s/$/build with:  ${BUILD_FLAGS} but leave ${BUILD_DEBUG} out/"${DQ} < /dev/null

# this is also OK with sh and ksh
#
${DEBUG_ECHO} \
sed -e ${DQ}'s/^/to test/'${DQ} \
    -e ${DQ}"s/$/build with:  ${BUILD_FLAGS} but leave ${BUILD_DEBUG:-${BUILD_DEBUG}} out/"${DQ} < /dev/null

# this one fails with sh but works with ksh
#
${DEBUG_ECHO} \
sed -e ${DQ}'s/^/to really test/'${DQ} \
    -e ${DQ}"s/$/build with:  ${BUILD_FLAGS}${BUILD_DEBUG:+ and ${BUILD_DEBUG}}/"${DQ} < /dev/null
----------------------------------------

-- 
						Greg A. Woods

+1 416 218-0098                  VE3TCP            RoboHack <woods@robohack.ca>
Planix, Inc. <woods@planix.com>          Secrets of the Weird <woods@weird.com>