From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/12765 Path: news.gmane.org!.POSTED!not-for-mail From: Rich Felker Newsgroups: gmane.linux.lib.musl.general Subject: Re: getopt_long_only bug Date: Thu, 26 Apr 2018 10:50:37 -0400 Message-ID: <20180426145037.GG3094@brightrain.aerifal.cx> References: <20180426104630.GR4418@port70.net> Reply-To: musl@lists.openwall.com NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="at6+YcpfzWZg/htY" X-Trace: blaine.gmane.org 1524754128 31120 195.159.176.226 (26 Apr 2018 14:48:48 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Thu, 26 Apr 2018 14:48:48 +0000 (UTC) User-Agent: Mutt/1.5.21 (2010-09-15) To: musl@lists.openwall.com Original-X-From: musl-return-12781-gllmg-musl=m.gmane.org@lists.openwall.com Thu Apr 26 16:48:44 2018 Return-path: Envelope-to: gllmg-musl@m.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by blaine.gmane.org with smtp (Exim 4.84_2) (envelope-from ) id 1fBiCR-0007xj-7u for gllmg-musl@m.gmane.org; Thu, 26 Apr 2018 16:48:43 +0200 Original-Received: (qmail 12100 invoked by uid 550); 26 Apr 2018 14:50:51 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Original-Received: (qmail 12065 invoked from network); 26 Apr 2018 14:50:50 -0000 Content-Disposition: inline In-Reply-To: <20180426104630.GR4418@port70.net> Original-Sender: Rich Felker Xref: news.gmane.org gmane.linux.lib.musl.general:12765 Archived-At: --at6+YcpfzWZg/htY Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Thu, Apr 26, 2018 at 12:46:31PM +0200, Szabolcs Nagy wrote: > i got the following bug report: > > $ cat a.c > #include > #include > > int main() > { > struct option lo[] = > { > {"emit-relocs", no_argument, NULL, 'q'}, > {"qmagic", no_argument, NULL, 'Q'}, > { 0 } > }; > > int li = -1; > char* a[] = { "", "-q", NULL }; > int c = getopt_long_only(2, a, "q", lo, &li); > > printf("c=%c/%i\n", c, c); > > return 0; > } > $ ./a.musl > c=Q/81 > $ ./a.glibc > c=q/113 OK, this is a weird corner case. Apparently when in longonly mode, short options need to be counted in addition to long ones for determining if a partial match is unique. The attached patch should solve the problem. Any review/comments would be helpful. It uses an ugly inline strstr of sorts, because to use strstr we'd need to copy to a temp buffer, and we wouldn't even benefit since the string being searched is so short (usually 1 byte, at most 4). The only reason it's there at all is because we committed to supporting multibyte option chars in getopt.c so getopt_long_only needs to handle them consistently. Rich --at6+YcpfzWZg/htY Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="glo.diff" diff --git a/src/misc/getopt_long.c b/src/misc/getopt_long.c index 008b747..ddcef94 100644 --- a/src/misc/getopt_long.c +++ b/src/misc/getopt_long.c @@ -1,5 +1,7 @@ #define _GNU_SOURCE #include +#include +#include #include #include #include @@ -58,10 +60,10 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring { int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':'; int i, cnt, match; - char *arg, *opt; + char *arg, *opt, *start = argv[optind]+1; for (cnt=i=0; longopts[i].name; i++) { const char *name = longopts[i].name; - opt = argv[optind]+1; + opt = start; if (*opt == '-') opt++; while (*opt && *opt != '=' && *opt == *name) name++, opt++; @@ -74,6 +76,17 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring } cnt++; } + if (cnt==1 && longonly && arg-start == mblen(start, MB_LEN_MAX)) { + int l = arg-start; + for (i=0; optstring[i]; i++) { + int j; + for (j=0; j