Repository navigation
fix(common): stop the HTML-escape removal from corrupting escaped backslashes - #1293
Merged
Merged
Conversation
…kslashes removeHtmlEscaping replaced every HTML escape it could match in the printed protobuf JSON, without looking at whether the sequence was itself escaped. A message text holding a literal backslash followed by the characters "u003c" is printed by JsonFormat as "\\u003c"; the replacement started at the second backslash, so the body carried "\<", which is not valid JSON: MalformedJsonException: Invalid escape sequence at line 7 column 22 path $.message.parts[0].text The scan now copies an escaped backslash as it is and rewrites a six-character escape only when no backslash precedes it, so both the value and the escape removal survive. Fixes 1292
Collaborator
|
Thank you @WMK666666 :-) |
This was referenced Nov 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1292
Problem
HtmlEscapeUtils.removeHtmlEscapingremoves the HTML escapesJsonFormatadds by replacing every\u003c,\u003e,\u0026,\u003dand\u0027in the printed document with its character, usingString.replaceon the whole string. It never asks whether the sequence it matched was itselfescaped.
JsonFormatprints a message text that really contains those characters as"\\u003c"— twobackslashes for the literal one, then the text
u003c. The replacement starts at the secondbackslash, so the body becomes
"\<":That is not valid JSON, and
ProtoJsonUtils.toJsonhands it straight to the transport, so the clientcannot parse a reply the server believes it serialized correctly:
Any agent that echoes code, a regex, or a note about an escape sequence hits this. The fix lands in
common, the one place bothspec-grpc.ProtoJsonUtilsandcompat-0.3's copy call, so the twopaths are fixed together.
Change
removeHtmlEscapingnow walks the document instead of replacing substrings:\\) is copied as is, so the value behind it is never mistaken for an escape;\u00XXsequence is rewritten only when it is not preceded by a backslash, andonly for the five HTML characters — anything else (
\n,\u00e9, …) is copied verbatim;alone, as documented.
For anything that has no HTML escape the method returns the input unchanged, so the fast path is the
same as before.
Tests
HtmlEscapeUtilsTest.removeHtmlEscaping_leavesAnEscapedBackslashBeforeUEscapeAlone— a value holdinga literal backslash followed by
u003ccomes back untouched (red on main:but was: <{"text":"a\< b"}>).HtmlEscapeUtilsTest.removeHtmlEscaping_restoresTheEscapeAfterAnEscapedBackslash— a literalbackslash followed by a real
<escape keeps the escaped backslash and drops the escape (a\\<b);this one passes before and after, as a guard that the two cases stay distinguishable.
ProtoJsonUtilsTest.toJson_keepsALiteralBackslashBeforeUEscapeInMessageText— builds aSendMessageParamswhoseTextPartcarries that text, prints it throughProtoJsonUtils.toJson,and reads the body back with
JsonFormat.parser(). On main this fails with theMalformedJsonExceptionabove, i.e. the assertion is on the produced document, not on a stringcomparison.
Full module tests for
common,spec-grpc,jsonrpc-commonandcompat-0.3/spec-grpc:common16,spec163,jsonrpc-common100,spec-grpc130,compat-0.3/spec53,compat-0.3/spec-grpc25 — 487 tests, 0 failures, 0 errors,BUILD SUCCESS.spotless:checkon Windows flags 12 files of thecommonmodule, but an untouched checkoutreports the same 12 (line-ending artifact), so that is not something this change introduced;
the formatting follows the file's existing style and stays within 100 columns.
Notes
compat-0.3/spec-grpchas its ownProtoJsonUtils_v0_3, but it delegates to the sameHtmlEscapeUtils, so no change is needed there.