[ 
https://issues.apache.org/jira/browse/CAMEL-25034?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Claus Ibsen updated CAMEL-25034:
--------------------------------
    Fix Version/s: 4.23.0

> convertBodyTo(type, charset) ignores the charset when the message has a 
> CamelCharsetName header, and leaves it on the exchange when the conversion 
> fails
> --------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25034
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25034
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core
>            Reporter: shashank
>            Priority: Minor
>             Fix For: 4.23.0
>
>
> {{convertBodyTo(String.class, "UTF-8")}} (and {{convertHeaderTo}} / 
> {{convertVariableTo}} with a charset) is the documented way to convert with a 
> given charset. {{ConvertBodyProcessor.process}} 
> ({{ConvertBodyProcessor.java:119-173}}) passes the charset to the type 
> converters by setting the exchange *property* {{CamelCharsetName}}, converts, 
> and then restores the old property:
> {code:java}
> originalCharsetName = exchange.getProperty(ExchangePropertyKey.CHARSET_NAME, 
> String.class);
> // override existing charset with configured charset as that is what the user
> // have explicit configured and expects to be used
> exchange.setProperty(ExchangePropertyKey.CHARSET_NAME, charset);
> value = old.getMandatoryBody(type);                 // :143
> ...
> // remove or restore charset when we are done as we should not propagate that 
>   (:163-171, not in a finally)
> {code}
> Two problems:
> # The converters read the charset with 
> {{ExchangeHelper.getCharsetName/getCharset}} 
> ({{ExchangeHelper.java:958-1001}}), where the {{CamelCharsetName}} *header* 
> "takes precedence" over the property. When the message carries that header 
> (the HL7 data format sets it, {{HL7DataFormat.java:153}}, and user routes set 
> it), the configured charset is silently ignored and the body is decoded with 
> the header's charset.
> # The restore is skipped when the conversion throws. The configured charset 
> then stays on the exchange, and the error handler, {{onException}} and the 
> dead letter channel convert the body with it.
> {{ConvertHeaderProcessor.java:132-160}} and 
> {{ConvertVariableProcessor.java:157-185}} have the same code.
> *Reproduction* (standalone program against main dbdd4b381):
> {noformat}
> from("direct:conv").convertBodyTo(String.class, "UTF-8")
>   body = "café" as UTF-8 bytes, no header                       -> café     
> (correct)
>   body = "café" as UTF-8 bytes, header CamelCharsetName=ISO-8859-1 -> café   
>  expected café
> from("direct:fail").onException(Exception.class).handled(true).setBody(simple("${exchangeProperty.CamelCharsetName}")).end()
>                    .convertBodyTo(Integer.class, "UTF-16")
>   body "abc"                                                       -> UTF-16  
>  expected (empty)
> {noformat}
> Property-based tests (jqwik): with the header, {{convertBodyTo(String.class, 
> "UTF-8")}} of UTF-8 bytes fails for random Latin-1 text (shrunk sample 
> {{à}}); without the header it passes 500 tries; after a failing conversion 
> the property is left behind (shrunk sample {{a}}).
> A Lean model proves the following:
> * Whenever a header with a different charset is present, the configured 
> charset is not used ({{header_always_wins}}), and every failing conversion 
> leaves the configured charset in the property ({{failure_always_leaks}}).
> * Without the header, a successful conversion uses the configured charset and 
> restores the property ({{no_header_ok}}), and without a configured charset 
> nothing changes ({{unconfigured_ok}}), so the fix only changes the two cases 
> above.
> The same property-based code is in camel-2.25.4 and camel-3.0.0 
> ({{ConvertBodyProcessor}}), camel-4.0.0 and camel-4.14.0, and the header 
> precedence in {{ExchangeHelper.getCharsetName}} is the same since 3.0, so all 
> maintained versions are affected. CAMEL-12279 (2.21) added the restore of the 
> original property, but not in a {{finally}} block and not for the header.
> *Proposed fix:* in the three processors:
> * if the message has a {{CamelCharsetName}} header, remember it and remove it 
> (or set it to the configured charset) for the duration of the conversion, the 
> same way as the property;
> * restore the header and the property in a {{finally}} block.
> Alternatively, pass the charset to the conversion directly instead of through 
> the exchange, but the type converters only read it from the exchange today.
> Tests: {{ConvertBodyTest}} with a {{CamelCharsetName=ISO-8859-1}} header and 
> {{convertBodyTo(String.class, "UTF-8")}} of UTF-8 bytes with non-ASCII text; 
> and a failing {{convertBodyTo(Integer.class, "UTF-16")}} followed by a check 
> that the exchange property is unchanged.
> _Filed with Claude Code on behalf of allthingssecurity._



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

Reply via email to