aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-08-11 02:37:48 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-08-11 02:37:48 +0200
commit9a7d0a01918df5a963b6c90177b321ff743282b2 (patch)
tree3378d6ce2ad70e7bc34423bd59ca49e5e9aa1304 /shell
parent81f962f3df0d7194b7a52c6f83259727759094c4 (diff)
downloadbusybox-9a7d0a01918df5a963b6c90177b321ff743282b2.tar.gz
shell: add OPTARG poisoning to getopt_optarg.tests
ash fails this! Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rwxr-xr-xshell/ash_test/ash-getopts/getopt_optarg.tests2
-rw-r--r--shell/hush.c19
-rwxr-xr-xshell/hush_test/hush-getopts/getopt_optarg.tests2
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 b346284f0..33682e868 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 f9a8de423..dc05f24b9 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 b346284f0..33682e868 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'"