barty/D4J-Repair huggingface dataset:
File: src/java/org/apache/commons/cli/HelpFormatter.java
Issue: infinite loop in the wrapping code of HelpFormatter
If there is not enough space to display a word on a single line, HelpFormatter goes into a infinite loops until the JVM crashes with an OutOfMemoryError.
Test case:

Options options = new Options();
options.addOption("h", "help", false, "This is a looooong description");

HelpFormatter formatter = new HelpFormatter();
formatter.setWidth(20);
formatter.printHelp("app", options); // hang & crash

An helpful exception indicating the insufficient width would be more appropriate than an OutOfMemoryError.

Buggy code:
protected StringBuffer renderWrappedText(StringBuffer sb, int width, 
                                         int nextLineTabStop, String text)
{
    int pos = findWrapPos(text, width, 0);

    if (pos == -1)
    {
        sb.append(rtrim(text));

        return sb;
    }
    sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);

    if (nextLineTabStop >= width)
    {
        // stops infinite loop happening
        throw new IllegalStateException("Total width is less than the width of the argument and indent " + 
                                        "- no room for the description");
    }

    // all following lines must be padded with nextLineTabStop space 
    // characters
    final String padding = createPadding(nextLineTabStop);

    while (true)
    {
        text = padding + text.substring(pos).trim();
        pos = findWrapPos(text, width, 0);

        if (pos == -1)
        {
            sb.append(text);

            return sb;
        }
        
        if ( (text.length() > width) && (pos == nextLineTabStop - 1) ) 
        {
            pos = width;
        }

        sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);
    }
}

Fixed code:
protected StringBuffer renderWrappedText(StringBuffer sb, int width, 
                                         int nextLineTabStop, String text)
{
    int pos = findWrapPos(text, width, 0);

    if (pos == -1)
    {
        sb.append(rtrim(text));

        return sb;
    }
    sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);

    if (nextLineTabStop >= width)
    {
        // stops infinite loop happening
        nextLineTabStop = width - 1;
    }

    // all following lines must be padded with nextLineTabStop space 
    // characters
    final String padding = createPadding(nextLineTabStop);

    while (true)
    {
        text = padding + text.substring(pos).trim();
        pos = findWrapPos(text, width, 0);

        if (pos == -1)
        {
            sb.append(text);

            return sb;
        }
        
        if ( (text.length() > width) && (pos == nextLineTabStop - 1) ) 
        {
            pos = width;
        }

        sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);
    }
}
File: src/java/org/apache/commons/cli/HelpFormatter.java
Issue: infinite loop in the wrapping code of HelpFormatter
If there is not enough space to display a word on a single line, HelpFormatter goes into a infinite loops until the JVM crashes with an OutOfMemoryError.
Test case:

Options options = new Options();
options.addOption("h", "help", false, "This is a looooong description");

HelpFormatter formatter = new HelpFormatter();
formatter.setWidth(20);
formatter.printHelp("app", options); // hang & crash

An helpful exception indicating the insufficient width would be more appropriate than an OutOfMemoryError.

Buggy code:
protected StringBuffer renderWrappedText(StringBuffer sb, int width, 
                                         int nextLineTabStop, String text)
{
    int pos = findWrapPos(text, width, 0);

    if (pos == -1)
    {
        sb.append(rtrim(text));

        return sb;
    }
    sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);

    if (nextLineTabStop >= width)
    {
        // stops infinite loop happening
        nextLineTabStop = width - 1;
    }

    // all following lines must be padded with nextLineTabStop space 
    // characters
    final String padding = createPadding(nextLineTabStop);

    while (true)
    {
        text = padding + text.substring(pos).trim();
        pos = findWrapPos(text, width, 0);

        if (pos == -1)
        {
            sb.append(text);

            return sb;
        }
        
        if ( (text.length() > width) && (pos == nextLineTabStop - 1) ) 
        {
            pos = width;
        }

        sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);
    }
}

