allthingssecurity opened a new pull request, #27105: URL: https://github.com/apache/camel/pull/27105
# Description [CAMEL-25150](https://issues.apache.org/jira/browse/CAMEL-25150) Regression of CAMEL-22068 (4.8.8, 4.10.5, 4.12.0). With `@CsvRecord(quoting = true, quotingEscaped = true)` Bindy writes a quote inside a field as a backslash and the quote (CAMEL-7519), so the value `He said "hi"` is written `"He said \"hi\""`. Unmarshal does not read that field back when the value ends with an odd number of quotes: ``` line: "123","He said \"hi\"","10" expected: firstField=123, secondField=He said "hi", number=10 actual: firstField=123, secondField=He said "hi"",10, number=null ``` The separator and the next column end up in the value and the following fields are shifted or empty, so a typed column (number, date) that follows gets `null` or fails. The same happens for `12"`, `"` and `a "b" "c"`. CAMEL-22068 added a loop to `BindyCsvDataFormat.unquoteTokens` for RFC 4180 doubled quotes: for a token that ends with the quote character, it counts the quotes in front of the final one (skipping backslashes), and an odd count means the final quote is part of the value. That is the right rule for RFC 4180 (`""` is one quote), but it also runs with `quotingEscaped = true`, where the value's quote is written `\"`. For `...\""` the loop counts one quote, decides the closing quote is escaped, and keeps the field open until a later token ends with a quote. Before CAMEL-22068 (4.8.7, 4.10.4) a token ending with the quote always closed the field, and these values were read correctly. This change applies the doubled-quote rule only when `quotingEscaped` is false (a new `BindyCsvFactory.isQuotingEscaped()` passes the flag in). This matches `BindyCsvFactory`, which already turns `""` into `"` only without `quotingEscaped` and `\"` into `"` only with it. Compatibility: - RFC 4180 input (`quotingEscaped = false`, the default) takes exactly the same path as today, including the CAMEL-22068 cases in `BindySimpleCsvFunctionWithExternalMethodTest`. - With `quotingEscaped = true`, the closing rule is the one of 4.8.7 and 4.10.4. A field whose value ends with an even number of quotes, or with no quote, is read as today. The one case that changes is RFC 4180 style input in this mode with a separator inside the quotes and an odd number of quotes in front of the separator (`"x"",y"`): today it is kept as one field (still with the doubled quote, since this mode does not unescape `""`), with the change it is split, as in 4.8.7 and 4.10.4. Such input is not what `quotingEscaped` describes, and today `"x"""` in the same mode shifts the columns instead. - The single quote as quote character is not affected (the loop only ran for `"`). - An escaped quote directly in front of the separator (`a",b` written `"a\",b"`) is still split; that already failed before CAMEL-22068 and needs the backslash itself to be escaped on marshal, which would change the output, so it is not part of this fix. Tests: - New `BindyCsvQuotingEscapedTrailingQuoteTest`: unmarshal of the line above; marshal/unmarshal round trip of `He said "hi"`, `12"`, `"` and `a "b" "c"`; a control round trip of values that work today (`""foo""`, `C:\temp\`, `a\`, `say "hi" now`). - Without the change: 2 of the 3 tests fail (`expected: <He said "hi"> but was: <He said "hi"",10>`), the control passes. - With the change, the whole camel-bindy module: 231 tests, 0 failures, 0 errors, 3 skipped. Found with a Lean 4 model of `unquoteTokens` (with `quotingEscaped` a value ending with `n` quotes is closed exactly when `n` is even), then reproduced with the real classes on main, and compared with the 4.10.0 `unquoteTokens`, which reads these values correctly. # Target - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch) # Tracking - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for the change (usually before you start working on it). # Apache Camel coding standards and style - [x] I checked that each commit in the pull request has a meaningful subject line and body. - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes. (I built and tested the affected module, including the formatter and import-sort plugins. I did not run the full root build.) # AI-assisted contributions - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used. This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer. _Claude Code on behalf of allthingssecurity_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
