Ruiqi Dong created CLI-342:
------------------------------

             Summary: Parser fails to throw MissingArgumentException for empty 
required arguments when parsing via Properties
                 Key: CLI-342
                 URL: https://issues.apache.org/jira/browse/CLI-342
             Project: Commons CLI
          Issue Type: Bug
          Components: Parser
    Affects Versions: 1.10.0
            Reporter: Ruiqi Dong
             Fix For: 1.10.0
         Attachments: Parser.java, ParserTest.java

The {{Parser}} class silently ignores invalid/empty argument values when 
parsing options through Properties, while the same scenario correctly throws 
{{MissingArgumentException}} when parsing via command line arguments. This 
inconsistent behavior is caused by a catch block that swallows 
{{RuntimeException}} in the {{processProperties}} method.

 

Description:

When parsing options that require arguments through Properties, if an empty or 
invalid value is provided, the parser does not throw a 
{{MissingArgumentException}} as expected. Instead, the exception is silently 
swallowed due to a catch block in the {{processProperties}} method. This 
creates inconsistent behavior between command-line parsing and Properties-based 
parsing.

 

Steps to Reproduce:

1. Create an Option that requires an argument:

Options options = new Options();
Option option = new Option("f", "file", true, "Input file");
options.addOption(option);

 

2. Parse via Properties with empty value:

Properties properties = new Properties();
properties.setProperty("file", "");
Parser parser = new PosixParser();
CommandLine cmd = parser.parse(options, new String[0], properties);

 

3. No exception is thrown, but the option has no valid value

 

Expected Behavior: The parser should throw a {{MissingArgumentException}} when 
a required argument is missing or empty, consistent with command-line parsing 
behavior.

Actual Behavior: No exception is thrown. The RuntimeException is caught and 
silently ignored in the {{processProperties}} method.

 

Unit Test Case:

@Test
void testEmptyArgumentViaPropertiesShouldThrowException() {
    Options options = new Options();
    Option option = new Option("f", "file", true, "Input file");
    options.addOption(option);
    
    Properties properties = new Properties();
    properties.setProperty("file", "");
    
    Parser parser = new PosixParser();
    
    // This should throw ParseException but doesn't
    assertThrows(ParseException.class, () -> {
        parser.parse(options, new String[0], properties);
    });
}


Root Cause Analysis:


In {{{}Parser.java{}}}, the {{processProperties}} method contains:

if (opt.hasArg()) {
    if (Util.isEmpty(opt.getValues())) {
        try {
            opt.processValue(value);
        } catch (final RuntimeException exp) { // NOPMD
            // if we cannot add the value don't worry about it
        }
    }
}

The catch block silently swallows any {{RuntimeException}} thrown by 
{{{}processValue(){}}}, including cases where the value is invalid or empty. 
When parsing via command line, the {{processArgs}} method correctly handles 
this:

if (opt.getValues() == null && !opt.hasOptionalArg()) {
    throw new MissingArgumentException(opt);
}

 

Suggested Fix:

Remove or modify the exception handling in {{processProperties}} to maintain 
consistency with command-line parsing:

if (opt.hasArg()) {
    if (Util.isEmpty(opt.getValues())) {
        opt.processValue(value);
        // Check if value was successfully set
        if (opt.getValues() == null && !opt.hasOptionalArg()) {
            throw new MissingArgumentException(opt);
        }
    }
}

Alternatively, catch and re-throw as ParseException:

if (opt.hasArg()) {
    if (Util.isEmpty(opt.getValues())) {
        try {
            opt.processValue(value);
        } catch (final RuntimeException exp) {
            throw new ParseException("Invalid value for option: " + option + " 
- " + exp.getMessage());
        }
        // Validate the value was set
        if (opt.getValues() == null && !opt.hasOptionalArg()) {
            throw new MissingArgumentException(opt);
        }
    }
}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to