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]