Skip to content

feat(api): reject unpaired surrogates in protobuf string fields - #7102

Open
halibobo1205 wants to merge 1 commit into
tronprotocol:release_v4.8.3from
halibobo1205:feature/jsonformat-require-valid-utf8
Open

halibobo1205 wants to merge 1 commit into
tronprotocol:release_v4.8.3from
halibobo1205:feature/jsonformat-require-valid-utf8

Conversation

@halibobo1205

Copy link
Copy Markdown
Collaborator

What does this PR do?

Validates HTTP and JSON-RPC values assigned to protobuf string fields, rejecting unpaired surrogates. This aligns validation with the UTF-8 requirement enforced during gRPC/protobuf decoding.

Why are these changes required?

Malformed Unicode is currently accepted and replaced with ? during protobuf serialization. This change validates it explicitly during request handling.

Compatibility changes:

  • Unpaired surrogates in protobuf string values now cause parsing or parameter errors instead of replacement.
  • When packing a transaction, existing logic skips contract parameters that fail to parse; the subsequent result depends on the request's remaining checks.
  • Well-formed Unicode, including emoji, and existing bytes field conversions remain unchanged.

This PR has been tested by:

  • 610 HTTP and JSON-RPC tests pass locally on JDK 17, covering malformed surrogates, error reporting and valid Unicode.
  • Before/after manual checks on a single-node private chain covered malformed strings and valid emoji through HTTP and JSON-RPC. Results matched the expected behavior.
  • Multi-sign was not enabled on the private chain. gRPC was not tested manually.

Follow up

None.

Extra details

Only HTTP and JSON-RPC request handling changes. Transaction validation, transaction execution and block processing are unchanged.

@halibobo1205 halibobo1205 added this to the GreatVoyage-v4.8.3 milestone Nov 11, 2026
@halibobo1205 halibobo1205 added the topic:api rpc/http related issue label Nov 11, 2026

@waynercheung waynercheung left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed commit 0f604c6.

No blocking correctness findings. Validation runs after unescaping and before protobuf string fields are assigned, with separate checks for the HTTP and JSON-RPC deployment-name setters. Valid Unicode and existing bytes conversions are unchanged.

packTransaction still drops contracts whose parameters fail to parse, which matches the compatibility note in the PR description.

[QUESTION] Should rejecting unpaired surrogates in visible=true text inputs to name-string bytes fields, such as account_name, be considered separately? This PR explicitly preserves the existing conversions.

Approved from the code-review perspective. One non-blocking regression-test suggestion is included inline.

}

@Test
public void testStringFieldRejectsUnpairedSurrogates() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NIT] Please add a regression test for Util.packTransaction with an unpaired surrogate in a contract parameter, asserting the documented dropped-contract behavior. A Permission.permission_name case is optional, since it uses the same STRING path already covered here.

@halibobo1205

Copy link
Copy Markdown
Collaborator Author

Reviewed commit 0f604c6.

No blocking correctness findings. Validation runs after unescaping and before protobuf string fields are assigned, with separate checks for the HTTP and JSON-RPC deployment-name setters. Valid Unicode and existing bytes conversions are unchanged.

packTransaction still drops contracts whose parameters fail to parse, which matches the compatibility note in the PR description.

[QUESTION] Should rejecting unpaired surrogates in visible=true text inputs to name-string bytes fields, such as account_name, be considered separately? This PR explicitly preserves the existing conversions.

Approved from the code-review perspective. One non-blocking regression-test suggestion is included inline.

Yes, intentional. This PR covers values bound to protobuf string fields, which protobuf requires to be valid UTF-8 (gRPC already enforces that when it parses a request). With visible=true, the text-valued bytes fields (the name-string entries in HttpSelfFormatFieldName, e.g. account_name, asset name/url, witness url, Note.memo) and extra_data are converted by the HTTP layer itself through ByteString.copyFromUtf8 / String.getBytes, so an unpaired surrogate there still becomes ?, exactly as before. The description lists this under "Not changed".

I kept it out because it is a bytes field, which the protobuf UTF-8 rule doesn't cover, and rejecting it would change the result of many more endpoints (account update, asset issue/update, witness create/update, exchange and market contracts).Happy to track it as a follow-up if we want these fields to reject as well.

@317787106

317787106 commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

[SUGGESTION, non-blocking] Consider a follow-up to reject unpaired surrogates at the remaining text conversion boundaries:

  • JsonFormat.unescapeBytesSelfType: visible=true text fields such as account_name, account_id, asset names/descriptions/URLs, witness URLs and Note.memo.
  • Util.setTransactionExtraData: HTTP extra_data and JSON-RPC extraData when visible=true.
  • Util.getHexString: asset-name and market-pair query parameters when visible=true.
  • Util.parseMethod: function_selector in the three contract-call endpoints.

I reproduced alice\uD800 → alice? and memo\uD800 → memo?; f(\uD800) also produces the same selector as f(?). These paths silently change the supplied text.

Validation should run on the original Java string before encoding or hashing. Checking ByteString.isValidUtf8() afterward cannot detect the replacement. Preserve the existing visible=false hex/binary behavior.

This can remain a follow-up since this PR explicitly preserves existing bytes conversions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:api rpc/http related issue

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants