shashank created CAMEL-25699:
--------------------------------

             Summary: camel-protobuf - converting a message to a Map replaces 
the value of every bytes field with the text of ByteString.toString() (size and 
a shortened, escaped preview), so the data of the field is lost
                 Key: CAMEL-25699
                 URL: https://issues.apache.org/jira/browse/CAMEL-25699
             Project: Camel
          Issue Type: Bug
            Reporter: shashank
            Assignee: shashank


The protobuf data format documents that the result of an unmarshal can be read 
as a {{Map}} ({{exchange.getMessage().getBody(Map.class)}}, the type converter 
{{ProtobufTypeConverter.toMap}} added by CAMEL-14192), and that a {{Map}} can 
be marshalled.

{{ProtobufConverter.convertValueToSuitableFieldType}} (main d46d51c24550, lines 
159-162) handles a {{bytes}} field together with an enum field: {{result = 
value.toString()}}. For an enum that is the name of the constant. For a 
{{bytes}} field the value is a {{com.google.protobuf.ByteString}}, and 
{{ByteString.toString()}} does not return the content; it returns a description 
for logging, for example
{noformat}
<ByteString@3a03464 size=4 contents="\001\002\003\377">
{noformat}
with the identity hash code, the size and an escaped preview that protobuf-java 
shortens for long values. So every {{bytes}} field of the message (also in 
nested messages and repeated fields) reaches the route as such a {{String}}; 
the data of the field cannot be recovered from it, and nothing fails or is 
logged.

The other direction fails loudly: {{ProtobufConverter.toProto}} passes a 
{{byte[]}} value for a {{bytes}} field to {{Builder.setField}} unchanged, and 
protobuf rejects it ({{IllegalArgumentException}}), so there is no {{Map}} form 
of a {{bytes}} field that can be marshalled.

Trigger: any message type with a {{bytes}} field (a common type for binary 
payloads, hashes, ids, encrypted data) and the documented {{Map}} output: 
{{unmarshal().protobuf(...)}} with {{contentTypeFormat=native}} (default) 
followed by {{getBody(Map.class)}} or {{convertBodyTo(Map.class)}}, or any 
other use of the {{Message}} to {{Map}} type converter.

h3. Reproduction

New {{ProtobufBytesFieldMapTest}} with the well-known type 
{{com.google.protobuf.BytesValue}} (one {{bytes}} field named {{value}}, part 
of protobuf-java, so the test protos are not changed), a value of 61 bytes:
* {{ProtobufConverter.toMap}}: on main the value is a {{String}}, not the bytes 
({{ClassCastException: class java.lang.String cannot be cast to class [B}});
* a route {{from("direct:unmarshal").unmarshal(new 
ProtobufDataFormat(BytesValue.getDefaultInstance()))}}, then 
{{getBody(Map.class)}}: the same;
* {{toProto(toMap(message))}}: fails on main ({{IllegalArgumentException: 
argument type mismatch}} from {{setField}}).

With the fix the three tests pass, and the camel-protobuf tests: 19 run, 0 
failures, 0 errors, 0 skipped.

h3. Proposed fix

* {{convertValueToSuitableFieldType}}: a {{bytes}} field becomes 
{{ByteString.toByteArray()}} ({{byte[]}}); enums are unchanged.
* {{getSuitableFieldValue}}: a {{byte[]}} value for a {{bytes}} field is 
wrapped with {{ByteString.copyFrom}}; a {{ByteString}} is passed as before, 
other types fail as before.

Users can notice that the {{Map}} now holds a {{byte[]}} for a {{bytes}} field 
instead of a {{String}}; a short note goes into the 4.24 upgrade guide.

How it was found: reading the data format converters while sweeping byte and 
size handling in data formats (round r29, track H, whose other tools were Z3 
models of retry and back-off arithmetic); the conversion has no arithmetic, so 
there is no model, the tests are the evidence. A small Java probe with 
protobuf-java 4.35.1 (the version of the parent pom) printed {{value 
BYTE_STRING -> <ByteString@3a03464 size=4 contents="\001\002\003\377">}}.

Not changed: an {{int64}} field given an {{Integer}} in the {{Map}} (or a 
{{float}} field given a {{Double}}) is still rejected by protobuf with an 
exception (loud, separate question); map fields stay a list of 
{{key}}/{{value}} maps.

Affected: main (d46d51c24550; tested). camel-4.23.x, camel-4.22.x, camel-4.18.x 
and camel-4.14.x have the same lines 160-162 (read, not run).

Duplicate check (2026-10-16): JIRA text "protobuf" with "ByteString", "bytes" 
or "toMap" (CAMEL-14192, the feature; CAMEL-24170, the July 2026 data format 
review umbrella, whose protobuf items are the JSON charset, the Jackson 
timezone and the class resolver, not this); GitHub pull requests "protobuf 
ByteString", "camel-protobuf map" (nothing related).

_Filed with Claude Code on behalf of allthingssecurity._




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

Reply via email to