Fixed code:
protected StringBuffer renderWrappedText(StringBuffer sb, int width, 
                                         int nextLineTabStop, String text)
{
    int pos = findWrapPos(text, width, 0);

    if (pos == -1)
    {
        sb.append(rtrim(text));

        return sb;
    }
    sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);

    if (nextLineTabStop >= width)
    {
        // stops infinite loop happening
        nextLineTabStop = 1;
    }

    // all following lines must be padded with nextLineTabStop space 
    // characters
    final String padding = createPadding(nextLineTabStop);

    while (true)
    {
        text = padding + text.substring(pos).trim();
        pos = findWrapPos(text, width, 0);

        if (pos == -1)
        {
            sb.append(text);

            return sb;
        }
        
        if ( (text.length() > width) && (pos == nextLineTabStop - 1) ) 
        {
            pos = width;
        }

        sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);
    }
}
File: src/java/org/apache/commons/cli/OptionBuilder.java
Issue: OptionBuilder is not reseted in case of an IAE at create
If the call to OptionBuilder.create() fails with an IllegalArgumentException, the OptionBuilder is not resetted and its next usage may contain unwanted settings. Actually this let the CLI-1.2 RCs fail on IBM JDK 6 running on Maven 2.0.10.

Buggy code:
public static Option create(String opt) throws IllegalArgumentException
{
        // create the option
    Option option = new Option(opt, description);

        // set the option properties
        option.setLongOpt(longopt);
        option.setRequired(required);
        option.setOptionalArg(optionalArg);
        option.setArgs(numberOfArgs);
        option.setType(type);
        option.setValueSeparator(valuesep);
        option.setArgName(argName);
        // reset the OptionBuilder properties
        OptionBuilder.reset();

    // return the Option instance
    return option;
}

Fixed code:
public static Option create(String opt) throws IllegalArgumentException
{
    Option option = null;
    try {
        // create the option
        option = new Option(opt, description);

        // set the option properties
        option.setLongOpt(longopt);
        option.setRequired(required);
        option.setOptionalArg(optionalArg);
        option.setArgs(numberOfArgs);
        option.setType(type);
        option.setValueSeparator(valuesep);
        option.setArgName(argName);
    } finally {
        // reset the OptionBuilder properties
        OptionBuilder.reset();
    }

    // return the Option instance
    return option;
}
File: src/java/org/apache/commons/cli/OptionGroup.java
Issue: Unable to select a pure long option in a group
OptionGroup doesn't play nice with options with a long name and no short name. If the selected option hasn't a short name, group.setSelected(option) has no effect.

Buggy code:
public void setSelected(Option option) throws AlreadySelectedException
{
    if (option == null)
    {
        // reset the option previously selected
        selected = null;
        return;
    }
    
    // if no option has already been selected or the 
    // same option is being reselected then set the
    // selected member variable
    if (selected == null || selected.equals(option.getOpt()))
    {
        selected = option.getOpt();
    }
    else
    {
        throw new AlreadySelectedException(this, option);
    }
}

Fixed code:
public void setSelected(Option option) throws AlreadySelectedException
{
    if (option == null)
    {
        // reset the option previously selected
        selected = null;
        return;
    }
    
    // if no option has already been selected or the 
    // same option is being reselected then set the
    // selected member variable
    if (selected == null || selected.equals(option.getKey()))
    {
        selected = option.getKey();
    }
    else
    {
        throw new AlreadySelectedException(this, option);
    }
}
File: src/java/org/apache/commons/cli/Util.java
Issue: Commons CLI incorrectly stripping leading and trailing quotes
org.apache.commons.cli.Parser.processArgs() calls Util.stripLeadingAndTrailingQuotes() for all argument values. IMHO this is incorrect and totally broken.
It is trivial to create a simple test for this. Output:
    $ java -cp target/clitest.jar Clitest --balloo "this is a \"test\""
    Value of argument balloo is 'this is a "test'.
The argument 'balloo' should indeed keep its trailing double quote. It is what the shell gives it, so don't try to do something clever to it.
The offending code was committed here:
http://svn.apache.org/viewvc?view=rev&revision=129874
and has been there for more than 6 years . Why was this committed in the first place?
The fix is trivial, just get rid of Util.stripLeadingAndTrailingQuotes(), and consequently avoid calling it from Parser.processArgs().

Buggy code:
static String stripLeadingAndTrailingQuotes(String str)
{
    if (str.startsWith("\""))
    {
        str = str.substring(1, str.length());
    }
    int length = str.length();
    if (str.endsWith("\""))
    {
        str = str.substring(0, length - 1);
    }
    
    return str;
}

