Bug 28081 - getopt_long doesn't return error on ambiguous option
Summary: getopt_long doesn't return error on ambiguous option
Status: RESOLVED NOTABUG
Alias: None
Product: glibc
Classification: Unclassified
Component: argparse (show other bugs)
Version: 2.33
: P2 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-07-12 15:55 UTC by Miroslav Lichvar
Modified: 2021-07-19 07:48 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Miroslav Lichvar 2021-07-12 15:55:24 UTC
An option which partially matches multiple getopt long options doesn't produce an error.

Reproducer:
#include <stdio.h>
#include <getopt.h>

int main(void) {
	const char *argv[] = {"a", "--f", "b", NULL };
	int index, c;

	static struct option long_options[] = {
		{"foobar", required_argument, 0, 0},
		{"foobaz", required_argument, 0, 0},
		{0, 0, 0, 0}
	};

	c = getopt_long(3, (char **)argv, "", long_options, &index);

	printf("c=%d index=%d\n", c, index);
}

Actual result:
c=0 index=0

Expected result:
option '--f' is ambiguous; possibilities: '--foobar' '--foobaz'
c=63 index=0

More information:
It seems this doesn't happen when the two options are different in the required_argument vs no_argument setting.

Observed on Fedora 34 using glibc-2.33-16.fc34.x86_64.
Comment 1 Andreas Schwab 2021-07-12 16:12:01 UTC
That's not a bug.  The two options are exactly equivalent, so there is no ambiguity.
Comment 2 Miroslav Lichvar 2021-07-12 16:15:33 UTC
They are not equivalent. They have a different index, which is how the application where I came across this issue recognizes them.
Comment 3 Andreas Schwab 2021-07-12 17:56:17 UTC
You need to use a different val.
Comment 4 Miroslav Lichvar 2021-07-13 07:34:28 UTC
Ok, if you don't plan to fix this issue, it would be good to have it described in the getopt_long() man page, or at least fix the example it contains to not use the same val for different options, so new projects are less likely to fall into this trap. I'll see if I can submit a patch for the man pages.
Comment 5 Miroslav Lichvar 2021-07-19 07:48:08 UTC
FWIW, the getopt code checks also for a different flag, not just val and has_arg. A minimal workaround, at least when the struct config is not reallocated, is to point the flag to the val itself, e.g.

opts[i].flag = &opts[i].val;