Aias00 opened a new issue, #7458:
URL: https://github.com/apache/shenyu/issues/7458

   ## Is there an existing issue for this?
   
   - [x] I searched open and closed issues.
   
   ## Current Behavior
   
   MQTT retained binary payloads are changed when replayed to later 
subscribers. The retained path converts raw bytes to a Java String using the 
JVM default charset, stores that String, and rebuilds the replayed payload as 
UTF-8.
   
   On a UTF-8 JVM, retained bytes `00 FF 80 41` become `00 EF BF BD EF BF BD 
41`. The invalid UTF-8 bytes are replaced with Unicode replacement characters, 
so replay is not byte-preserving. A valid UTF-8 text control is unchanged.
   
   ## Expected Behavior
   
   Retained messages must preserve the application payload as opaque bytes. 
MQTT 3.1.1 section 3.3.3 states that PUBLISH payload content and format are 
application-specific; it does not require UTF-8 text:
   
   
https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc384800413
   
   ## Steps To Reproduce
   
   1. Publish a retained MQTT message whose payload is `00 FF 80 41`.
   2. Establish a later subscription matching the topic.
   3. Inspect the retained PUBLISH payload received by that subscriber.
   4. Observe the UTF-8 replacement bytes instead of the original four bytes.
   
   An offline production-method reproduction used Netty EmbeddedChannel, actual 
Publish.publish(), TopicRepository and Subscribe.subscribe(). The leader 
recompiled current source and tested a QoS 1 retained publication; subscriber 
delivery QoS remains separate from the byte-corruption claim. The harness 
selects the frame whose RETAIN flag is true, avoiding confusion with live 
asynchronous fan-out.
   
   ```text
   defaultCharset=UTF-8
   utf8-control.original=[99,111,110,116,114,111,108]
   utf8-control.replayed=[99,111,110,116,114,111,108]
   utf8-control.bytesEqual=true
   binary.original=[0,-1,-128,65]
   binary.replayed=[0,-17,-65,-67,-17,-65,-67,65]
   binary.bytesEqual=false
   ```
   
   ## Location And Impact
   
   - 
[Publish.java:58](https://github.com/apache/shenyu/blob/67596c1d228b62da75cd0a0ecb47d0ac5d995384/shenyu-protocol/shenyu-protocol-mqtt/src/main/java/org/apache/shenyu/protocol/mqtt/Publish.java#L58):
 retained data is converted to a String.
   - 
[Publish.java:117](https://github.com/apache/shenyu/blob/67596c1d228b62da75cd0a0ecb47d0ac5d995384/shenyu-protocol/shenyu-protocol-mqtt/src/main/java/org/apache/shenyu/protocol/mqtt/Publish.java#L117):
 conversion uses default charset.
   - 
[TopicRepository.java:31](https://github.com/apache/shenyu/blob/67596c1d228b62da75cd0a0ecb47d0ac5d995384/shenyu-protocol/shenyu-protocol-mqtt/src/main/java/org/apache/shenyu/protocol/mqtt/repositories/TopicRepository.java#L31):
 storage is Map<String,String>.
   - 
[Subscribe.java:113](https://github.com/apache/shenyu/blob/67596c1d228b62da75cd0a0ecb47d0ac5d995384/shenyu-protocol/shenyu-protocol-mqtt/src/main/java/org/apache/shenyu/protocol/mqtt/Subscribe.java#L113):
 replay encodes the String as UTF-8.
   
   Severity: Medium. Confidence: high. Binary sensor/protobuf/application 
payloads can no longer be decoded or interpreted correctly by later 
subscribers, even though textual payloads appear to work.
   
   ## Suggested Fix And Regression Coverage
   
   Retain an owned copy of the original readable payload bytes and replay those 
bytes directly. Prefer byte storage over decoding to text; if reference-counted 
buffers are retained, define ownership and cleanup for replacement/deletion 
explicitly.
   
   Test text and arbitrary binary retained payloads byte-for-byte, including 
sliced buffers/nonzero reader offsets, replacement and zero-byte retained 
deletion. Preserve live fan-out behavior.
   
   ## Validation And Related Issues
   
   Reviewed master `67596c1d228b62da75cd0a0ecb47d0ac5d995384` 
(`2.7.2-SNAPSHOT`). An isolated verifier and leader current-source reproduction 
confirmed corruption. Existing PublishTest/SubscribeRepositoryTest: 24 tests 
passed, without this binary replay case.
   
   #6848 concerns SUBACK grants, #6850 live fan-out QoS/packet IDs, #6849 
retain-bit/zero-byte deletion, and #6639 pooled buffer ownership. None 
describes this retained payload text conversion. No matching binary-retained 
issue was found.
   
   No live broker or network request was used. This issue does not claim that 
QoS 0 replay is wrong when SUBACK actually grants QoS 0.
   


-- 
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]

Reply via email to