Fixed code:
static String stripLeadingAndTrailingQuotes(String str)
{
    int length = str.length();
    if (length > 1 && str.startsWith("\"") && str.endsWith("\"") && str.substring(1, length - 1).indexOf('"') == -1)
    {
        str = str.substring(1, length - 1);
    }
    
    return str;
}
File: src/main/java/org/apache/commons/cli/HelpFormatter.java
Issue: StringIndexOutOfBoundsException in HelpFormatter.findWrapPos
In the last while loop in HelpFormatter.findWrapPos, it can pass text.length() to text.charAt(int), which throws a StringIndexOutOfBoundsException. The first expression in that while loop condition should use a <, not a <=.
This is on line 908 in r779646:
http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/java/org/apache/commons/cli/HelpFormatter.java?revision=779646&view=markup

Buggy code:
protected int findWrapPos(String text, int width, int startPos)
{
    int pos;
    
    // the line ends before the max wrap pos or a new line char found
    if (((pos = text.indexOf('\n', startPos)) != -1 && pos <= width)
            || ((pos = text.indexOf('\t', startPos)) != -1 && pos <= width))
    {
        return pos + 1;
    }
    else if (startPos + width >= text.length())
    {
        return -1;
    }


    // look for the last whitespace character before startPos+width
    pos = startPos + width;

    char c;

    while ((pos >= startPos) && ((c = text.charAt(pos)) != ' ')
            && (c != '\n') && (c != '\r'))
    {
        --pos;
    }

    // if we found it - just return
    if (pos > startPos)
    {
        return pos;
    }
    
    // if we didn't find one, simply chop at startPos+width
    pos = startPos + width;
    while ((pos <= text.length()) && ((c = text.charAt(pos)) != ' ')
           && (c != '\n') && (c != '\r'))
    {
        ++pos;
    }        
    return pos == text.length() ? -1 : pos;
}

Fixed code:
protected int findWrapPos(String text, int width, int startPos)
{
    int pos;
    
    // the line ends before the max wrap pos or a new line char found
    if (((pos = text.indexOf('\n', startPos)) != -1 && pos <= width)
            || ((pos = text.indexOf('\t', startPos)) != -1 && pos <= width))
    {
        return pos + 1;
    }
    else if (startPos + width >= text.length())
    {
        return -1;
    }


    // look for the last whitespace character before startPos+width
    pos = startPos + width;

    char c;

    while ((pos >= startPos) && ((c = text.charAt(pos)) != ' ')
            && (c != '\n') && (c != '\r'))
    {
        --pos;
    }

    // if we found it - just return
    if (pos > startPos)
    {
        return pos;
    }
    
    // if we didn't find one, simply chop at startPos+width
    pos = startPos + width;
    
    return pos == text.length() ? -1 : pos;
}
File: src/main/java/org/apache/commons/cli/HelpFormatter.java
Issue: HelpFormatter strips leading whitespaces in the footer
I discovered a bug in Commons CLI while using it through Groovy's CliBuilder. See the following issue:

http://jira.codehaus.org/browse/GROOVY-4313?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel

Copied:
The following code:

def cli = new CliBuilder(footer: "line1:\n line2:\n")
cli.usage()

Produces the following output:

line1
line2

Note that there are no whitespaces before "line2". Replacing them with "\t" doesn't solve the problem either.

Buggy code:
public void printWrapped(PrintWriter pw, int width, int nextLineTabStop, String text)
    {
        StringBuffer sb = new StringBuffer(text.length());

        renderWrappedText(sb, width, nextLineTabStop, text);
        pw.println(sb.toString());
    }

Fixed code:
public void printWrapped(PrintWriter pw, int width, int nextLineTabStop, String text)
    {
        StringBuffer sb = new StringBuffer(text.length());

        renderWrappedTextBlock(sb, width, nextLineTabStop, text);
        pw.println(sb.toString());
    }
File: src/main/java/org/apache/commons/cli/Options.java
Issue: LongOpt falsely detected as ambiguous
Options options = new Options();
options.addOption(Option.builder().longOpt("importToOpen").hasArg().argName("FILE").build());
options.addOption(Option.builder("i").longOpt("import").hasArg().argName("FILE").build());
Parsing "--import=FILE" is not possible since 1.3 as it throws a AmbiguousOptionException stating that it cannot decide whether import is import or importToOpen. In 1.2 this is not an issue. 
The root lies in the new DefaultParser which does a startsWith check internally.

