btlqql opened a new issue, #4287:
URL: https://github.com/apache/rocketmq-dashboard/issues/4287

   ## 1. Symptom
   
   The message explorer and the DLQ message drawer render message properties 
through
   `MessagePropertyDisplay.limitProperties`, which caps every value at 
`MAX_PROPERTY_VALUE_CHARS`
   (1024) and appends `...`. When that limit falls between the two chars of a 
supplementary
   character (an emoji, or a CJK extension character), the returned value ends 
with an isolated
   high surrogate instead of a code point.
   
   The panel then shows a replacement glyph at the end of an already 
abbreviated value, and the
   JSON body carries an invalid escape (`\uD83D` with no low surrogate).
   
   ## 2. Root cause
   
   
`server/src/main/java/org/apache/rocketmq/studio/common/util/MessagePropertyDisplay.java:74-79`
   
   ```java
       private static String abbreviate(String value) {
           if (value == null || value.length() <= MAX_PROPERTY_VALUE_CHARS) {
               return value;
           }
           return value.substring(0, MAX_PROPERTY_VALUE_CHARS) + "...";
       }
   ```
   
   The cap counts UTF-16 `char`s, the cut is a plain `substring`, and 
`value.charAt(1023)` is a
   high surrogate for the reproduction below, so the result is `1023 ASCII 
chars + U+D83D + "..."`.
   A `char` is not a code point: the string is no longer valid Unicode text.
   
   The same rule is already applied in two other places in the repository, 
which is what makes this
   an inconsistency rather than a deliberate cap: `CredentialUtils.mask` 
documents that it moves to
   a code point boundary "prevents a supplementary character from being split 
into an isolated
   surrogate in API responses", and the web side of this very panel was fixed 
in #4226 ("preserve
   Unicode code points when truncating message properties"). The server side 
that feeds those panels
   still splits the pair.
   
   ## 3. Impact
   
   - `GET /api/messages/<topic>/<msgId>` (built by 
`RocketMQMessageProvider:704`) and the DLQ drawer
     (`RocketMQDLQProvider:402`) both call `limitProperties`, so any message 
property longer than
     1024 chars whose boundary lands inside a supplementary character is 
displayed corrupted.
   - The truncation is not a display-only concern for the JSON contract: the 
value is emitted with a
     lone surrogate escape, which strict consumers reject.
   - `hasOversizedProperty` still reports the value as oversized while the 
abbreviated value does not
     represent a prefix of the original text, so the "value was abbreviated" 
hint is inconsistent
     with what is rendered.
   
   ## 4. Reproduction
   
   Message with a property value of `1023 * "a" + "😀" + "tail"` (1026 UTF-16 
chars), then open the
   message detail. Unit level:
   
   ```java
   String value = "a".repeat(1023) + "\uD83D\uDE00" + "tail";
   MessagePropertyDisplay.limitProperties(Map.of("k", 
value)).get("k").charAt(1023); // 0xD83D, unpaired
   ```
   
   ## 5. Expected behaviour
   
   - The abbreviated value never ends (or starts) inside a surrogate pair: the 
cap backs off one char
     when the char at the limit starts a pair.
   - A pair that fits inside the cap is still kept in full (`1022 * "a" + "😀"` 
stays intact).
   - Values within the cap and the `MAX_PROPERTIES` entry cap are unchanged, as 
is the `...` marker
     and `hasOversizedProperty`.


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