BUG: getopt does not permute argv correctly

Eric Blake eblake@redhat.com
Fri May 25 14:22:00 GMT 2018


On 05/25/2018 09:01 AM, Thomas Kindler wrote:
> Hi!
> 
> I'm using cygwin64 with newlib 3.0.0. POSIXLY_CORRECT is not set.

Note that Cygwin provides its own getopt() implementation, rather than 
relying on newlib.  So you may be reporting to the wrong list.

> $ ./test 1 2 3 -a -b -c
> 
> Newlib v3.0.0
> POSIXLY_CORRECT=0x0
> before:
>    0: "./test"
>    1: "1"
>    2: "2"
>    3: "3"
>    4: "-a"
>    5: "-b"
>    6: "-c"
> after:
>    0: "./test"
>    1: "1"
>    2: "2"
>    3: "3"
>    4: "-a"
>    5: "-b"
>    6: "-c"
> a=0, b=0, c=0

That behavior is POSIX compliant.  Just because POSIXLY_CORRECT is not 
set does not mean that you can expect non-POSIX behavior.

> 
> ===> Failure!
> 
> I would expect that argv is permuted, so that -a -b -c come first. Also, I
> expect a=1, b=1, c=1.

Your expectations do not match with POSIX. But they do match with Linux 
behavior.  Here's where cygwin does that:

winsup/cygwin/libc/getopt.c:
int
getopt(int nargc, char * const *nargv, const char *options)
{

         /*
          * We don't pass FLAG_PERMUTE to getopt_internal() since
          * the BSD getopt(3) (unlike GNU) has never done this.
          *
          * Furthermore, since many privileged programs call getopt()
          * before dropping privileges it makes sense to keep things
          * as simple (and bug-free) as possible.
          */
         return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));

You may have a point that Cygwin should be patched to more closely match 
Linux.  Or you could use getopt_long() which permutes by default unless 
POSIXLY_CORRECT is set.  But for now, your observation matches the 
Cygwin code, and is independent of newlib.

> I also tried this program on an embedded ARM Cortex-M4 target, using the
> GNU Arm Embedded Toolchain and newlib v2.5.0:
> 
> 
> Here, I see another, different behaviour:
> 
>> test 1 2 3 -a -b -c
> Newlib v2.5.0
> POSIXLY_CORRECT=0x0
> before:
>    0: "test"
>    1: "1"
>    2: "2"
>    3: "3"
>    4: "-a"
>    5: "-b"
>    6: "-c"
> after:
>    0: "test"
>    1: "-a"
>    2: "-b"
>    3: "-c"
>    4: "1"
>    5: "2"
>    6: "3"
> a=1, b=1, c=1
> 
> ===> (somewhat surprisingly) OK!

That's because newlib's getopt() is different from Cygwin's, and DOES 
permute by default.  (Maybe Cygwin should be patched to just use 
newlib's version, rather than duplicating things?)

> 
> 
>> test 1 2 3 -abc
> Newlib v2.5.0
> POSIXLY_CORRECT=0x0
> before:
>    0: "test"
>    1: "1"
>    2: "2"
>    3: "3"
>    4: "-abc"
> after:
>    0: "test"
>    1: "1"
>    2: "2"
>    3: "3"
>    4: "-abc"
> a=1, b=1, c=1
> 
> 
> ===> Failure! a, b, c is parsed, but does not get permuted to argv[1].

Ouch - that looks like a bug in newlib.  Patches are welcome!

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org



More information about the Newlib mailing list