ArgumentList bug when using containsOption

I came across what seems to be potentially a bug while using the ArgumentList class’ method containsOption.

More specifically, I was looking for an option using the pipe:

ArgumentList al("", commandLine);
auto containsMyOption = al.containsOption("--list-interfaces|-l");

When I passed a different argument (and one argument only) like this:

myapp --input=/path/to/a/file.dat

the result of containsMyOption was false, which was expected.

When I passed the short version of the argument like this

myapp -i=/path/to/a/file.dat

The value of containsMyOption was true.

What I noticed was that this is happening when comparing the argument (i.e. the second version), with the option passed in the containsOption function.

Namely, when the comparison is made between argument and option (containsOption(StringRef option) calls indexOfOption(StringRef option) which in turn iterates through the arguments and uses the == operator to compare:

bool ArgumentList::Argument::operator== (StringRef wildcard) const
    for (auto& o : StringArray::fromTokens (wildcard, "|", {}))
        if (text == o)
            return true;

        if (isShortOptionFormat (o) && o.length() == 2 && isShortOption ((char) o[1]))
            return true;

        if (isLongOptionFormat (o) && isLongOption (o))
            return true;

    return false;

In the second type of argument mentioned above, the second if of the operator== function, will return true. The first two operands of the && chain correctly return true. The third one:


also returns true although it shouldn’t since this is the comparison between the actual argument and the given option to compare.

The latter function doesn’t validate that indeed the option used in the argument was the one provided in the top function (containsOption). Instead, it checks if the short option is generally included in the argument (after its dash has been stripped, because o[1] is used as an input argument):

bool ArgumentList::Argument::isShortOption ( char option) const
jassert (option != '-'); // this is probably not what you intended to pass in

return isShortOption() && text.containsChar (option);

isShortOption tests if the argument is using a short option (which correctly returns true for the second type of command-line argument), while text.containsChar(option) also correctly returns true because -i=/path/to/file.dat contains the l character. Nevertheless it should just be checking the second character and compare it to see if it’s the same option.