[git commit] shell: add OPTARG poisoning to getopt_optarg.tests

Denys Vlasenko vda.linux at googlemail.com
Fri Aug 11 00:37:48 UTC 2017


commit: https://git.busybox.net/busybox/commit/?id=9a7d0a01918df5a963b6c90177b321ff743282b2
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

ash fails this!

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 shell/ash_test/ash-getopts/getopt_optarg.tests   |  2 ++
 shell/hush.c                                     | 19 ++++++++++++++-----
 shell/hush_test/hush-getopts/getopt_optarg.tests |  2 ++
 3 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/shell/ash_test/ash-getopts/getopt_optarg.tests b/shell/ash_test/ash-getopts/getopt_optarg.tests
index b346284..33682e8 100755
--- a/shell/ash_test/ash-getopts/getopt_optarg.tests
+++ b/shell/ash_test/ash-getopts/getopt_optarg.tests
@@ -4,6 +4,7 @@ var=QWERTY
 OPTARG=ASDFGH
 while getopts "w:et" var; do
 	echo "var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
+	OPTARG=ASDFGH
 done
 echo "exited: var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
 
@@ -12,5 +13,6 @@ echo "*** OPTIND=0, optstring:'w:et' args:$*"
 OPTIND=0
 while getopts "w:et" var; do
 	echo "var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
+	OPTARG=ASDFGH
 done
 echo "exited: var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
diff --git a/shell/hush.c b/shell/hush.c
index f9a8de4..dc05f24 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -9872,7 +9872,8 @@ static int FAST_FUNC builtin_shift(char **argv)
 #if ENABLE_HUSH_GETOPTS
 static int FAST_FUNC builtin_getopts(char **argv)
 {
-/*
+/* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getopts.html
+
 TODO:
 If an invalid option is seen, getopts places ? into VAR and, if
 not silent, prints an error message and unsets OPTARG. If
@@ -9886,6 +9887,8 @@ colon (:) is placed in VAR and OPTARG is set to the option
 character found.
 
 Test that VAR is a valid variable name?
+
+"Whenever the shell is invoked, OPTIND shall be initialized to 1"
 */
 	char cbuf[2];
 	const char *cp, *optstring, *var;
@@ -9920,14 +9923,20 @@ Test that VAR is a valid variable name?
 		exitcode = EXIT_FAILURE;
 		c = '?';
 	}
-	if (optarg)
-		set_local_var_from_halves("OPTARG", optarg);
-	else
-		unset_local_var("OPTARG");
 	cbuf[0] = c;
 	cbuf[1] = '\0';
 	set_local_var_from_halves(var, cbuf);
 	set_local_var_from_halves("OPTIND", utoa(optind));
+
+	/* Always set or unset, never left as-is, even on exit/error:
+	 * "If no option was found, or if the option that was found
+	 * does not have an option-argument, OPTARG shall be unset."
+	 */
+	if (optarg)
+		set_local_var_from_halves("OPTARG", optarg);
+	else
+		unset_local_var("OPTARG");
+
 	return exitcode;
 }
 #endif
diff --git a/shell/hush_test/hush-getopts/getopt_optarg.tests b/shell/hush_test/hush-getopts/getopt_optarg.tests
index b346284..33682e8 100755
--- a/shell/hush_test/hush-getopts/getopt_optarg.tests
+++ b/shell/hush_test/hush-getopts/getopt_optarg.tests
@@ -4,6 +4,7 @@ var=QWERTY
 OPTARG=ASDFGH
 while getopts "w:et" var; do
 	echo "var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
+	OPTARG=ASDFGH
 done
 echo "exited: var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
 
@@ -12,5 +13,6 @@ echo "*** OPTIND=0, optstring:'w:et' args:$*"
 OPTIND=0
 while getopts "w:et" var; do
 	echo "var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
+	OPTARG=ASDFGH
 done
 echo "exited: var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"


More information about the busybox-cvs mailing list