shashank created CAMEL-25151:
--------------------------------

             Summary: camel-bindy - a java.util.Date field rejects a valid 
value that is longer than its pattern (M/d/yyyy with 12/25/2026, h:mm a, MMMM), 
so Bindy cannot read back dates it has written
                 Key: CAMEL-25151
                 URL: https://issues.apache.org/jira/browse/CAMEL-25151
             Project: Camel
          Issue Type: Bug
          Components: camel-bindy
            Reporter: shashank


{{DateFormatFactory.DatePatternFormat.parse}} (used for every 
{{java.util.Date}} field of a CSV, fixed-length or key-value pair model) 
refuses a value that has more characters than the pattern:

{code:java}
if (string.length() <= this.pattern.length()) {
    df.setLenient(false);
    return df.parse(string);
} else {
    throw new FormatException("Date provided does not fit the pattern defined");
}
{code}

A pattern letter count is a minimum width, not a maximum: {{M}}, {{d}}, {{H}} 
and {{h}} print two digits for values of 10 and more, {{MMMM}} and {{EEEE}} 
print full names, {{a}} prints {{AM}}/{{PM}} for one letter. So valid dates in 
the pattern's own format are rejected:

||pattern||value||result||
|{{M/d/yyyy}}|{{12/25/2026}}|FormatException (10 characters for an 8 character 
pattern)|
|{{d.M.yyyy}}|{{25.12.2026}}|FormatException|
|{{MMMM d yyyy}}|{{September 30 2026}}|FormatException|
|{{h:mm a}}|{{11:45 PM}}, also {{9:05 AM}}|FormatException for every value|
|{{dd-MM-yyyy}}|{{25-12-2026}}|ok (the width is fixed)|

This also breaks the round trip: marshal writes {{12/25/2026}} for the pattern 
{{M/d/yyyy}}, and unmarshal of that text fails with "Date provided does not fit 
the pattern defined". For {{M/d/yyyy}} about four dates out of five fail (every 
day from the 10th and every date in October to December).

The check was added to reject a date followed by other characters, such as 
{{20090901-10:32:30}} for {{yyyyMMdd}}, because {{DateFormat.parse(String)}} 
stops at the end of the pattern and ignores the rest. CAMEL-11620 removed the 
same check from the {{LocalDate}}, {{LocalDateTime}} and {{LocalTime}} 
factories, but not from the {{java.util.Date}} one.

h3. Reproduction

{code:java}
@CsvRecord(separator = ";")
public static class Row {
    @DataField(pos = 1, pattern = "M/d/yyyy")
    private Date us;
}
// unmarshal of "12/25/2026" -> IllegalArgumentException: Date provided does 
not fit the pattern defined, position: 1, line: 1
// marshal of 2026-11-30 gives "11/30/2026", and unmarshal of that text fails 
the same way
{code}

A unit test with the four patterns above fails on main. A small formal model 
(Lean 4) of the check shows that it accepts the output of {{format}} exactly 
when every numeric field has no more digits than its pattern letters, and that 
the fix below accepts every formatted date and still rejects a date followed by 
other characters.

h3. Affected versions

The check is the same in 2.25.0, 3.0.0, 4.0.0, 4.14.0, 4.18.0, 4.22.0 and main.

h3. Proposed fix

Keep the check for what it was meant to catch: when the value is longer than 
the pattern, parse it with a {{ParsePosition}} and accept it only when the 
whole value was used; otherwise throw the same {{FormatException}} as before:

{code:java}
} else {
    df.setLenient(false);
    ParsePosition position = new ParsePosition(0);
    date = df.parse(string, position);
    if (date == null || position.getIndex() != string.length()) {
        throw new FormatException("Date provided does not fit the pattern 
defined");
    }
    return date;
}
{code}

A value that is not longer than the pattern takes exactly the same path as 
today, so nothing that is accepted today changes. (Requiring the whole value to 
be used for every value would be stricter than today: for example 
{{2026-09-30T10:11:12Z}} with the pattern {{yyyy-MM-dd'T'HH:mm:ss}}, 20 
characters for a 21 character pattern because of the quotes, is accepted today 
with the {{Z}} ignored, and would be rejected.) A date followed by other 
characters is still rejected with the same {{FormatException}} and message (the 
existing tests {{BindySimpleCsvUnmarshallTest.testMessageWithErroneousDate}} 
and {{BindySimpleCsvUnmarshallPositionModifiedTest}} pass unchanged).

Duplicate check (2026-09-30): JIRA "bindy" with "date" and "pattern", "does not 
fit the pattern", "java.util.Date": only CAMEL-11620 (java.time, fixed) and 
older unrelated issues. No open pull request touches the Bindy date factories.

_Filed with Claude Code on behalf of allthingssecurity._




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

Reply via email to