Buggy code:
public List<String> getMatchingOptions(String opt)
{
    opt = Util.stripLeadingHyphens(opt);
    
    List<String> matchingOpts = new ArrayList<String>();

    // for a perfect match return the single option only

    for (String longOpt : longOpts.keySet())
    {
        if (longOpt.startsWith(opt))
        {
            matchingOpts.add(longOpt);
        }
    }
    
    return matchingOpts;
}

Fixed code:
public List<String> getMatchingOptions(String opt)
{
    opt = Util.stripLeadingHyphens(opt);
    
    List<String> matchingOpts = new ArrayList<String>();

    // for a perfect match return the single option only
    if(longOpts.keySet().contains(opt)) {
        return Collections.singletonList(opt);
    }

    for (String longOpt : longOpts.keySet())
    {
        if (longOpt.startsWith(opt))
        {
            matchingOpts.add(longOpt);
        }
    }
    
    return matchingOpts;
}
File: src/main/java/org/apache/commons/cli/DefaultParser.java
Issue: Optional argument picking up next regular option as its argument
I'm not sure if this is a complete fix.  It seems to miss the case where short options are concatenated after an option that takes an optional argument.

A failing test case for this would be to modify {{setUp()}} in BugCLI265Test.java to include short options "a" and "b":

{code:java}
    @Before
    public void setUp() throws Exception {
        parser = new DefaultParser();

        Option TYPE1 = Option.builder("t1").hasArg().numberOfArgs(1).optionalArg(true).argName("t1_path").build();
        Option OPTION_A = Option.builder("a").hasArg(false).build();
        Option OPTION_B = Option.builder("b").hasArg(false).build();
        Option LAST = Option.builder("last").hasArg(false).build();

        options = new Options().addOption(TYPE1).addOption(OPTION_A).addOption(OPTION_B).addOption(LAST);
    }
{code}

Add add a test for the concatenated options following an option with optional argument case:

{code:java}
    @Test
    public void shouldParseConcatenatedShortOptions() throws Exception {
      String[] concatenatedShortOptions = new String[] { "-t1", "-ab" };

      final CommandLine commandLine = parser.parse(options, concatenatedShortOptions);

      assertTrue(commandLine.hasOption("t1"));
      assertEquals(null, commandLine.getOptionValue("t1"));
      assertTrue(commandLine.hasOption("a"));
      assertTrue(commandLine.hasOption("b"));
      assertFalse(commandLine.hasOption("last"));
    }
{code}

One possible fix is to check that at least the first character of the option is a short option if all the other cases fail in {{isShortOption(...)}} like so:

{code:java}
    private boolean isShortOption(String token)
    {
        // short options (-S, -SV, -S=V, -SV1=V2, -S1S2)
        if (!token.startsWith("-") || token.length() == 1)
        {
            return false;
        }

        // remove leading "-" and "=value"
        int pos = token.indexOf("=");
        String optName = pos == -1 ? token.substring(1) : token.substring(1, pos);
        if (options.hasShortOption(optName))
        {
            return true;
        }
        return optName.length() > 0 && options.hasShortOption(String.valueOf(optName.charAt(0)));
    }
{code}

Buggy code:
private boolean isShortOption(String token)
{
    // short options (-S, -SV, -S=V, -SV1=V2, -S1S2)
    return token.startsWith("-") && token.length() >= 2 && options.hasShortOption(token.substring(1, 2));

    // remove leading "-" and "=value"
}

Fixed code:
private boolean isShortOption(String token)
{
    // short options (-S, -SV, -S=V, -SV1=V2, -S1S2)
    if (!token.startsWith("-") || token.length() == 1)
    {
        return false;
    }

    // remove leading "-" and "=value"
    int pos = token.indexOf("=");
    String optName = pos == -1 ? token.substring(1) : token.substring(1, pos);
    return options.hasShortOption(optName);
}
File: src/main/java/org/apache/commons/cli/DefaultParser.java
Issue: Optional argument picking up next regular option as its argument
I have recently migrated a project from CLI 1.2 to 1.3.1 and have encountered what may be a bug or difference in the way optional arguments are being processed.

I have a command that opens several different kinds of databases by type, or alternately, the last opened database of that type.

Option TYPE1 = Option.builder("t1").hasArg().numberOfArgs(1).optionalArg(true).argName("t1_path").build();
Option TYPE2 = Option.builder("t2").hasArg().numberOfArgs(1).optionalArg(true).argName("t2_path").build();
Option LAST  =  Option.builder("last").hasArg(false).build();

Commands then look like "open -t1 path/to/my/db" or "open -t1 -last"

