Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 Oct 2010 17:07:27 GMT
From:      Mark Johnston <markjdb@gmail.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   bin/151720: sh(1): parser accepts invalid syntax without reporting an error
Message-ID:  <201010251707.o9PH7Rsu045893@www.freebsd.org>
Resent-Message-ID: <201010251710.o9PHAAkB069624@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         151720
>Category:       bin
>Synopsis:       sh(1): parser accepts invalid syntax without reporting an error
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Oct 25 17:10:09 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Mark Johnston
>Release:        8.1-RELEASE
>Organization:
>Environment:
FreeBSD mark-laptop-bsd.mark-home 8.1-RELEASE FreeBSD 8.1-RELEASE #2: Tue Oct 19 21:08:25 EDT 2010     root@mark-laptop-bsd.mark-home:/usr/obj/usr/src/sys/GENERIC_BCM  i386
>Description:
One can use sh(1)'s '${#var}' syntax to get the length of the string referenced by var, or 0 if var is unset. However, in this case sh(1) doesn't verify that var is a valid variable name. For instance:

$ foo=bar
$ echo ${#foo}
3
$ echo ${#foo^^&$}
3
$ echo ${#foo?&$#$^%$#^%#$%^$#%}
3
$

and so on. bash and zsh correctly reject the last two expressions with a 'bad substitution' error as one would expect.
>How-To-Repeat:
Run sh(1) and try the above examples.
>Fix:
I've submitted a patch which fixes the parser. I've also attached a regression test to go into tools/regression/bin/sh/errors. With the patch, I get:

$ foo=bar
$ echo ${#foo}
3
$ echo ${#foo^^&$}
${foo...}: Bad substitution
$ echo ${#foo?&$#$^%$#^%#$%^$#%}
${foo...}: Bad substitution
$

Note that valid expressions such as '${#?}', '${#-}' and '${##}' are still handled properly with this patch.

Patch attached with submission follows:

diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index c51ab48..40249f5 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -1283,6 +1283,8 @@ parsesub: {
 				}
 			}
 		} else if (subtype != VSERROR) {
+			if (subtype == VSLENGTH && c != '}')
+				subtype = VSERROR;
 			pungetc();
 		}
 		STPUTC('=', out);
diff --git a/tools/regression/bin/sh/errors/bad-parm-exp6.2 b/tools/regression/bin/sh/errors/bad-parm-exp6.2
new file mode 100644
index 0000000..6d4b5c2
--- /dev/null
+++ b/tools/regression/bin/sh/errors/bad-parm-exp6.2
@@ -0,0 +1 @@
+${#foo^}
diff --git a/tools/regression/bin/sh/errors/bad-parm-exp6.2.stderr b/tools/regression/bin/sh/errors/bad-parm-exp6.2.stderr
new file mode 100644
index 0000000..dbf14b5
--- /dev/null
+++ b/tools/regression/bin/sh/errors/bad-parm-exp6.2.stderr
@@ -0,0 +1 @@
+./errors/bad-parm-exp6.2: ${foo...}: Bad substitution


>Release-Note:
>Audit-Trail:
>Unformatted:



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