NetBSD Problem Report #17248

Received: (qmail 16432 invoked by uid 605); 13 Jun 2002 17:08:27 -0000
Message-Id: <200206131708.g5DH83E12485@snowdrop.l8s.co.uk>
Date: Thu, 13 Jun 2002 18:08:03 +0100 (BST)
From: david@l8s.co.uk
Sender: gnats-bugs-owner@netbsd.org
Reply-To: david@l8s.co.uk
To: gnats-bugs@gnats.netbsd.org
Subject: getopt(3) doesn't error an unexpected '-' option
X-Send-Pr-Version: 3.95

>Number:         17248
>Category:       lib
>Synopsis:       getopt(3) doesn't error "ls -l-"
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    lib-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jun 13 17:09:00 +0000 2002
>Closed-Date:    Tue Feb 04 09:03:34 +0000 2003
>Last-Modified:  Tue Feb 04 09:03:34 +0000 2003
>Originator:     David Laight
>Release:        NetBSD 1.5ZC
>Organization:
	dis
>Environment:
System: NetBSD snowdrop 1.5ZC NetBSD 1.5ZC (GENERIC) #10: Thu May 16 12:50:04 BST 2002 dsl@snowdrop:/oldroot/usr/bsd-current/src/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:
	getopt(3) returns -1 if it finds an unexpected '-' option.
	This causes the program to use that entire option string
	as an argument.
>How-To-Repeat:
	Pass a '-' option to a program that doesn't expect it.

	$ : >-l-
	$ ls -l-
	-rw-r--r--  1 dsl  wheel  0 Jun 13 11:21 -l-

	This ought to generate the usage message from ls (because '-'
	if one of the few options it doesn't have).
	However you get the output of 'ls -l -- -l-'

>Fix:
	Apply either of the following patches.
	The first just fixes the above problem, the second also reduces
	the chances that a program will get incorrect answers after
	resetting optind and/or argv.
	I've also applied a cosmetic change to the code that
	determines optarg in order to made it more readable.

Index: getopt.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/stdlib/getopt.c,v
retrieving revision 1.21
diff -u -r1.21 getopt.c
--- getopt.c	2001/04/24 09:07:43	1.21
+++ getopt.c	2002/06/13 16:42:52
@@ -83,12 +83,14 @@

 	if (optreset || !*place) {		/* update scanning pointer */
 		optreset = 0;
-		if (optind >= nargc || *(place = nargv[optind]) != '-') {
+		/* for SYSV compatibility treat '-' as not an option */
+		if (optind >= nargc || *(place = nargv[optind]) != '-' ||
+		    !place[1] ) {
 			place = EMSG;
 			return (-1);
 		}
-		if (place[1] && *++place == '-'	/* found "--" */
-		    && place[1] == '\0') {
+		/* "--" => end of options */
+		if (*++place == '-' && place[1] == '\0') {
 			++optind;
 			place = EMSG;
 			return (-1);
@@ -96,12 +98,6 @@
 	}					/* option letter okay? */
 	if ((optopt = (int)*place++) == (int)':' ||
 	    !(oli = strchr(ostr, optopt))) {
-		/*
-		 * if the user didn't specify '-' as an option,
-		 * assume it means -1.
-		 */
-		if (optopt == (int)'-')
-			return (-1);
 		if (!*place)
 			++optind;
 		if (opterr && *ostr != ':')

Index: getopt.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/stdlib/getopt.c,v
retrieving revision 1.21
diff -u -r1.21 getopt.c
--- getopt.c	2001/04/24 09:07:43	1.21
+++ getopt.c	2002/06/13 16:44:22
@@ -61,8 +61,8 @@
 	optreset;		/* reset getopt */
 char	*optarg;		/* argument associated with option */

-#define	BADCH	(int)'?'
-#define	BADARG	(int)':'
+#define	BADCH	'?'
+#define	BADARG	':'
 #define	EMSG	""

 /*
@@ -75,33 +75,43 @@
 	char * const nargv[];
 	const char *ostr;
 {
 	static char *place = EMSG;		/* option letter processing */
+	static char old_optind = 1;
+	static char * const *old_argv = 0;
 	char *oli;				/* option letter list index */

 	_DIAGASSERT(nargv != NULL);
 	_DIAGASSERT(ostr != NULL);

+	/* If this isn't a continuation of the last call
+	   ensure we don't continue parsing an old option string. */
+	if (old_optind != optind || nargv != old_argv)
+	    place = EMSG;
+
 	if (optreset || !*place) {		/* update scanning pointer */
 		optreset = 0;
-		if (optind >= nargc || *(place = nargv[optind]) != '-') {
+		/* for SYSV compatibility treat '-' as not an option */
+		if (optind >= nargc || *(place = nargv[optind]) != '-' ||
+		    !place[1] ) {
 			place = EMSG;
 			return (-1);
 		}
-		if (place[1] && *++place == '-'	/* found "--" */
-		    && place[1] == '\0') {
+		/* "--" => end of options */
+		if (*++place == '-' && place[1] == '\0') {
 			++optind;
 			place = EMSG;
 			return (-1);
 		}
-	}					/* option letter okay? */
-	if ((optopt = (int)*place++) == (int)':' ||
-	    !(oli = strchr(ostr, optopt))) {
-		/*
-		 * if the user didn't specify '-' as an option,
-		 * assume it means -1.
-		 */
-		if (optopt == (int)'-')
-			return (-1);
+	}
+
+	/* Save these to detect (most) cases when the user resets
+	   optind in order to process a different set of arguments
+	   (basically makes us kill the saved 'place' next time around). */
+	old_optind = optind;
+	old_argv = nargv;
+
+	/* option letter okay? */
+	if ((optopt = *place++) == ':' || !(oli = strchr(ostr, optopt))) {
 		if (!*place)
 			++optind;
 		if (opterr && *ostr != ':')
@@ -118,7 +128,9 @@
 	else {					/* need an argument */
 		if (*place)			/* no white space */
 			optarg = place;
-		else if (nargc <= ++optind) {	/* no arg */
+		else if (nargc > ++optind)	/* white space */
+			optarg = nargv[optind];
+		else {				/* no arg */
 			place = EMSG;
 			if (*ostr == ':')
 				return (BADARG);
@@ -128,8 +140,6 @@
 				    getprogname(), optopt);
 			return (BADCH);
 		}
-	 	else				/* white space */
-			optarg = nargv[optind];
 		place = EMSG;
 		++optind;
 	}
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed 
State-Changed-By: wiz 
State-Changed-When: Thu Jun 13 13:49:11 PDT 2002 
State-Changed-Why:  
Took the first patch -- thanks. 
I didn't find any description for changing optind in POSIX, so I let it 
be as it was. 
State-Changed-From-To: closed->open 
State-Changed-By: wiz 
State-Changed-When: Mon Jun 24 15:00:14 PDT 2002 
State-Changed-Why:  
Undid the changes, since they broke e.g. su, env, tset, ... 
See bin/17274. 
State-Changed-From-To: open->closed 
State-Changed-By: dsl 
State-Changed-When: Tue Feb 4 01:02:00 PST 2003 
State-Changed-Why:  
Fixed by rev 1.25 of src/lib/libc/stdlib/getopt.c 
>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.