summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschwarze <>2020-05-27 22:25:09 +0000
committerschwarze <>2020-05-27 22:25:09 +0000
commit0ea23439e30b2add8b59fc2da3d3c74cd8f6da2a (patch)
treefb04fce091273d4e597a7c4887754743b011dccd
parente17abbddd79622502d5988b8d2041d8c3cceee27 (diff)
downloadopenbsd-0ea23439e30b2add8b59fc2da3d3c74cd8f6da2a.tar.gz
openbsd-0ea23439e30b2add8b59fc2da3d3c74cd8f6da2a.tar.bz2
openbsd-0ea23439e30b2add8b59fc2da3d3c74cd8f6da2a.zip
This patch fixes one bug and one instance of undesirable behaviour.
The bug, present since 4.4BSD, was that a trailing dash in an option group, when the dash is not permitted as an option letter, resulted in the whole option group being returned as an argument, even though the previous option in the group was already parsed as an option: OPTS=abc ./getopt-test -a- -c arg ===>> OPT(a)ARG(-a-)ARG(-c)ARG(arg). Instead, treat the dash as an invalid option and continue parsing options: ===>> OPT(a)ERR(?-)OPT(c)ARG(arg). The undesirable behaviour was that allowing the dash as an option letter only allowed isolated dashes ("-") and trailing dashes in groups ("-a-"), but neither middle dashes in groups ("-a-b"), even though that already partially worked in 4.4BSD, nor leading dashes in groups ("--a"), even though that works on all other BSDs and on glibc. Also, while POSIX does not require that the dash can be used as an option letter at all, arguably, it encourages that letters either be fully supported or not supported at all. It is dubious whether supporting an option letter in some positions but not in others can be considered conforming. This patch makes OpenBSD behaviour identical to FreeBSD and NetBSD, improves compatibility with glibc (except that glibc does not support isolated "-"), improves compatibility with DragonFly (except that DragonFly is buggy when the dash option letter can take an optional argument but that argument is not present), improves compatibility with Illumos and Solaris 11 (except those do not support "-" and mishandle "--a"), and restores 4.4BSD behaviour for "-a-b". In no respect i'm aware of is compatibility with any other systems reduced. For the full rationale, see my mail to tech@ on 30 Mar 2020 14:26:41 +0200. Part of the problem was originally reported by an anonymous coward on tech@ on 12 Mar 2020 03:40:24 +0200, additional analysis was contributed by martijn@, and then the OP sent the final version of the patch i'm now committing on 17 Mar 2020 19:17:56 +0200. No licensing problem here because after the commit, the file does not contain a single word written by the OP. Also, the OP told me in private mail that he intends to publish the patch under the ISC license already contained in the file and that he wishes to be known by the pseudonym "0xef967c36". OK martijn@, and no objection when shown on tech@, but commit delayed to stay clear of the release.
-rw-r--r--src/lib/libc/stdlib/getopt_long.c10
1 files changed, 1 insertions, 9 deletions
diff --git a/src/lib/libc/stdlib/getopt_long.c b/src/lib/libc/stdlib/getopt_long.c
index 48c26601ae..0de50457c2 100644
--- a/src/lib/libc/stdlib/getopt_long.c
+++ b/src/lib/libc/stdlib/getopt_long.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: getopt_long.c,v 1.31 2020/03/30 12:52:58 martijn Exp $ */ 1/* $OpenBSD: getopt_long.c,v 1.32 2020/05/27 22:25:09 schwarze Exp $ */
2/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ 2/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
3 3
4/* 4/*
@@ -418,15 +418,7 @@ start:
418 } 418 }
419 419
420 if ((optchar = (int)*place++) == (int)':' || 420 if ((optchar = (int)*place++) == (int)':' ||
421 (optchar == (int)'-' && *place != '\0') ||
422 (oli = strchr(options, optchar)) == NULL) { 421 (oli = strchr(options, optchar)) == NULL) {
423 /*
424 * If the user specified "-" and '-' isn't listed in
425 * options, return -1 (non-option) as per POSIX.
426 * Otherwise, it is an unknown option character (or ':').
427 */
428 if (optchar == (int)'-' && *place == '\0')
429 return (-1);
430 if (!*place) 422 if (!*place)
431 ++optind; 423 ++optind;
432 if (PRINT_ERROR) 424 if (PRINT_ERROR)