If I use the now deprecated GnuParser, both commands work as expected.  However, if I use the new DefaultParser, for the 2nd example, it thinks "-last" is the argument for -t1 rather than an option in its own right.

I added the numberOfArgs(1) after reading a post on StackOverflow, but it made no difference in the behavior.  Only switching back to the GnuParser seemed to work.

Buggy code:
private boolean isShortOption(String token)
{
    // short options (-S, -SV, -S=V, -SV1=V2, -S1S2)
    if (!token.startsWith("-") || token.length() == 1)
    {
        return false;
    }

    // remove leading "-" and "=value"
    int pos = token.indexOf("=");
    String optName = pos == -1 ? token.substring(1) : token.substring(1, pos);
    return options.hasShortOption(optName);
    // check for several concatenated short options
}

Fixed code:
private boolean isShortOption(String token)
{
    // short options (-S, -SV, -S=V, -SV1=V2, -S1S2)
    if (!token.startsWith("-") || token.length() == 1)
    {
        return false;
    }

    // remove leading "-" and "=value"
    int pos = token.indexOf("=");
    String optName = pos == -1 ? token.substring(1) : token.substring(1, pos);
    if (options.hasShortOption(optName))
    {
        return true;
    }
    // check for several concatenated short options
    return optName.length() > 0 && options.hasShortOption(String.valueOf(optName.charAt(0)));
}
File: src/main/java/org/apache/commons/cli/TypeHandler.java
Issue: Option parser type EXISTING_FILE_VALUE not check file existing
When the user pass option type FileInputStream.class, I think the expected behavior for the return value is the same type, which the user passed.

Options options = new Options();
options.addOption(Option.builder("f").hasArg().type(FileInputStream.class).build());
CommandLine cline = new DefaultParser().parse(options, args);
FileInputStream file = (FileInputStream) cline.getParsedOptionValue("f"); // it returns "File" object, without check File exist.


I attach a solution for it:
https://github.com/schaumb/commons-cli/commit/abfcc8211f529ab75f3b3edd4a827e484109eb0b



Buggy code:
public static Object createValue(final String str, final Class<?> clazz) throws ParseException
    {
        if (PatternOptionBuilder.STRING_VALUE == clazz)
        {
            return str;
        }
        else if (PatternOptionBuilder.OBJECT_VALUE == clazz)
        {
            return createObject(str);
        }
        else if (PatternOptionBuilder.NUMBER_VALUE == clazz)
        {
            return createNumber(str);
        }
        else if (PatternOptionBuilder.DATE_VALUE == clazz)
        {
            return createDate(str);
        }
        else if (PatternOptionBuilder.CLASS_VALUE == clazz)
        {
            return createClass(str);
        }
        else if (PatternOptionBuilder.FILE_VALUE == clazz)
        {
            return createFile(str);
        }
        else if (PatternOptionBuilder.EXISTING_FILE_VALUE == clazz)
        {
            return createFile(str);
        }
        else if (PatternOptionBuilder.FILES_VALUE == clazz)
        {
            return createFiles(str);
        }
        else if (PatternOptionBuilder.URL_VALUE == clazz)
        {
            return createURL(str);
        }
        else
        {
            return null;
        }
    }

Fixed code:
public static Object createValue(final String str, final Class<?> clazz) throws ParseException
    {
        if (PatternOptionBuilder.STRING_VALUE == clazz)
        {
            return str;
        }
        else if (PatternOptionBuilder.OBJECT_VALUE == clazz)
        {
            return createObject(str);
        }
        else if (PatternOptionBuilder.NUMBER_VALUE == clazz)
        {
            return createNumber(str);
        }
        else if (PatternOptionBuilder.DATE_VALUE == clazz)
        {
            return createDate(str);
        }
        else if (PatternOptionBuilder.CLASS_VALUE == clazz)
        {
            return createClass(str);
        }
        else if (PatternOptionBuilder.FILE_VALUE == clazz)
        {
            return createFile(str);
        }
        else if (PatternOptionBuilder.EXISTING_FILE_VALUE == clazz)
        {
            return openFile(str);
        }
        else if (PatternOptionBuilder.FILES_VALUE == clazz)
        {
            return createFiles(str);
        }
        else if (PatternOptionBuilder.URL_VALUE == clazz)
        {
            return createURL(str);
        }
        else
        {
            return null;
        }
    }